Android Studio新手开发第二十二天

目录

列表视图ListView

焦点抢占问题及解决方式

列表视图ListView

        列表类视图是 Android 开发中最重要和最常用的组件之一,用于展示大量结构化数据。ListView与Spinner一样通过setAdapter方法设置列表项的数据适配器,但它设置监听器的方法却不同。它通过调用方法setOnItemClickListener设置列表项的点击监听器OnItemClickListener,调用方法setOnitemLongClickListener设置列表项的长按监听器OnItemLongClickListener。列表视图ListView还新增了几个属性以及对应的方法。属性divider指定分割线的图形若不需要分割线只需将该属性的值设为"@null",其对应的方法为setDivider;属性dividerHeight指定分割线的高度,对应方法为setDividerHeight;属性listSelector指定列表项的按压背景,其对应方法为setSelector。代码示例如下,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SeniorWidget.ListViewActivity">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

        button_selector.xml的代码如下。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/teal_200" android:state_pressed="true"/>
    <item android:drawable="@color/green" />
</selector>

        部分Java代码如下,数据适配器的内容与下拉框中的用法是一样的,不同在于属性以及对应方法的使用,还有监听器的不同。

public class ListViewActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {

    private int[] image_id = {R.drawable.one, R.drawable.two, R.drawable.three, R.drawable.four, R.drawable.five,
            R.drawable.six, R.drawable.seven, R.drawable.eight, R.drawable.nine, R.drawable.zero};
    private Integer[] number = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    private String[] number_english = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view);

        ListView listView = findViewById(R.id.listView);
        List<NumberInfo> numberInfoList = getList();

        listView.setAdapter(new MyBaseAdapter(this, numberInfoList));
        listView.setSelection(0);
        listView.setDivider(getDrawable(R.drawable.image_3));
        listView.setDividerHeight(5);
        listView.setSelector(R.drawable.button_selector);

        listView.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        if (adapterView.getId() == R.id.listView) {
            Toast.makeText(this,String.format("选中了第%d项",i),Toast.LENGTH_SHORT).show();
        }
    }

    public List<NumberInfo> getList() {
        List<NumberInfo> numberInfoList = new ArrayList<NumberInfo>();
        for (int i = 0; i < number.length; i++) {
            NumberInfo numberInfo = new NumberInfo();
            numberInfo.setImage_id(image_id[i]);
            numberInfo.setNumber(number[i]);
            numberInfo.setNumber_english(number_english[i]);
            numberInfoList.add(numberInfo);
        }
        Log.e(TAG, "getList: ");
        return numberInfoList;
    }

    class NumberInfo {
        private int image_id;
        private int number;
        private String number_english;

        public int getImage_id() {
            return image_id;
        }

        public void setImage_id(int image_id) {
            this.image_id = image_id;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        public String getNumber_english() {
            return number_english;
        }

        public void setNumber_english(String number_english) {
            this.number_english = number_english;
        }
    }

    class MyBaseAdapter extends BaseAdapter {
        private List<NumberInfo> numberInfoList;
        private Context mcontext;

        public MyBaseAdapter(Context context, List<NumberInfo> list) {
            super();
            numberInfoList = list;
            mcontext = context;
        }

        @Override
        public int getCount() {
            return numberInfoList.size();
        }

        @Override
        public Object getItem(int i) {
            return numberInfoList.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            ViewHolder viewHolder;
            if (view == null) {
                viewHolder = new ViewHolder();
                view = LayoutInflater.from(mcontext).inflate(R.layout.item_base, null);
                viewHolder.imageView = view.findViewById(R.id.imageView);
                viewHolder.textView_1 = view.findViewById(R.id.textView_1);
                viewHolder.textView_2 = view.findViewById(R.id.textView_2);
                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }

            NumberInfo numberInfo = numberInfoList.get(i);
            viewHolder.imageView.setImageResource(numberInfo.getImage_id());
            viewHolder.textView_1.setText(String.format("%d", numberInfo.getNumber()));
            viewHolder.textView_2.setText(numberInfo.getNumber_english());
            viewHolder.imageView.requestFocus();
            return view;
        }

        final class ViewHolder {
            public ImageView imageView;
            public TextView textView_1;
            public TextView textView_2;
        }
    }
}

        效果图如下,可以看到列表视图能够展示全部的数据项,这与下拉框不一样,下拉框在选择后只能展示一项的内容。

