一、场景(例如:购物车)

1、当我们需要以列表样式管理某些数据时,可能需要列表项的某个字段可编辑

2、编辑Item上的某个字段后可能还要更新相关字段的值

二、可能遇到的问题

1、列表滑动导致输入框中的数据错位(或者焦点错位)

2、无法更新Item上相关的字段项的值

3、监听输入框文本更改时陷入死循环

三、可行方案(RecyclerView+TextWatcher

       1、用RecyclerView 实现一个ListView的效果:

package com.zhn.edit.recycler;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem; import java.util.ArrayList;
import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener,
EditAbleListAdapter.EditAbleListAdapterListener{ private FloatingActionButton mFLoatingBtnEmail; private RecyclerView mRecyclerEditAble;
private LinearLayoutManager mEditAbleLayoutManager;
private EditAbleListAdapter mEditAbleListAdapter;
private List<datagoods> mDataGoods=new ArrayList<datagoods>(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mFLoatingBtnEmail = (FloatingActionButton) findViewById(R.id.floating_btn_email);
mFLoatingBtnEmail.setOnClickListener(this); mRecyclerEditAble= (RecyclerView) findViewById(R.id.recycler_editable); initData(); } private void initData() {
mEditAbleLayoutManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
mRecyclerEditAble.setLayoutManager(mEditAbleLayoutManager);
mEditAbleListAdapter=new EditAbleListAdapter(this,this);
mRecyclerEditAble.setAdapter(mEditAbleListAdapter); for (int i=;i<;i++){
mDataGoods.add(new DataGoods("Goods"+i,i,i,i*i));
} mEditAbleListAdapter.refreshDatas(mDataGoods);
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.floating_btn_email:
for (int i=;i<mdatagoods.size();i++){
            log.e(mainactivity.class.getsimplename(),mdatagoods.get(i).tostring());="" }="" break;="" default:="" @override="" public="" void="" onedittextchanged(int="" position,="" string="" value)="" {="" todo="" 此处或者回调前应做值合法性验证="" mdatagoods.get(position).setnum(integer.parseint(value));="" <="" pre=""></mdatagoods.size();i++){></datagoods></datagoods>

2、在Adapter中自定义一个Interface 用来将输入的值回传给Activity

3、定义TxtWatcher 接收position和要同步更新的文本框

4、给EditText添加焦点变化的监听器,根据焦点状态绑定和解绑TxtWatcher

package com.zhn.edit.recycler;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView; import java.util.ArrayList;
import java.util.List; /**
* Created by zhn
* 2017/7/9 下午4:20
*/
public class EditAbleListAdapter extends RecyclerView.Adapter{ public void refreshDatas(List<datagoods> mDataGoods) {
mDatas.clear();
mDatas.addAll(mDataGoods);
notifyDataSetChanged();
} public interface EditAbleListAdapterListener{
public void onEditTextChanged(int position,String value);
} private Context mContext;
private List<datagoods> mDatas=new ArrayList<datagoods>(); private EditAbleListAdapterListener mListener;
public EditAbleListAdapter(Context context,EditAbleListAdapterListener listener){
this.mContext=context;
this.mListener=listener;
} @Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new EditAbleListViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_editable_view,null));
} @Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((EditAbleListViewHolder)holder).setContent(position,mDatas.get(position)); } @Override
public int getItemCount() {
return mDatas.size();
} public class EditAbleListViewHolder extends RecyclerView.ViewHolder{ private TextView mTvItemNo;
private TextView mTvGoodsName;
private TextView mTvPrice;
private EditText mEtNum;
private TextView mTvTotalPrice; private TxtWatcher mTxtWatcher; public EditAbleListViewHolder(View itemView) {
super(itemView); mTvItemNo= (TextView) itemView.findViewById(R.id.tv_item_no);
mTvGoodsName= (TextView) itemView.findViewById(R.id.tv_goods_name);
mTvPrice= (TextView) itemView.findViewById(R.id.tv_price);
mEtNum= (EditText) itemView.findViewById(R.id.et_num);
mTvTotalPrice= (TextView) itemView.findViewById(R.id.tv_total_price); mTxtWatcher=new TxtWatcher();
} public void setContent(int position,DataGoods data){ mTvItemNo.setText(String.valueOf(position+));
mTvGoodsName.setText(data.getGoodsName());
mTvPrice.setText(String.valueOf(data.getPrice()));
mEtNum.setText(String.valueOf(data.getNum()));
mTvTotalPrice.setText(String.valueOf(data.getTotalPrice())); mTxtWatcher.buildWatcher(position,mTvTotalPrice); mEtNum.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
mEtNum.addTextChangedListener(mTxtWatcher);
}else{
mEtNum.removeTextChangedListener(mTxtWatcher);
}
}
});
} } public class TxtWatcher implements TextWatcher{ private int mPosition;
private TextView mTvTotalPrice; public void buildWatcher(int position,TextView view){
this.mPosition=position;
this.mTvTotalPrice=view;
} @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(s.length()>){
if(mListener!=null){
mListener.onEditTextChanged(mPosition,s.toString());
mTvTotalPrice.setText(String.valueOf(mDatas.get(mPosition).getPrice()*Double.parseDouble(s.toString())));
}
}else{
if(mListener!=null){
mListener.onEditTextChanged(mPosition,"");
mTvTotalPrice.setText("");
}
}
} @Override
public void afterTextChanged(Editable s) { }
} }

四、选择RecyclerView而不是ListView的原因

        RecyclerView 在滑动的时候会使EditText失去焦点,这样可以触发OnFocusChangeListener,这样可以更准确的绑定和解绑TxtWatcher。为什么要解绑TxtWatcher?因为在RecyclerView刷新的时候会重复触发TextWatcher导致很多次无用的回调(甚至死循环)。

ListView在滑动的时候不会使EditText失去焦点,导致了滑动时输入框焦点错位,并且因为输入框是复用的所以导致TextWatcher重复触发很多次(可能是死循环)。

五、注意在布局中设置列表是尽量降低RecyclerView布局重绘的可能性(例如:固定大小等等)

最新文章

  1. 工作笔记--哪些bug应由研发发现?
  2. Unity 依赖注入之二
  3. logging 模块误用导致的内存泄露
  4. CentOS7下搭建邮件服务器(dovecot + postfix + SSL)
  5. my first article
  6. linq order by charindex 排序 按给定字符串顺序排序
  7. 取余运算(codevs 1497)
  8. Lambda中的一些方法的总结
  9. APICloud请你看英特尔智能硬件大赛决赛直播
  10. 委托、匿名函数、Lambda表达式和事件的学习
  11. 定时自动同步文件,支持多文件夹同步,支持过滤文件和文件夹,解决FileSystemWatcher多次文件触发事件(源码)
  12. 关于AVD不能导入文件的解决方案
  13. WebService实现文件上传下载
  14. linux function
  15. 许士彦:创业不走寻常路 APP最好时间已过
  16. JAVA中enum的常见用法
  17. 光谱郑匡移动互联网O2O完美融合
  18. Windows下编译mxnet
  19. Thrift入门初探--thrift安装及java入门实例
  20. 优化Linux内核参数提高服务器负载能力

热门文章

  1. jmeter的dubbo压测,依赖jar包要放到执行机的lib/ext下
  2. windows安装docker
  3. VMware实用技巧
  4. 安装Nginx须要系统的辅助软件(linux)
  5. 怎样在Swift中使用NSError
  6. 数组/矩阵转换成Image类
  7. ARP协议(4)ARP编程
  8. Use of implicitly declared global variable
  9. mysql与mongoDB的特点和优劣
  10. bzoj 2428 均分数据