在Toolbar中放置Spinner
Author: nex3z
2016-04-17
在展示列表时,可以通过在Toolbar中放置Spinner的形式,提供对列表进行过滤和分类的功能。本文在RecyclerView使用方法举例(2)的基础上,为Toolbar添加一个用于选择电影排序方法的Spinner,如图1所示。

图1
0. 关于排序字符串的处理
之前在MovieService.java中定义了三种排序方式:按照流行度降序、按照投票平均分降序、按照投票量降序,如下所示:
String SORT_BY_POPULARITY_DESC = "popularity.desc";
String SORT_BY_VOTE_AVERAGE_DESC = "vote_average.desc";
String SORT_BY_VOTE_COUNT_DESC = "vote_count.desc";
String SORT_BY_POPULARITY_DESC = "popularity.desc";
String SORT_BY_VOTE_AVERAGE_DESC = "vote_average.desc";
String SORT_BY_VOTE_COUNT_DESC = "vote_count.desc";
String SORT_BY_POPULARITY_DESC = "popularity.desc";
String SORT_BY_VOTE_AVERAGE_DESC = "vote_average.desc";
String SORT_BY_VOTE_COUNT_DESC = "vote_count.desc";
【完整文件】
对应这三种排序方式,在res/values/array.xml中定义字符串数组,用于显示:
<string-array name="sort_array">
<item>Vote Average</item>
<resources>
<string-array name="sort_array">
<item>Popularity</item>
<item>Vote Average</item>
<item>Vote Count</item>
</string-array>
</resources>
<resources>
<string-array name="sort_array">
<item>Popularity</item>
<item>Vote Average</item>
<item>Vote Count</item>
</string-array>
</resources>
【完整文件】
1. 添加Spinner
首先在Toolbar中添加Spinner,直接把Spinner放置在Toolbar里面即可:
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" >
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.v7.widget.Toolbar>
...
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" >
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.v7.widget.Toolbar>
...
...
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" >
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.v7.widget.Toolbar>
...
【完整文件】
2. 配置Spinner
2.1. 禁止显示Toolbar标题
首先设置Toolbar不显示标题,否则Spinner会被标题挤到旁边:
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new MainActivityFragment())
public class MainActivity extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new MainActivityFragment())
.commit();
}
...
}
public class MainActivity extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new MainActivityFragment())
.commit();
}
...
}
由于列表的显示逻辑位于MainActivityFragment ,所以之后对Spinner点击事件的处理也要由它完成,MainActivityFragment需要获取位于MainActivity的Spinner的实例。注意上面使用了FragmentManager来添加MainActivityFragment,这样之后在MainActivityFragment中,就可以通过(Spinner) getActivity().findViewById(R.id.spinner) 获取Spinner;如果只是在layout中定义MainActivityFragment位于MainActivity的布局里,那么之后在MainActivityFragment中调用(Spinner) getActivity().findViewById(R.id.spinner) 只会返回null 。
【完整文件】
2.2. 配置Spinner
这里Spinner的使用方法并没有不同:
Spinner spinner = (Spinner) getActivity().findViewById(R.id.spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(),
R.array.sort_array, R.layout.spinner_item);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
spinner.setAdapter(adapter);
Spinner spinner = (Spinner) getActivity().findViewById(R.id.spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(),
R.array.sort_array, R.layout.spinner_item);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
spinner.setAdapter(adapter);
Spinner spinner = (Spinner) getActivity().findViewById(R.id.spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(),
R.array.sort_array, R.layout.spinner_item);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
spinner.setAdapter(adapter);
在创建ArrayAdapter时,sort_array 是之前定义的用于显示的字符串数据,spinner_item 是收缩状态时的布局(如2中红框),而setDropDownViewResource() 用到的spinner_dropdown_item 是下拉状态时的布局(如3中红框)。

图2

图3
spinner_item 的定义见这里,粘贴并修改自Android自带的android.R.layout.simple_spinner_item,spinner_dropdown_item 的定义见这里,粘贴并修改自Android自带的android.R.layout.simple_spinner_dropdown_item。
2.3. 处理Spinner事件
当Spinner中的item被点击时,可以通过position来选择对应的排序方式:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mSort = MovieService.SORT_BY_POPULARITY_DESC;
mSort = MovieService.SORT_BY_VOTE_AVERAGE_DESC;
mSort = MovieService.SORT_BY_VOTE_COUNT_DESC;
fetchInitialMovies(mSort);
public void onNothingSelected(AdapterView<?> parent) {}
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (position) {
case 0:
mSort = MovieService.SORT_BY_POPULARITY_DESC;
break;
case 1:
mSort = MovieService.SORT_BY_VOTE_AVERAGE_DESC;
break;
case 2:
mSort = MovieService.SORT_BY_VOTE_COUNT_DESC;
break;
}
fetchInitialMovies(mSort);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (position) {
case 0:
mSort = MovieService.SORT_BY_POPULARITY_DESC;
break;
case 1:
mSort = MovieService.SORT_BY_VOTE_AVERAGE_DESC;
break;
case 2:
mSort = MovieService.SORT_BY_VOTE_COUNT_DESC;
break;
}
fetchInitialMovies(mSort);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
【完整文件】
3. 完整代码
完整代码可以参考这里。