接近尾声之时,小伙伴又给我提了一个需求,让我做一个类似于Excel的表格,大致就是如下图这样。
我们可以看到这里面不仅有多个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
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上的操作。
图片选择有很多封装好的第三方,很好用。大家随意在网上找就好。
有问题可以多多交流,我也是才弄得这个,暂时还没发现问题。