标签:
ConversationFragment的布局:
首先我们找到我们要写的Fragment布局文件。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@+id/lv_conversation_list" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </ListView> <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:background="@drawable/bg_conversion_menu" android:gravity="center" android:orientation="horizontal" android:paddingLeft="30dp" android:paddingRight="30dp" > <Button android:id="@+id/bt_edit" android:layout_width="0dp" android:layout_height="30dp" android:layout_marginEnd="30dp" android:layout_weight="1" android:background="@drawable/selector_bt_bg" android:text="编辑" style="?android:attr/buttonBarButtonStyle" /> <Button android:id="@+id/bt_newSms" android:layout_width="0dp" android:layout_height="30dp" android:layout_weight="1" android:background="@drawable/selector_bt_bg" android:text="新建短信" style="?android:attr/buttonBarButtonStyle"/> </LinearLayout> </LinearLayout>
我们为了给button设置点击的时候变换背景图片。
我们需要在res文件夹下面创建一个drawable的文件夹。然后创建一个selector文件作为设置我们动态的图片设置。
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:drawable="@drawable/bg_btn_normal" android:state_pressed="false"></item> <item android:drawable="@drawable/bg_btn_pressed" android:state_pressed="true"></item> </selector>
比如我们设置这两个是在按下的时候,或者没有按下的时候显示不同的背景图片。
我们为了实现点击编辑出现另外一组菜单。
我们应该先显示一组在界面上,我们可以给linearLayout设置这样一个属性。
android:visibility="gone"让当前你设置的这个菜单不可见。
但是我们应该使用动画去实现它,所以我们不能直接使用gone去让这个菜单直接消失。
我们应该使用一个RelativeLayout让这两个控件叠加在一起。
<RelativeLayout android:layout_width="match_parent" android:layout_height="60dp" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg_conversion_menu" android:gravity="center" android:orientation="horizontal" android:paddingLeft="30dp" android:paddingRight="30dp" > <Button android:id="@+id/bt_edit" style="?android:attr/buttonBarButtonStyle" android:layout_width="0dp" android:layout_height="30dp" android:layout_marginEnd="30dp" android:layout_weight="1" android:background="@drawable/selector_bt_bg" android:text="编辑" /> <Button android:id="@+id/bt_newSms" style="?android:attr/buttonBarButtonStyle" android:layout_width="0dp" android:layout_height="30dp" android:layout_weight="1" android:background="@drawable/selector_bt_bg" android:text="新建短信" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg_conversion_menu" android:gravity="center" android:orientation="horizontal" android:paddingLeft="15dp" android:paddingRight="15dp" android:translationY="60dp" > <Button style="?android:attr/buttonBarButtonStyle" android:layout_width="0dp" android:layout_height="30dp" android:layout_marginEnd="15dp" android:layout_weight="1" android:background="@drawable/selector_bt_bg" android:text="取消" /> <Button style="?android:attr/buttonBarButtonStyle" android:layout_width="0dp" android:layout_height="30dp" android:layout_marginEnd="15dp" android:layout_weight="1" android:background="@drawable/selector_bt_bg" android:text="取消选择" /> <Button style="?android:attr/buttonBarButtonStyle" android:layout_width="0dp" android:layout_height="30dp" android:layout_weight="1" android:background="@drawable/selector_bt_bg" android:text="删除" /> </LinearLayout> </RelativeLayout>
——————————————————————
菜单动画的实现:
当我们点击编辑按钮的时候:会实现选择菜单变回原来的位置,当前的编辑菜单向下移出屏幕。
public class ConversionFragment extends BaseFragment { private Button bt_conversation_edit; private Button bt_conversation_newSms; private Button bt_conversation_selectAll; private Button bt_conversation_cancel; private Button bt_conversation_delete; private LinearLayout ll_conversation_edit; private LinearLayout ll_conversation_select; @Override public View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_conversation, null); bt_conversation_edit = (Button) view .findViewById(R.id.bt_conversation_edit); bt_conversation_newSms = (Button) view .findViewById(R.id.bt_conversation_newSms); bt_conversation_selectAll = (Button) view .findViewById(R.id.bt_conversation_selectAll); bt_conversation_cancel = (Button) view .findViewById(R.id.bt_conversation_cancel); bt_conversation_delete = (Button) view .findViewById(R.id.bt_conversation_delete); ll_conversation_edit = (LinearLayout) view .findViewById(R.id.ll_conversation_edit); ll_conversation_select = (LinearLayout) view .findViewById(R.id.ll_conversation_select); return view; } @Override public void initListener() { bt_conversation_edit.setOnClickListener(this); bt_conversation_newSms.setOnClickListener(this); bt_conversation_selectAll.setOnClickListener(this); bt_conversation_cancel.setOnClickListener(this); bt_conversation_delete.setOnClickListener(this); } @Override public void initData() { } @Override public void processClick(View v) { switch (v.getId()) { case R.id.bt_conversation_edit: showSelectMenu(); break; case R.id.bt_conversation_cancel: showEditMenu(); break; } } private void showEditMenu() { ViewPropertyAnimator.animate(ll_conversation_select).translationY(ll_conversation_edit.getHeight()).setDuration(200); new Handler().postDelayed(new Runnable() { @Override public void run() { ViewPropertyAnimator.animate(ll_conversation_edit).translationY(0).setDuration(200); } }, 200); } private void showSelectMenu() { ViewPropertyAnimator.animate(ll_conversation_edit).translationY(ll_conversation_edit.getHeight()).setDuration(200); new Handler().postDelayed(new Runnable() { @Override public void run() { ViewPropertyAnimator.animate(ll_conversation_select).translationY(0).setDuration(200); } }, 200); } }
我们给tanslationY(0)设置为0是因为我们默认给他设置已经移动到屏幕外,设置0的意思就是让这个控件回到原来的位置。
————————————————————————————
看源码分析如何查会话:
我们要先去看看源码怎么查询会话,发现他是在sms的conversations这个uri进行查询的
所以我们定义一个常量类去设置这个uri常量。
public class ConstantValues { public interface URI{ Uri URI_SMS_CONVERSATION=Uri.parse("content://sms//conversations"); } }
我们在Fragment里面的initData方法里面我们这样去查询
public void initData() { getActivity().getContentResolver().query(ConstantValues.URI.URI_SMS_CONVERSATION, null, null, null, null); }
看完源码我们发现他内部其实是这样进行查询的
查询到的结果是这样的
也就是说他能查询到最新的一条会话,和这个会话的id 还有这个id一共有多少条短信。
记住查询需要读短信的权限。
————————————————————————————
异步查询会话:
我们首先要先去查询你的Cursor里面有多少个数据。
我们定义一个CursorUtils去查询你的cursor里面的数据
public void initData() { Cursor cursor = getActivity().getContentResolver().query(ConstantValues.URI.URI_SMS_CONVERSATION, null, null, null, null); CursorUtils.printCursor(cursor); }
public class CursorUtils { public static void printCursor(Cursor cursor){ LogUtils.i("sys", "条数:"+cursor.getCount()); while (cursor.moveToNext()) { for (int i = 0; i < cursor.getColumnCount(); i++) { String name=cursor.getColumnName(i); String content=cursor.getString(i); LogUtils.i("sys", name+":"+content); } LogUtils.i("sys", "++++++++++++++++++++++++++++++"); } } }
异步处理我们可以使用去new 一个子线程。但是每次都去创建子线程这样会让你的代码变得不工整。
所以我们直接创建一个类,这个类就是专门用于处理异步查询。
由于我们对数据库操作,所以创建一个dao包。
然后创建一个AsyncQueryHandler类进行异步查询。
public class SimpleQueryHandler extends AsyncQueryHandler { public SimpleQueryHandler(ContentResolver cr) { super(cr); } }
SimpleQueryHandler queryHandler = new SimpleQueryHandler(getActivity().getContentResolver()); queryHandler.startQuery(token, cookie, uri, projection, selection, selectionArgs, orderBy);
token和cookie是用来传递对象用的,一个是int 和object类型.
这个异步查询是没有返回值的,所以我们可以去他的类里面调用 方法去获取他的返回值,然后再去获取他的查询内容。
public class SimpleQueryHandler extends AsyncQueryHandler { //这个方法就是用来接收刚刚传递的两个参数,当查询完成的时候调用 @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { super.onQueryComplete(token, cookie, cursor); } }
————————————————————————————
创建CursorAdapter:
这个类是BaseAdapter的一个子类。
为什么我们不直接用BaseAdapter,而用CursorAdapter.
因为我们的BaseAdapter的使用集合比较多。
然后List如果你先显示三个数据。然后你再add一个数据,他并不会显示到listView上面。
你需要刷新才能显示上去。
所以我们使用CursorAdapter 它有一个方法是notifyDataSetChanged();可以用来刷新数据当你的数据改变的时候。
CursorAdapter 专门用来显示数据库数据的
public class ConversationListAdapter extends CursorAdapter { public ConversationListAdapter(Context context, Cursor c, int flags) { super(context, c, flags); } //返回的view对象是就是listview的条目getView() @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { // TODO Auto-generated method stub return null; } //设置Listview每个条目显示的内容 @Override public void bindView(View view, Context context, Cursor cursor) { // TODO Auto-generated method stub } }
记住CursorAdapter不是v4包下的。
我们这里先把自己创建的CursorAdapter的子类创建出来。
@Override public void initData() { ConversationListAdapter adapter = new ConversationListAdapter(getActivity(), null); lv_conversation_list.setAdapter(adapter); SimpleQueryHandler queryHandler = new SimpleQueryHandler(getActivity().getContentResolver()); queryHandler.startQuery(0, adapter, ConstantValues.URI.URI_SMS_CONVERSATION, null, null, null, null); /* Cursor cursor = getActivity().getContentResolver().query(ConstantValues.URI.URI_SMS_CONVERSATION, null, null, null, null); CursorUtils.printCursor(cursor);*/ }
这里我们给构造函数 设置context为getActivity();给cursor设置为null
因为我们是在查询完成的时候才能获取到cursor对象。
所以我们给第二个参数设置为adapter 让他传递进去,然后在完成查询的时候给他设置cursor。
public class SimpleQueryHandler extends AsyncQueryHandler { public SimpleQueryHandler(ContentResolver cr) { super(cr); } //这个方法就是用来接收刚刚传递的两个参数,当查询完成的时候调用 @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { super.onQueryComplete(token, cookie, cursor); if(cookie!=null&& cookie instanceof CursorAdapter){ //查询得到的cursor,交给CursorAdapter,由它把cursor的内容显示至listView ((CursorAdapter)cookie).changeCursor(cursor); } } }
会话列表的布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="8dp" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/selector_bt_bg" android:padding="8dp" > <ImageView android:id="@+id/iv_conversation_avator" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/img_default_avatar" /> <TextView android:id="@+id/tv_conversation_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginLeft="3dp" android:layout_marginTop="3dp" android:text="年月日" android:textSize="15sp" /> <TextView android:id="@+id/tv_conversation_address" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="3dp" android:layout_marginTop="3dp" android:layout_toLeftOf="@id/tv_conversation_date" android:layout_toRightOf="@id/iv_conversation_avator" android:singleLine="true" android:text="名字111111111111111" android:textSize="18sp" /> <TextView android:id="@+id/tv_conversation_body" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@id/iv_conversation_avator" android:layout_marginLeft="3dp" android:layout_marginTop="3dp" android:layout_toRightOf="@id/iv_conversation_avator" android:singleLine="true" android:text="阿卡还得靠就爱上疯狂绝代双骄法律客户端是否快速的凤凰山" android:textSize="13sp" /> </RelativeLayout> </LinearLayout>
那么他可能会覆盖掉你的日期。所以我们先定义出日期的控件。
然后在名字的textview里面使用toleftof日期的textview的id.这样名字过长就不会覆盖掉日期。
————————————————————————————————
创建ViewHolder用于封装条目的所有组件:
ListView我们都只要需要优化。不然内存会大量的使用。
不过cursorAdapter已经帮你做了复用缓存了。
但是ViewHolder没有帮我们实现。
所以我们自己去实现。
先定义出ViewHolder类:
class ViewHolder{ private ImageView iv_conversation_avator; private ImageView tv_conversation_address; private ImageView tv_conversation_body; private ImageView tv_conversation_date; public ViewHolder(View view) { iv_conversation_avator = (ImageView) view.findViewById(R.id.iv_conversation_avator); tv_conversation_address = (ImageView) view.findViewById(R.id.tv_conversation_address); tv_conversation_body = (ImageView) view.findViewById(R.id.tv_conversation_body); tv_conversation_date = (ImageView) view.findViewById(R.id.tv_conversation_date); }
由于CursorAdapter内部是这样实现的:
public ConversationListAdapter(Context context, Cursor c) { super(context, c); // TODO Auto-generated constructor stub } //返回的view对象是就是listview的条目getView() @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { //这个类就是用来设置布局文件给listView来显示的 return View.inflate(context, R.layout.item_conversation,null); } //设置Listview每个条目显示的内容 @Override public void bindView(View view, Context context, Cursor cursor) { //通过这个就可以使用ViewHolder里面的控件了 ViewHolder holder = getViewHolder(view); } public ViewHolder getViewHolder(View view){ //判断你你的holder对象是否已经存在,如果存在直接使用 ViewHolder holder = (ViewHolder) view.getTag(); //如果不存在就创建出来 if(holder==null){ holder = new ViewHolder(view); //setTag可以用于存放数据。 view.setTag(holder); } return holder; } class ViewHolder{ private ImageView iv_conversation_avator; private ImageView tv_conversation_address; private ImageView tv_conversation_body; private ImageView tv_conversation_date; public ViewHolder(View view) { iv_conversation_avator = (ImageView) view.findViewById(R.id.iv_conversation_avator); tv_conversation_address = (ImageView) view.findViewById(R.id.tv_conversation_address); tv_conversation_body = (ImageView) view.findViewById(R.id.tv_conversation_body); tv_conversation_date = (ImageView) view.findViewById(R.id.tv_conversation_date); } } }
我们定义这样一个ViewHolder,就是当你第一次创建的时候去new 一个对象。
下次使用的时候可以直接使用。
——————————————————————
ListView显示查询的会话:
由于我们bindView(View view, Context context, Cursor cursor);
获得的Cursor对象,去使用的时候不是很清晰。所以我们还是创建一个bean。
把Cursor里面的数据保存到bean里面。这样使用起来比较方便清晰。
public class ConversationBean { private String snippet; private String thread_id; private String msg_count; private String address; private Long date; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Long getDate() { return date; } public void setDate(Long date) { this.date = date; } public static ConversationBean creatConversationCursor(Cursor cursor) { ConversationBean conversationBean = new ConversationBean(); conversationBean.setSnippet(cursor.getString(cursor .getColumnIndex("snippet"))); conversationBean.setThread_id(cursor.getString(cursor .getColumnIndex("_id"))); conversationBean.setMsg_count(cursor.getString(cursor .getColumnIndex("msg_count"))); conversationBean.setAddress(cursor.getString(cursor .getColumnIndex("address"))); conversationBean.setDate(cursor.getLong(cursor .getColumnIndex("date"))); return conversationBean; } public String getSnippet() { return snippet; } public void setSnippet(String snippet) { this.snippet = snippet; } public String getThread_id() { return thread_id; } public void setThread_id(String thread_id) { this.thread_id = thread_id; } public String getMsg_count() { return msg_count; } public void setMsg_count(String msg_count) { this.msg_count = msg_count; } }
@Override public void bindView(View view, Context context, Cursor cursor) { //通过这个就可以使用ViewHolder里面的控件了 ViewHolder holder = getViewHolder(view); ConversationBean conversationBean = ConversationBean.creatConversationCursor(cursor); }
这是因为CursorAdapter源码已经对cursor进行了移动判断了。
由于他给我们提供的
queryHandler.startQuery(0, adapter,ConstantValues.URI_SMS_CONVERSATION, null, null, null, null);
这个方法只能查出 最新的一条短信的内容和短信数目,和短信的名字的id。
所以我们需要自己定义一些查询条件,去查找我们需要的日期和名字等。
但是我们查询的时候有一些注意事项。
第一点:就是当我们自己去创建查询字段的时候他会覆盖掉他默认查询的内容。
所以我们需要把他默认查询的内容也添加到查询字段中。
String[] projection = { "sms.body AS snippet", "sms.thread_id AS _id", "groups.msg_count AS msg_count", "address", "date" };
AS代表给他一个别名。
String[] projection = { "sms.body AS snippet", "sms.thread_id AS thead_id", "groups.msg_count AS msg_count", "Address AS address", "Date AS date" };
做完这些之后,我们需要把Cursor提交给Adapter.
protected void onQueryComplete(int token, Object cookie, Cursor cursor) { super.onQueryComplete(token, cookie, cursor); if(cookie!=null&& cookie instanceof CursorAdapter){ //查询得到的cursor,交给CursorAdapter,由它把cursor的内容显示至listView ((CursorAdapter)cookie).changeCursor(cursor); } }
是因为CursorAdapter规定你的cursor当中必须有一个字段是_id 字段。
所以我们直接在查询的字段的时候随便把一个字段的别名改成_id即可:
String[] projection = { "sms.body AS snippet", "sms.thread_id AS _id", "groups.msg_count AS msg_count", "address AS address", "date AS date" };
然后记住在bean里面添加这些字段进去。date日期我们使用Long类型。
然后我们就可以在Adapter里面设置内容了。
public void bindView(View view, Context context, Cursor cursor) { //通过这个就可以使用ViewHolder里面的控件了 ViewHolder holder = getViewHolder(view); ConversationBean conversationBean = ConversationBean.creatConversationCursor(cursor); holder.tv_conversation_address.setText(conversationBean.getAddress()); holder.tv_conversation_body.setText(conversationBean.getSnippet()); holder.tv_conversation_date.setText(conversationBean.getDate()+""); }
ListView显示头像、联系人姓名:
时间显示是这样的:如果是今天的就显示时间。如果是以前的就显示年月日。
我们可以使用DateUtils.isToday(long)判断是否是今天的时间,如果是返回true.
我们还可以使用DateFormat这个类来格式日期的显示格式。
使用getTimeFormat(context).format(long)方法去把long型的时间格式化成时分格式显示
使用getDateFormat(context),format(long)方法把long型的时间格式化成年月日格式显示
if (DateUtils.isToday(conversationBean.getDate())) { holder.tv_conversation_date.setText(DateFormat.getTimeFormat( context).format(conversationBean.getDate())); } else { holder.tv_conversation_date.setText(DateFormat.getDateFormat( context).format(conversationBean.getDate())); }
然后我们还需要按date 进行排序。要是降序desc,因为今天的日期应该是最上面的。
这个在查询的时候进行排序即可。
queryHandler.startQuery(0, adapter, ConstantValues.URI_SMS_CONVERSATION, projection, null, null, "date desc");
public class ContactDao { public static String getNameforAddress(ContentResolver resolver,String address){ String name=null; Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, address); Cursor cursor = resolver.query(uri, new String []{PhoneLookup.DISPLAY_NAME}, null, null, null); if (cursor.moveToFirst()) { name = cursor.getString(0); cursor.close(); } return name; } }
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, address); Cursor cursor = resolver.query(uri, new String []{PhoneLookup.DISPLAY_NAME}, null, null, null);
withAppendedPath()方法的作用是拼接Uri。将里面的数据拼接到Uri后面。
第一个参数是PhoneLookup提供的一个常量,里面封装的是联系人的主机名+路径。
第二个参数是我们要查询的数据。
PhoneLookup.DISPALY_NAME常量是我们联系人里面的名字,通过你第二个参数查询出来的名字。
因为一个号码通常对应一个名字,所以我们查出来的名字应该只有一个结果。
所以我们直接使用movetofirst就可以了。
String name = ContactDao.getNameforAddress( context.getContentResolver(), conversationBean.getAddress()); if (TextUtils.isEmpty(name)) { holder.tv_conversation_address .setText(conversationBean.getAddress() +" " + conversationBean.getMsg_count()); } else { holder.tv_conversation_address.setText(name + " " + conversationBean.getMsg_count() ); }
我们需要去掉它
我们需要在ListView里面这样设置就可以去除这条线:
<ListView android:id="@+id/lv_conversation_list" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:divider="@android:color/transparent" > </ListView>
还有一个问题就是当你点击条目的时候会有一个蓝色的底色:
我们需要自己定义的灰色不需要这个蓝色的底色所以我们需要给ListView默认的selector去掉。
android:listSelector="@android:color/transparent"
——————————————————
显示联系人头像:
由于要使用数据库查询所以我们在dao里面创建一个方法:
public static Bitmap getAvatorByAddress(ContentResolver resolver,String address){ Bitmap bitmap=null; Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, address); Cursor cursor = resolver.query(uri, new String []{PhoneLookup._ID}, null, null, null); if (cursor.moveToFirst()) { String _id = cursor.getString(0); InputStream is = Contacts.openContactPhotoInputStream(resolver, Uri.withAppendedPath(Contacts.CONTENT_URI, _id)); bitmap=BitmapFactory.decodeStream(is); } return bitmap; }
这个方法是直接查询你的联系人里面的头像,将他转化成一个输入流。
记住我们需要通过_id去查询。所以我们要用withAppendedPath()方法去拼接uri.
然后我们就获得了输入流既让他转换成Bitmap 返回就可以了。
然后我们在Adapter里面设置头像,就可以了
Bitmap avtor = ContactDao.getAvatorByAddress(context.getContentResolver(), conversationBean.getAddress()); if (avtor==null) { holder.iv_conversation_avator.setBackgroundResource(R.drawable.img_default_avatar); }else{ holder.iv_conversation_avator.setBackgroundDrawable(new BitmapDrawable(avtor)); }
String name = ContactDao.getNameforAddress( context.getContentResolver(), conversationBean.getAddress()); if (TextUtils.isEmpty(name)) { holder.tv_conversation_address.setText(conversationBean .getAddress() + " " + conversationBean.getMsg_count()); } else { holder.tv_conversation_address.setText(name + " " + conversationBean.getMsg_count()); Bitmap avtor = ContactDao.getAvatorByAddress(context.getContentResolver(), conversationBean.getAddress()); if (avtor==null) { holder.iv_conversation_avator.setBackgroundResource(R.drawable.img_default_avatar); }else{ holder.iv_conversation_avator.setBackgroundDrawable(new BitmapDrawable(avtor)); } }
假设你这样去写,如果没有联系人的话 他就不会去执行头像的代码,这样他就会复用你以前使用过的代码会出现 重复代码
————————————————————————
选择模式下选中条目:
我们现在布局中创建出一个imageView让他显示在联系人条目的左边
<ImageView android:id="@+id/iv_check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:background="@drawable/common_checkbox_normal" android:layout_gravity="center" android:visibility="gone" />
我们在Adapter里面定义出来一个标签。我们默认是 flase如果当我们点击编辑的时候才让他为true;
private boolean selectMode = false;
public boolean getIsSelectMode() { return selectMode; } public void setIsSelectMode(boolean selectMode) { this.selectMode = selectMode; }
public void processClick(View v) { switch (v.getId()) { case R.id.bt_conversation_edit: showSelectMenu(); adapter.setIsSelectMode(true); adapter.notifyDataSetChanged(); break; case R.id.bt_conversation_cancel: showEditMenu(); adapter.setIsSelectMode(false); adapter.notifyDataSetChanged(); break; }
他就不会去显示。
然后我们在Adapter里面的bindView();方法里面去设置
if (selectMode) { holder.iv_check.setVisibility(View.VISIBLE); }else holder.iv_check.setVisibility(View.GONE); }
我们在Fragment里面创建一个lIstView的点击事件。
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //因为我们使用CursorAdapter这个类,他帮我们封装好了getItem可以返回你指定的Cursor对象 if(adapter.getIsSelectMode()){ //选择选框 }else{ //进入对话界面 } } });
那么我们点击条目应该进入对话详情。
如果是在选择界面,我们应该点击条目的时候我们需要选择这个条目,也就是改变选择按钮的背景图片。
接下来我们要创建一个集合,去保存我们点击的条目的thead_id。因为我们要判断我们这个条目是否点击过,如果点击过那么就变回去,如果没有就保存进来且变背景图片。
private List<integer> selectedConversationId=new ArrayList<integer>();
public void SelectSingle(int position){ Cursor cursor=(Cursor)getItem(position); ConversationBean conversationBean = ConversationBean.creatConversationCursor(cursor); if (selectedConversationId.contains(conversationBean.getThread_id())) { selectedConversationId.remove((Integer)conversationBean.getThread_id()); } else{ selectedConversationId.add(conversationBean.getThread_id()); } notifyDataSetChanged(); }
这里要注意我们 remove的时候必须把int转为对象。不然他就相当于删除你指定的索引
还要注意我们需要点击之后我们还需要刷新界面。
这里我们使用getItem()方法的时候,其实它内部已经调用了movetoposition方法。
直接移动到了当前cursor的位置。
所以我们可以直接使用getItem方法传递一个position进来获取指定的cursor
然后我们需要在编辑界面的时候给他定义背景图片,如果是编辑模式且你点击了那么
//判断当前是否进入选择模式 if(isSelectMode){ holder.iv_check.setVisibility(View.VISIBLE); //判断集合中是否包含会话id,从而确定该条目是否被选中 if(selectedConversationIds.contains(conversation.getThread_id())){ holder.iv_check.setBackgroundResource(R.drawable.common_checkbox_checked); } else{ holder.iv_check.setBackgroundResource(R.drawable.common_checkbox_normal); } } else{ holder.iv_check.setVisibility(View.GONE); }
public void SelectAll(){ Cursor cursor = getCursor(); cursor.moveToPosition(-1); while (cursor.moveToNext()) { ConversationBean conversationCursor = ConversationBean.creatConversationCursor(cursor); selectedConversationId.add(conversationCursor.getThread_id()); } notifyDataSetChanged(); } public void Selectcanel(){ selectedConversationId.clear(); notifyDataSetChanged(); }
所以我们需要先给他移动到-1的位置,然后在开始便利,把所有的id都存入集合中。
我们改成set集合,因为list集合会出现同样的。而set集合不会。
标签:
原文地址:http://blog.csdn.net/a_salt_fish/article/details/51225609