RecyclerView/ListView中多EditText时,焦点,数据实时问题的解决

接近尾声之时,小伙伴又给我提了一个需求,让我做一个类似于Excel的表格,大致就是如下图这样。

RecyclerView/ListView中多EditText时,焦点,数据实时问题的解决_第1张图片

我们可以看到这里面不仅有多个editText,还有图片,一次要给x个数据项。

在此我建议使用RecyclerView,使用ListView会很有很多问题,处理起来很麻烦,比如我1,2行输入的内容,可能会被复用到其他行去。而在RecyclerView里面很轻松就能解决这个问题。

思路我们先整理一下。所有的数据都在Adapter里面,我们要把内容从Adapter传到Activity,又或者说,Activity能够获取到此时此刻Adapter里面的数据。怎么传?

我们先列举一个实体类。

public class DeviceAllInfoBean implements Serializable {
     String name;//名字
     String age;//年龄
     String height;//身高
     String imgStream;//图片

    public DeviceAllInfoBean(String imgStream,String name,String age,String height) {
        this.imgStream=imgStream;
        this.name=name;
        this.age=age;
        this.height=height;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getImgStream() {
        return deviceTime;
    }

    public void setImgStream(String imgStream) {
        this.imgStream= imgStream;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age= age;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getHeight() {
        return height;
    }

    public void setHeight(String height) {
        this.height= height;
    }
}

然后我们在Adapter里面通过实体,来设置实体内容,然后用一个public方法,通过Gson把实体转化成Json数据,返回给Activity。

放码过来:

1、在Adapter的构造器内,进行一个for循环,循环次数x.这里我就循环6次,也就是初始化的时候,有6行,行内数据为空。

public MyAdapter(Context context,List deviceAllInfoBeanList) {
        entities = new ArrayList();
        for (int i = 0; i < 6; i++) {
                DeviceAllInfoBean entities = new DeviceAllInfoBean(“”,null,null,null);
                this.entities.add(entities);
        }
    }

2、在onBindViewHolder中遍历值,获取每一个的值

注:entities是一个List数组:List entities;可以看做一个暂时存储器,来存放后面editText的实体内容。

final DeviceAllInfoBean deviceAllInfoBean = this.entities.get(position);
        String str_name = deviceAllInfoBean.name;

接下来在上面代码的下面,设置值到实体类中,存入tag中。(setTag有暂时存储数据的功效,不知道这么说准确不,但是这里确实是有暂时存储的作用)

((ViewHold) holder).et_name.setText(TextUtils.isEmpty(str_name) ? "" : str_name);
deviceAllInfoBean.setName((TextUtils.isEmpty(str_name) ? "" : str_name));

 ((ViewHold) holder).et_name.setTag(deviceAllInfoBean);

为了防止,你输入了1,2的数据,下面的都被填满成1,2的数据。我们就加一句这个,防止数据复用。

ViewHolder的setTag和getTag的解释如下:

注:这个方法是RecyclerView的方法,ListView是没有这个方法的。

holder.setIsRecyclable(false);//不使用复用 防止数据多时 复用时  多个item中的EditText填写的数据一样

接下来,设置监听:EditText我一共用了两个监听。

①addTextChangedListener  文本监听

这里面做的操作是:拿到setTag中的实体类,且把这个实体赋值给一个新的实体对象,将触发TextChange的editText现在的值获取到,赋值给实体的对应的属性。最后将以前的position的值用List里面的set方法进行值的替换。

注:list.set(position,bean);是替换某一个position对应的值。

((ViewHold) holder).et_name.addTextChangedListener(new TextWatcher() {//监听EditText的text变化
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after){

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                DeviceAllInfoBean entities1 = (DeviceAllInfoBean) ((ViewHold) holder).et_name.getTag();
                entities1.setName(((ViewHold) holder).et_name.getText().toString());
                entities.set(position, entities1);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

②OnFocusChangeListener  焦点监听

在焦点获取到的状态下,获取存存入tag中的值,且将值设置到控件上。

在失去焦点的状态下,获取editText输入的值,且设置到实体中。

View.OnFocusChangeListener listener = new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
             if(!isFromImg){
                  if (!b) {
                    if (view == ((ViewHold) holder).et_name) {
                        DeviceAllInfoBean entities = (DeviceAllInfoBean) ((ViewHold) holder).et_name.getTag();
                        entities.setName(((ViewHold) holder).et_name.getText().toString());
                    } 
                } else{
                    if (view == ((ViewHold) holder).et_name) {
                        DeviceAllInfoBean entities1 = (DeviceAllInfoBean) ((ViewHold) holder).et_name.getTag();
                        String et_name1 = entities1.deviceName;
                        ((ViewHold) holder).et_name.setText(TextUtils.isEmpty(et_name1) ? "" : et_name1);
                    }
                }
}
               
            }
        };
/**
*isFromImg是一个boolean值,是一个标识,用于判断是否是选择图片之后的焦点监听
*(我在选择头像图片之后,不监听焦点事件。)不用的可以不要这个isFromImg条件。
*/

别忘了给editText设置焦点监听:

((ViewHold) holder).et_name.setOnFocusChangeListener(listener);

然后写一个方法,可以让Activity调用这个方法来获取到Adapter中所有EditText值的方法。

public String getDataToActivity() {
        return new Gson().toJson(entities);
    }

然后再Activity中去调用这个方法,获取到这6个Item中所有的Json数据。

最后,选择图片,直接在item的ImageView上添加一个点击事件,跳转到图片选择界面。可能你有点迷茫,在Adapter中的onClick中去调用StartActivitieForResult,在哪里去接收?网上很多都有讲,在Adapter中发出,那么在其所在的Activity中用onActivity去接收数据。

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK&&null!=data) {
            final ArrayList pathList = data.getStringArrayListExtra(PhotoPickerActivity.EXTRA_RESULT_SELECTION);
            final boolean original =
                    data.getBooleanExtra(PhotoPickerActivity.EXTRA_RESULT_ORIGINAL, false);
            myAdapter.setNewData(position,pathList);
        }
    }
/**
*在图片选择界面选择/拍照之后,setResult,调用该Activity的onActivity。
*pathList是选择的图片集合。多选就可以用List装,单选也可以用List(如果不考虑List所占用资源的话)
*这里的setNewData(int,)是Adapter中的一个方法,把img本地的地址传递到这里,然后传递到Adapter中,进行显示。
*/

最后我们来看Adapter中的setNewData()这个方法。

/**
*设置图片到item中。(理解意思就行了。这些操作都是自由发挥的。)
*/
public void setNewData(int itemPosition,List data) {
        this.itemPosition=itemPosition;
        this.listOfImg.clear();
        if (data != null) {
            this.listOfImg.addAll(data);
        }
        imgPath=listOfImg.get(0);

        entities.get(itemPosition).setImgStream(imgPath);
        isFromImg=true;
        notifyDataSetChanged();
    }

到这里就差不多完成了一个RecyclerView内item有多个EditText,且包含图片选择并显示在item上的操作。

图片选择有很多封装好的第三方,很好用。大家随意在网上找就好。

有问题可以多多交流,我也是才弄得这个,暂时还没发现问题。

你可能感兴趣的:(android)