ListView中有一个属性:android:choiceMode,对应三个可选值:

singleChoice 单选
multipleChoice 多选
none 默认情况,没有选中效果
在ListView的布局中设置了android:choiceMode属性后,item布局需要实现checkable,才有选中效果。

那么我们先来看一下这个checkable接口:

/**
 * Defines an extension for views that make them checkable.
 *
 */
public interface Checkable {

    /**
     * Change the checked state of the view
     * 
     * @param checked The new checked state
     */
    void setChecked(boolean checked);

    /**
     * @return The current checked state of the view
     */
    boolean isChecked();

    /**
     * Change the checked state of the view to the inverse of its current state
     *
     */
    void toggle();
}

接口很简单,就三个方法:

setChecked(boolean checked) 设置是否选中。当我们点击item的时候,会调用这个方法。
boolean isChecked() 判断是否选中。
toggle() 开关,如果当前是选中的状态,调用该方法后取消选中,反之,选中。
实现单选效果:

1、 ListView布局中android:choiceMode设置为singleChoice。 
2、选取实现了checkable接口的View或者ViewGroup作为item布局控件。

当item展示的数据比较简单,例如就是一段文本,item布局可以直接使用系统自带的CheckedTextView控件,该控件有一个属性:android:checkMark=”?android:listChoiceIndicatorSingle”为单选样式;“?android:listChoiceIndicatorMultiple”为多选样式。若要修改显示的样式,可以自己写一个selector,然后checkMark指定为这个selector。例如:

在drawable文件夹下面创建一个ic_hideable_item.xml文件。


   
   


checkMark指定为上面的那个xml文件:

    android:id="@+id/tv_single_choice"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/listPreferredItemHeightSmall"
    android:textSize="14sp"
    android:gravity="center_vertical"
    android:checkMark="@drawable/ic_hideable_item"
    android:paddingLeft="16dp"
    android:paddingRight="16dp">


实现多选效果:

1、 ListView布局中android:choiceMode设置为multipleChoice。 
2、选取实现了checkable接口的View或者ViewGroup作为item布局控件。 
这里笔者自定义一个控件实现Checkable接口。代码如下:

public class CheckableLayout extends RelativeLayout implements Checkable {

    private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};

    private boolean mChecked;

    public CheckableLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    @Override
    public void setChecked(boolean b) {

        if (b != mChecked){
            mChecked = b;
            refreshDrawableState();
        }
    }

    @Override
    public boolean isChecked() {
        return mChecked;
    }

    @Override
    public void toggle() {

        setChecked(!mChecked);
    }


    @Override
    protected int[] onCreateDrawableState(int extraSpace) {

        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);

        if (isChecked()) mergeDrawableStates(drawableState, CHECKED_STATE_SET);

        return drawableState;
    }
}

应用到item布局:

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">


            android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:duplicateParentState="true"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="30dp"
        android:textColor="@color/hideable_text_color"
        tools:text="测试数据"/>


            android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:duplicateParentState="true"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="20dp"
        android:src="@drawable/ic_hideable_item"/>



注意到上面TextView、ImageView控件中的android:duplicateParentState属性, 
该属性表示当前控件是否跟随父控件的状态(点击、焦点等)。若将TextView的该属性置为false,则文字无变色效果;若将ImageView的该属性置为false,则无选中效果。

最后怎样获取选中item对应的位置呢?

单选—> 通过ListView的getCheckedItemPosition()获取选中的位置。
多选—> 通过ListView的getCheckedItemPositions()得到一个SparseBooleanArray,key为position,value为是否选中。
mSingleListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                int checkedItemPosition = mSingleListView.getCheckedItemPosition();
                Toast.makeText(MainActivity.this, "you chose item " + checkedItemPosition, Toast.LENGTH_SHORT).show();
            }
        });


        mMultipleListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                SparseBooleanArray checkedItemPositions = mMultipleListView.getCheckedItemPositions();
                boolean isChecked = checkedItemPositions.get(position);
                Toast.makeText(MainActivity.this, "item " + position + " isChecked=" + isChecked, Toast.LENGTH_SHORT).show();
            }
        });

源码传送门

更多相关文章

  1. 中秋深夜码字,完成了一个底部导航栏(Android自定义控件),一键添加
  2. Android控件笔记——多状态按钮ToggleButton
  3. 快速使用Android BaseRecyclerViewAdapterHelper之实现一种&多种
  4. 关于含有RecyclerView的布局载入时,会滚动到底部问题
  5. Android从右到左的布局(RTL Layout)
  6. 第三章 Android控件架构与事件拦截机制
  7. Android 控件之Spinner
  8. listview 属性 小结
  9. android ui 布局

随机推荐

  1. Android中使用WebView, WebChromeClient
  2. Android[项目] Android天气预报
  3. Android手势ImageView三部曲 第三部
  4. Android之Adapter用法总结
  5. Android(安卓)网络请求库Retrofit简单使
  6. Android学习资源-retrofit,eventBus,butter
  7. 关于调试的一个问题
  8. Android开发环境搭建
  9. Android(安卓)studio连接Bmob云数据库教
  10. 《Android》Lesson09-Acitivity的四种启