欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ListView中的条目获取焦点时更换背景。

程序员文章站 2022-06-06 15:27:31
...

需求

最近有一个需求,一个ListView或者RecyclerView或者ListPopupWindow列表。这三个控件都是类似的,其实可以认为是同一个控件,因为本质上其实都是列表展示的控件。列表的item在获取到焦点的时候需要和其他的item区别开来,背景换个颜色。做了好几次尝试,最后找到了比较好的解决办法,这里记录下来。

分析

这里的问题有两个:①是获取到焦点,比如用手柄去控制手机的时候,通过手柄摇杆去控制焦点的移动,这个时候,不会触发click事件。②listview这一类的列表,本身是一个view控件,其每一个item又是一个view,这就存在view之间焦点的转移问题。

解决的逻辑

其实解决的逻辑非常简单:
思路一:既然是获取焦点的时候改变背景,那当然是需要监听焦点变化,

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
		        View view= LayoutInflater.from(context).inflate(R.layout.pop_item_server_ip_layout,parent,false);
		view.setOnFocusChangeListener(new View.OnFocusChangeListener() {
		            @Override
		            public void onFocusChange(View view, boolean hasFocus) {
		                if (hasFocus){
		            view.setBackgroundColor(context.getResources().getColor(R.color.white));
		
		        }else{
		            view.setBackgroundColor(context.getResources().getColor(R.color.transparent));
		        }
		            }
		        });
 	}

刚开始,我也是按照这样的逻辑去解决的,但是实际上并没有起到效果,时间问题,我并没有深究,但是可以确定的是焦点并没有监听到,这样说来焦点就没有到达这个item上来。所以不管如何尝试都是没有任何效果,不会改变背景的。
如果一定要,从这个思路解决这个问题,也不是不可以,就是让焦点穿透进来,怎么穿透,listviewAPI里面提供了方法。
可以参考:https://blog.csdn.net/dcqboke/article/details/38588695

思路二:AdaptergetView()方法里面是负责绘制item的,改变背景就在这里进行控制,肯定是没问题的。但是哪个item获取到了焦点,它的position得传递进来,然后Adapter需要notifyDataSetChanged(),
按照这个思路,

问题来了,怎么监听到哪个item获取到了焦点呢?

非常简单,通过setOnItemSelectedListener这个监听方法就可以监听到,这个监听在新的API里出现的,之前一直在使用的setOnItemClickListener这个监听,两个监听可以同时存在和使用。
首先,在Adapter里面写一个方法,getSelectionPosition(int selecPosition)用于将获取到焦点的item的position传递进Adapter。

public class PopServerAdapter extends BaseAdapter {

    private Context context;
    private List<ServerPopBean> list;
    private int selecPosition=-1;

    public void setSelecPosition(int selecPosition){
        this.selecPosition=selecPosition;
    }

    public PopServerAdapter(Context context,List<ServerPopBean> list){
        this.context=context;
        this.list=list;
    }

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

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view= LayoutInflater.from(context).inflate(R.layout.pop_item_server_ip_layout,parent,false);
        if (selecPosition==position){
            view.setBackgroundColor(context.getResources().getColor(R.color.white));

        }else{
            view.setBackgroundColor(context.getResources().getColor(R.color.transparent));
        }

        TextView name=view.findViewById(R.id.item_serverIpTV);
        name.setText(list.get(position).getServer_name());
        return view;
    }
}

其次,在ListPopupWindow 的OnitemSelection监听中调用此方法将获取到焦点的postion传递进Adapter,不能忘记notify整个adapter,否则是没有效果的。

ListPopupWindow listPopupWindow.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                    @Override
                    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
//                        Toast.makeText(ServerSetting2Activity.this, "has focus", Toast.LENGTH_SHORT).show();
//                        选中的那一项item背景给设置颜色
                        popServerAdapter.setSelecPosition(position);
                        popServerAdapter.notifyDataSetChanged();
                    }

                    @Override
                    public void onNothingSelected(AdapterView<?> parent) {

                    }
                });

结束,这样就完成了需求了。

效果图

ListView中的条目获取焦点时更换背景。

demo的GitHub地址

https://github.com/jakezhang1990/ListPopChangeItemBgDemo

参考链接

https://blog.csdn.net/u013894427/article/details/53130397

https://blog.csdn.net/dcqboke/article/details/38588695

相关标签: android技术