焦点抢占问题及解决方式

        如果在列表项中有按钮或者编辑框这类控件,当发生点击事件时这类控件会抢占焦点导致列表项的点击监听器失效。为了解决该问题,可以在列表项的布局文件中的的根节点添加属性descendantFocusability并设置其值或者在Java代码中调用方法setdescendantFocusability设置。该属性有三种取值,如下表所示说明。

属性取值代码中的方法参数取值说明

beforeDescendants

ViewGroup.FOCUS_BEFORE_DESCENDANTS

视图组优先:ViewGroup 先于子视图获取焦点

afterDescendants

ViewGroup.FOCUS_AFTER_DESCENDANTS

子视图优先:子视图先于 ViewGroup 获取焦点

blocksDescendants

ViewGroup.FOCUS_BLOCK_DESCENDANTS

阻止子视图:ViewGroup 获取焦点,阻止子视图获取

        代码示例如下,页面布局文件不变。

        下面为item_listview.xml中的代码,在原来的列表项布局中新加了一个按钮并且在布局的根结点添加了属性descendantFocusability并且取值为blocksDescendants。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:descendantFocusability="blocksDescendants">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:layout_weight="1"
        android:src="@drawable/image_3"/>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:layout_weight="2"
        android:orientation="vertical">
        <TextView
            android:id="@+id/textView_1"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="17sp"
            android:textColor="#1269db"
            android:text="@string/app_name"/>
        <TextView
            android:id="@+id/textView_2"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:textSize="17sp"
            android:text="@string/app_name"/>
    </LinearLayout>

    <Button
        android:id="@+id/button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_gravity="center"
        android:text="Button" />

</LinearLayout>

        Java代码的不同主要在于适配器中,在类ViewHolder中添加了一个按钮button用于获取按钮实例,在方法getView中改变在于与按钮相关的部分,如获取按钮实例以及设置按钮监听器,其余基本不变。

   class MyBaseAdapter extends BaseAdapter {
        private List<NumberInfo> numberInfoList;
        private Context mcontext;

        public MyBaseAdapter(Context context, List<NumberInfo> list) {
            super();
            numberInfoList = list;
            mcontext = context;
        }

        @Override
        public int getCount() {
            return numberInfoList.size();
        }

        @Override
        public Object getItem(int i) {
            return numberInfoList.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            ViewHolder viewHolder;
            if (view == null) {
                viewHolder = new ViewHolder();
                view = LayoutInflater.from(mcontext).inflate(R.layout.item_listview, null);
                viewHolder.imageView = view.findViewById(R.id.imageView);
                viewHolder.textView_1 = view.findViewById(R.id.textView_1);
                viewHolder.textView_2 = view.findViewById(R.id.textView_2);
                viewHolder.button = view.findViewById(R.id.button);
                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }

            NumberInfo numberInfo = numberInfoList.get(i);
            viewHolder.imageView.setImageResource(numberInfo.getImage_id());
            viewHolder.textView_1.setText(String.format("%d", numberInfo.getNumber()));
            viewHolder.textView_2.setText(numberInfo.getNumber_english());
            viewHolder.button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(mcontext,String.format("点击了第%d项的按钮!",i+1),Toast.LENGTH_SHORT).show();
                }
            });
            viewHolder.imageView.requestFocus();
            return view;
        }

        final class ViewHolder {
            public ImageView imageView;
            public TextView textView_1;
            public TextView textView_2;
            public Button button;
        }
    }

        效果图如下,可以看到按钮并没有抢占列表项的焦点,两者的监听器能够正常运行。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值