RecycleView使用EditText的数据和焦点错乱问题解决方案

RecycleView是常用的列表控件,在日常的开发中使用频率很高,使用起来很方便,只要设置好条目布局和数据就可以完美的展示数据。EditText是常用的输入控件,用于用户的数据输入。二者本来各自使用都很容易,但是如果放到一起就出现问题,条目的复用导致EditText输入的内容出现错乱,焦点的获取也混乱了,令很多新手大为头疼。

基本的思路是要在条目的可见和隐藏时处理好焦点的问题,要将操作的EditText的位置坐标记录下来,进行有效管理,还有将输入框的显示和隐藏也管理起来。解决的代码本身并不复杂,注释也标识出来了。之前写过一个List View和EditText搭配使用的文章,这里算是更新吧,并且输入框也增加了多个输入框的处理逻辑。

核心的Adapter代码如下:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private String TAG="MyAdapter";
    private List<ItemDataEntity> list;
    private Context mContext;
    private final InputMethodManager inputMethodManager;
    //edittext的焦点position位置
    int etFocusPos = -1;
    private int idSelectView=-1;

    public MyAdapter(List<ItemDataEntity> list, Context mContext) {
        this.list = list;
        this.mContext = mContext;
        inputMethodManager = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
    }


    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, null);
        ViewHolder viewHolder = new ViewHolder(inflate);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        holder.tvNum.setText("序号:"+list.get(position).getNum());
        holder.tvName.setText("姓名:"+list.get(position).getName());
        holder.etAge.setText(list.get(position).getAge());
        holder.etaddress.setText(list.get(position).getAddress());
        holder.etaddress.addTextChangedListener(textWatcher);
        holder.etAge.addTextChangedListener(textWatcher);
        //当焦点获取或取消时
        holder.etaddress.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                if (b){
                    idSelectView = view.getId();
                    etFocusPos = position;
                    Log.i(TAG,"etFocusPos焦点选中-"+etFocusPos);
                }
            }
        });
        //当焦点获取或取消时
        holder.etAge.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                if (b){
                    idSelectView = view.getId();
                    etFocusPos = position;
                    Log.i(TAG,"etFocusPos焦点选中-"+etFocusPos);
                }
            }
        });
    }

    /**
     * 当适配器创建的view(即列表项view)划出屏幕,不可见时调用
     * @param holder
     */
    @Override
    public void onViewDetachedFromWindow(ViewHolder holder) {
        super.onViewDetachedFromWindow(holder);
        Log.i(TAG,"隐藏item="+holder.getAdapterPosition());
        //根据点击的不同editextview 处理焦点和监听
        if (idSelectView==R.id.et_address){
            holder.etaddress.removeTextChangedListener(textWatcher);
            holder.etaddress.clearFocus();
        }else if (idSelectView==R.id.et_age){
            holder.etAge.removeTextChangedListener(textWatcher);
            holder.etAge.clearFocus();
        }
        //当条目不可见时,重置焦点position,隐藏键盘
        if (etFocusPos == holder.getAdapterPosition()) {
            inputMethodManager.hideSoftInputFromWindow(((ViewHolder) holder).etaddress.getWindowToken(), 0);
            etFocusPos=-1;
        }
    }

    /**
     * edittextview的文本监听
     */
    TextWatcher textWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            //每次修改文字后,保存在数据集合中
            Log.i(TAG,"index="+etFocusPos+",save="+s.toString());
            if (!TextUtils.isEmpty(s.toString())&&etFocusPos!=-1){
                if (idSelectView==R.id.et_address){
                    list.get(etFocusPos).setAddress(s.toString());
                }else if (idSelectView==R.id.et_age){
                    list.get(etFocusPos).setAge(s.toString());
                }
            }
        }
    };

    /**
     * 当列表项出现到可视界面的时候调用
     * @param holder
     */
    @Override
    public void onViewAttachedToWindow(ViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        Log.i(TAG,"显示item="+holder.getAdapterPosition());
        if (idSelectView==R.id.et_age){
            holder.etAge.addTextChangedListener(textWatcher);
        }else if (idSelectView==R.id.et_address){
            holder.etaddress.addTextChangedListener(textWatcher);
        }
        //根据点击的位置,处理焦点和光标位置
        if (etFocusPos == holder.getAdapterPosition()) {
            if (idSelectView==R.id.et_age){
                holder.etAge.requestFocus();
                holder.etAge.setSelection(holder.etAge.getText().length());
            }else if (idSelectView==R.id.et_address){
                holder.etaddress.requestFocus();
                holder.etaddress.setSelection(holder.etaddress.getText().length());
            }
        }
    }
    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        private TextView tvNum;
        private TextView tvName;
        private EditText etAge;
        private EditText etaddress;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            tvNum = itemView.findViewById(R.id.tv_num);
            tvName = itemView.findViewById(R.id.tv_name);
            etAge = itemView.findViewById(R.id.et_age);
            etaddress = itemView.findViewById(R.id.et_address);
        }
    }
}

布局:

<?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:layout_margin="5dp"
    xmlns:tool="http://schemas.android.com/tools"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/tv_num"
        tool:text="001"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_marginLeft="10dp"
        tool:text="tom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/et_age"
        android:layout_marginLeft="10dp"
        android:layout_width="80dp"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/et_address"
        android:layout_marginLeft="10dp"
        android:layout_width="80dp"
        android:layout_height="wrap_content" />
</LinearLayout>

展示的逻辑:

ArrayList<ItemDataEntity> itemDataEntities = new ArrayList<>();
        for (int i=0;i<50;i++){
            ItemDataEntity itemDataEntity = new ItemDataEntity();
            itemDataEntity.setName("T"+i);
            itemDataEntity.setNum(""+i);
            itemDataEntities.add(itemDataEntity);
        }
        RecyclerView recyclerView=findViewById(R.id.recycleview);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplication());
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
        MyAdapter myAdapter = new MyAdapter(itemDataEntities, getApplication());
        recyclerView.setAdapter(myAdapter);

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页