标签:
我们已经能够存储单首音乐了,接下来我们开始添加一次存储多首音乐的界面设计。
当用户长按某首音乐项的时候,将进入ListView的多选modal状态
,我们叫它模式框。
在理解这个模式框
之前,我们要先进一步了解一下ListView
。
ListView
本身带有单选和多选功能,也就是说在单选模式下,它能够记住当前选中的唯一的列表项;在多选模式下,它能够记住目前选取的所有的列表项。
这种选择模式共有4种CHOICE_MODE_NONE
CHOICE_MODE_SINGLE
CHOICE_MODE_MULTIPLE
CHOICE_MODE_MULTIPLE_MODAL
。
使用setChoiceMode()
函数,就可以设置ListView
的选择模式。
ListView lv = (ListView) findViewById(R.id.list_view);
lv.setChoiceMode(ListView.CHOICE_MODE_NONE);
这是ListView
默认的选择模式,当使用者点击列表项后,不会将任何点击的列表项当成被选择上的列表项。
使用这个选项模式,当使用者点击列表项后,会将最后一次点击的列表项当成被选择上的列表项。
ArrayAdapter adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_single_choice , datalist);
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lv.setAdapter(adapter);
每次点击列表项,可以在它的监听函数中得知哪个列表项被点击了,
lv.setOnItemClickListener(new ListView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//添加需要响应的操作
}
}
以后就可以通过ListView
的getCheckedItemPositions()
获取被选中的数据项的位置列表,
SparseBooleanArray checkedItems = lv.getCheckedItemPositions();
例如,当列表项按照序号为3->2->1-7
的顺序被点击后,7
将被记录下来,作为当前被选中的数据项。调用getCheckedItemPositions()
后,将得到一个键值对,里面只会记录,
key=7, value=true
这里为了看到被选中的效果,采用了Android SDK提供的android.R.layout.simple_list_item_single_choice
布局,作为列表项的布局。
使用这个选项模式,当使用者点击列表项后,会将所有点击的列表项当成被选择上的列表项。
ArrayAdapter adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_multiple_choice, datalist);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lv.setAdapter(adapter);
每次点击列表项,可以在它的监听函数中得知哪个列表项被点击了,
lv.setOnItemClickListener(new ListView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//添加需要响应的操作
}
}
通过ListView
的getCheckedItemPositions()
获取被选中的数据项的位置列表,
SparseBooleanArray checkedItems = lv.getCheckedItemPositions();
例如,当列表项按照序号为3->2->1->7
的顺序被点击后,3 2 1 7
将被记录下来,作为当前被选中的数据项。调用getCheckedItemPositions()
后,将得到一个个键值对,里面会记录,
key=1, value=true
key=2, value=true
key=3, value=true
key=7, value=true
这些记录,将按照列表项的位置从小到大排列。
如果用户在已经被选上的数据项上,又再次点击,这将取消对它的选择。例如,当列表项按照序号为3->2->1->7->2->1
的顺序被点击后,就变成了,
key=1, value=false
key=2, value=false
key=3, value=true
key=7, value=true
对于被取消了选择的列表项,并不会从记录中移除,而是改变它的值成false
。
这里为了看到被选中的效果,采用了Android SDK提供的android.R.layout.simple_list_item_multiple_choice
布局,作为列表项的布局。
在CHOICE_MODE_MULTIPLE_MODAL
模式中,用户必须通过长按任意一个列表项,进入多选模式,否则不能进行多选。
这个模式的使用与CHOICE_MODE_MULTIPLE
类似,不过它需要设置一个ActionMode
,这样才能在长按列表项后,改变ActionBar
的菜单栏,打开多选的菜单。
实现ListView
的MultiChoiceModeListener
接口,
private class MyMultiChoiceModeListener implements ListView.MultiChoiceModeListener {
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
//添加列表项被点击后的响应
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
//这里返回true
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
//这里返回true
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
//这里返回true
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
}
使用创建的接口,传递给ListView
,
ArrayAdapter adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_multiple_choice, datalist);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
ListView.MultiChoiceModeListener callback = new MyMultiChoiceModeListener();
lv.setMultiChoiceModeListener(callback);
lv.setAdapter(adapter);
在CHOICE_MODE_MULTIPLE_MODAL
模式下,对列表项的点击,是在ListView.MultiChoiceModeListener
的onItemCheckedStateChanged()
函数中响应的。
这里为了看到被选中的效果,采用了Android SDK提供的android.R.layout.simple_list_item_multiple_choice
布局,作为列表项的布局。
前面的演示中,分别对不同的选择模式,使用了不同的数据项布局,
CHOICE_MODE_SINGLE --> android.R.layout.simple_list_item_single_choice
CHOICE_MODE_MULTIPLE --> android.R.layout.simple_list_item_multiple_choice
CHOICE_MODE_MULTIPLE_MODAL --> android.R.layout.simple_list_item_multiple_choice
我们也可以选择自己的布局来实现。但是不管使用什么布局,我们都希望被选上的列表项有特别的效果,和其他没有被选上的数据项区别开。这里有两种方案,
使用实现了Clickable
接口的控件或者布局,作为数据项的布局。例如前面我们使用的android.R.layout.simple_list_item_multiple_choice
android.R.layout.simple_list_item_single_choice
等,它们本身就是CheckedTextView
。当点击它们的时候,它们就自带了勾选框,可以看到效果。
所以,可以选择CheckBox
Switch
这类同样实现了Clickable
接口的布局来表现;也可以自定义一个实现了Clickable
接口的布局。这里用android.R.layout.simple_list_item_multiple_choice
的实现来举个例子,
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
给数据项的布局使用一个Selector
,告诉这个布局,当它被activated
以后要怎么显示。比如,定义一个布局custom_item_layout.xml
,
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp" --> 为了布局好看设置一个最小高度
android:gravity="center_vertical"
android:padding="5dp"
android:background="@drawable/selector">
</TextView>
给这个布局设计一个selector
,增加对android:activated
属性的设置,
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:drawable="@color/yellow"/>
</selector>
使用这个这个布局,
ArrayAdapter adapter = new ArrayAdapter<String>(this,
R.layout.custom_item_layout, datalist);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lv.setAdapter(adapter);
当我们多选的时候,那些选中项,就变成黄色,看到如下的界面,
接下来,我们将上面学到的方法应用到我们当前的项目中。
创建music_choice_actionbar.xml
菜单项,
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:title="@string/play"
android:id="@+id/menu_play"/>
</menu>
定义一个MultiChoiceModeListener
,将菜单项和菜单项被点击后的响应添加进去,
private ListView.MultiChoiceModeListener mMultiChoiceListener = new AbsListView.MultiChoiceModeListener() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
//增加进入modal模式后的菜单栏菜单项
getMenuInflater().inflate(R.menu.music_choice_actionbar, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch(item.getItemId()) {
case R.id.menu_play: {
//这里添加点击添加到播放列表后的响应
}
break;
}
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
}
};
将音乐列表设置成多选modal
模式,
public class MusicListActivity extends AppCompatActivity {
......
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_list);
mMusicList = new ArrayList<MusicItem>();
mMusicListView = (ListView) findViewById(R.id.music_list);
MusicItemAdapter adapter = new MusicItemAdapter(this, R.layout.music_item, mMusicList);
mMusicListView.setAdapter(adapter);
mMusicListView.setOnItemClickListener(mOnMusicItemClickListener);
//设置多选modal模式
mMusicListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL);
//设置多选模式变化的监听器
mMusicListView.setMultiChoiceModeListener(mMultiChoiceListener);
}
......
}
为了便于观察哪些音乐处于多选状态,我们让被选择的数据项处于高亮状态,
在res\drawable
目录下,定义一个高亮的selector
-menu_item_selector
,
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:drawable="@color/colorHighlight"/>
</selector>
给音乐项的布局文件music_item.xml
设置上高亮的selector
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/menu_item_selector">
<ImageView>
......
</ImageView>
<LinearLayout>
......
</LinearLayout>
</LinearLayout>
增加添加到播放列表
的功能,
private ListView.MultiChoiceModeListener mMultiChoiceListener = new AbsListView.MultiChoiceModeListener() {
......
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch(item.getItemId()) {
case R.id.menu_play: {
//获取被选中的音乐项
List musicList = new ArrayList<MusicItem>();
SparseBooleanArray checkedResult = mMusicListView.getCheckedItemPositions();
for (int i = 0; i < checkedResult.size(); i++) {
if(checkedResult.valueAt(i)) {
int pos = checkedResult.keyAt(i);
MusicItem music = mMusicList.get(pos);
musicList.add(music);
}
}
//调用MusicService提供的接口,把播放列表保存起来
mMusicService.addPlayList(musicList);
//退出ListView的modal状态
mode.finish();
}
break;
}
return true;
}
......
};
现在长按数据项,点击看看,已经能够成功的把选上的音乐添加到播放列表了。
/*******************************************************************/
* 版权声明
* 本教程只在CSDN和安豆网发布,其他网站出现本教程均属侵权。
*另外,我们还推出了Arduino智能硬件相关的教程,您可以在我们的网店安豆的杂货铺中购买相关硬件。同时也感谢大家对我们这些码农的支持。
*最后再次感谢各位读者对安豆
的支持,谢谢:)
/*******************************************************************/
标签:
原文地址:http://blog.csdn.net/anddlecn/article/details/52705534