《android权威编程指南》的学习
在实现本书中criminalintent应用时,想用onCreateContextMenu长按菜单来实现记录的删除、添加等功能
1.onCreateContextMenu的创建
我实现的是长按每条记录的整体视图弹出菜单(即这个视图中的任意位置),而不是视图中的某个控件。首先建立监听器。
代码1-1:
public CrimeHolder(View itemView){
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnCreateContextMenuListener(new
View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu contextMenu, View v, ContextMenu.ContextMenuInfo contextMenuInfo) {
contextMenu.setHeaderTitle("选择操作");
contextMenu.add(0,0,0,R.string.crime_delete);
//或者contextMenu.add(0,0,0,"删除");
contextMenu.add(0,1,0,"添加");
mId=mCrime.getId();
}
});
2.为每个事件添加处理过程
通过覆盖onContextItemSelected(MenuItem item)方法来实现,关于添加事件书中有详细的代码及讲解(p223),这里我们主要说明一下删除。先看一下代码1-2:
@Override
public boolean onContextItemSelected(MenuItem item){
switch (item.getItemId()){
//添加事件的处理
case 1:
Crime crime=new Crime();
CrimeLab.get(getActivity()).addCrime(crime);
Intent intent=CrimePagerActivity
.newIntent(getActivity(),crime.getId());
startActivity(intent);
return true;
//删除事件的处理
case 0:
mChanged= CrimeLab.get(getActivity()).getPosition(mId);
CrimeLab.get(getActivity()).deleteCrime(mChanged);
updateUI();
return true;
default:
return super.onContextItemSelected(item);
}
}
mchanged是我在CrimeListFragment中定义的一个int私有变量:
private int mChanged;
此变量用来实现从CrimeFragment中得到被改变过时间与日期等信息的fragment的编号,然后在CrimeListFragment中刷新,之前本书中要求我们用
mAdapter.notifyItemChanged(mChanged);来实现刷新被改变的具体条目而不是用
mAdapter.notifyDataSetchanged();全部刷新。其实任意的int型变量都可以用来作为我们要删除的条目的编号,之所以在这里用到mChanged,是因为我们删除掉之后必须更新一下我们的视图才能显示出效果(见代码1-2中删除事件的updateUI()方法),而在updateUI中:
private void updateUI(){
CrimeLab crimeLab=CrimeLab.get(getActivity());
List<Crime> crimes=crimeLab.getCrimes();
if(mAdapter==null) {
mAdapter = new CrimeAdapter(crimes);
mCrimeRecyclerView.setAdapter(mAdapter);
}else{
mAdapter.notifyItemChanged(mChanged);
}
updateSubtitle();
}
如果只是长按菜单,就没有实现CrimeListFragement与CrimeFragment的通信,故mChanged就没有实际的值,app会报错。
好了,那么现在如何得到我们长按的那个条目的编号呢?
见代码1-1中: mId=mCrime.getId();mId是定义的一个UUID变量。
在crimeLab中我增加了两个方法:
//得到当前id对应的crime在列表中的编号
public int getPosition(UUID id){
for(Crime crime:mCrimes){
if(crime.getId().equals(id)){
return mCrimes.indexOf(crime);
}
}
return 0;
}
//列表的对应编号的crime的删除
public void deleteCrime(int position){mCrimes.remove(position);}
点击运行,即可看见效果。
3.关于建立菜单的知识整合
1
注意:onContextItemSelected的实现方法是onContextItemSelected,它只能在Activity中响应!!
即:一定要是一个Activity去实现这个ListView,假如是其他的组件比如Dialog,Dialog.setContentView(ListView) 然后再去设置它的onContextItemSelected就无法被响应。
- 2
onCreateOptionsMenu :此方法为创建菜单方法,这个菜单就是你在点击手机menu键时会看到的菜单。
onCreateContextMenu :此方法为创建菜单方法,你还需要对此菜单进行注册Activity.registerForContextMenu(View view),这个菜单是在你长按前面注册的view时看到的菜单。
onMenuItemSelected :当你选择上面两种菜单任意一种时都会触发这个事件。
onOptionsItemSelected :这个方法只在onCreateOptionsMenu 创建的菜单被选中时才会被触发。
onContextItemSelected :这个方法只在onCreateContextMenu 创建的菜单被选中时才会被触发。
注:关于 onMenuItemSelected 与 onContextItemSelected的区别(此问题我暂时没遇到):
查阅于别人的博客,大致意思为:当同时使用这两个方法时,由于优先级的问题,onMenuItemSelected会先被调用,如果我们需要的菜单不在其中是就会返回false,并且没有执行onContextItemSelected.解决方法为:在onMenuItemSelected中添加语句当在某个特定的条件时,就调用onContextItemSelected.