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

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

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

二、可能遇到的问题

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

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

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

三、可行方案(RecyclerView+TextWatcher

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

  1. package com.zhn.edit.recycler;
  2.  
  3. import android.os.Bundle;
  4. import android.support.design.widget.FloatingActionButton;
  5. import android.support.design.widget.Snackbar;
  6. import android.support.v7.app.AppCompatActivity;
  7. import android.support.v7.widget.LinearLayoutManager;
  8. import android.support.v7.widget.RecyclerView;
  9. import android.support.v7.widget.Toolbar;
  10. import android.util.Log;
  11. import android.view.View;
  12. import android.view.Menu;
  13. import android.view.MenuItem;
  14.  
  15. import java.util.ArrayList;
  16. import java.util.List;
  17.  
  18. public class MainActivity extends AppCompatActivity implements View.OnClickListener,
  19. EditAbleListAdapter.EditAbleListAdapterListener{
  20.  
  21. private FloatingActionButton mFLoatingBtnEmail;
  22.  
  23. private RecyclerView mRecyclerEditAble;
  24. private LinearLayoutManager mEditAbleLayoutManager;
  25. private EditAbleListAdapter mEditAbleListAdapter;
  26. private List<datagoods> mDataGoods=new ArrayList<datagoods>();
  27.  
  28. @Override
  29. protected void onCreate(Bundle savedInstanceState) {
  30. super.onCreate(savedInstanceState);
  31. setContentView(R.layout.activity_main);
  32.  
  33. mFLoatingBtnEmail = (FloatingActionButton) findViewById(R.id.floating_btn_email);
  34. mFLoatingBtnEmail.setOnClickListener(this);
  35.  
  36. mRecyclerEditAble= (RecyclerView) findViewById(R.id.recycler_editable);
  37.  
  38. initData();
  39.  
  40. }
  41.  
  42. private void initData() {
  43. mEditAbleLayoutManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
  44. mRecyclerEditAble.setLayoutManager(mEditAbleLayoutManager);
  45. mEditAbleListAdapter=new EditAbleListAdapter(this,this);
  46. mRecyclerEditAble.setAdapter(mEditAbleListAdapter);
  47.  
  48. for (int i=;i<;i++){
  49. mDataGoods.add(new DataGoods("Goods"+i,i,i,i*i));
  50. }
  51.  
  52. mEditAbleListAdapter.refreshDatas(mDataGoods);
  53. }
  54.  
  55. @Override
  56. public void onClick(View v) {
  57. switch (v.getId()) {
  58. case R.id.floating_btn_email:
  59. 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

  1. package com.zhn.edit.recycler;
  2.  
  3. import android.content.Context;
  4. import android.support.v7.widget.RecyclerView;
  5. import android.text.Editable;
  6. import android.text.TextWatcher;
  7. import android.view.LayoutInflater;
  8. import android.view.View;
  9. import android.view.ViewGroup;
  10. import android.widget.EditText;
  11. import android.widget.TextView;
  12.  
  13. import java.util.ArrayList;
  14. import java.util.List;
  15.  
  16. /**
  17. * Created by zhn
  18. * 2017/7/9 下午4:20
  19. */
  20. public class EditAbleListAdapter extends RecyclerView.Adapter{
  21.  
  22. public void refreshDatas(List<datagoods> mDataGoods) {
  23. mDatas.clear();
  24. mDatas.addAll(mDataGoods);
  25. notifyDataSetChanged();
  26. }
  27.  
  28. public interface EditAbleListAdapterListener{
  29. public void onEditTextChanged(int position,String value);
  30. }
  31.  
  32. private Context mContext;
  33. private List<datagoods> mDatas=new ArrayList<datagoods>();
  34.  
  35. private EditAbleListAdapterListener mListener;
  36. public EditAbleListAdapter(Context context,EditAbleListAdapterListener listener){
  37. this.mContext=context;
  38. this.mListener=listener;
  39. }
  40.  
  41. @Override
  42. public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  43. return new EditAbleListViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_editable_view,null));
  44. }
  45.  
  46. @Override
  47. public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
  48. ((EditAbleListViewHolder)holder).setContent(position,mDatas.get(position));
  49.  
  50. }
  51.  
  52. @Override
  53. public int getItemCount() {
  54. return mDatas.size();
  55. }
  56.  
  57. public class EditAbleListViewHolder extends RecyclerView.ViewHolder{
  58.  
  59. private TextView mTvItemNo;
  60. private TextView mTvGoodsName;
  61. private TextView mTvPrice;
  62. private EditText mEtNum;
  63. private TextView mTvTotalPrice;
  64.  
  65. private TxtWatcher mTxtWatcher;
  66.  
  67. public EditAbleListViewHolder(View itemView) {
  68. super(itemView);
  69.  
  70. mTvItemNo= (TextView) itemView.findViewById(R.id.tv_item_no);
  71. mTvGoodsName= (TextView) itemView.findViewById(R.id.tv_goods_name);
  72. mTvPrice= (TextView) itemView.findViewById(R.id.tv_price);
  73. mEtNum= (EditText) itemView.findViewById(R.id.et_num);
  74. mTvTotalPrice= (TextView) itemView.findViewById(R.id.tv_total_price);
  75.  
  76. mTxtWatcher=new TxtWatcher();
  77. }
  78.  
  79. public void setContent(int position,DataGoods data){
  80.  
  81. mTvItemNo.setText(String.valueOf(position+));
  82. mTvGoodsName.setText(data.getGoodsName());
  83. mTvPrice.setText(String.valueOf(data.getPrice()));
  84. mEtNum.setText(String.valueOf(data.getNum()));
  85. mTvTotalPrice.setText(String.valueOf(data.getTotalPrice()));
  86.  
  87. mTxtWatcher.buildWatcher(position,mTvTotalPrice);
  88.  
  89. mEtNum.setOnFocusChangeListener(new View.OnFocusChangeListener() {
  90. @Override
  91. public void onFocusChange(View v, boolean hasFocus) {
  92. if(hasFocus){
  93. mEtNum.addTextChangedListener(mTxtWatcher);
  94. }else{
  95. mEtNum.removeTextChangedListener(mTxtWatcher);
  96. }
  97. }
  98. });
  99. }
  100.  
  101. }
  102.  
  103. public class TxtWatcher implements TextWatcher{
  104.  
  105. private int mPosition;
  106. private TextView mTvTotalPrice;
  107.  
  108. public void buildWatcher(int position,TextView view){
  109. this.mPosition=position;
  110. this.mTvTotalPrice=view;
  111. }
  112.  
  113. @Override
  114. public void beforeTextChanged(CharSequence s, int start, int count, int after) {
  115.  
  116. }
  117.  
  118. @Override
  119. public void onTextChanged(CharSequence s, int start, int before, int count) {
  120. if(s.length()>){
  121. if(mListener!=null){
  122. mListener.onEditTextChanged(mPosition,s.toString());
  123. mTvTotalPrice.setText(String.valueOf(mDatas.get(mPosition).getPrice()*Double.parseDouble(s.toString())));
  124. }
  125. }else{
  126. if(mListener!=null){
  127. mListener.onEditTextChanged(mPosition,"");
  128. mTvTotalPrice.setText("");
  129. }
  130. }
  131. }
  132.  
  133. @Override
  134. public void afterTextChanged(Editable s) {
  135.  
  136. }
  137. }
  138.  
  139. }

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

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

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

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

Android RecyclerView嵌套EditView实时更新Item数据的更多相关文章

  1. android ListView中含有按钮事件实时更新ListView数据案例

    1.布局文件Listview <?xml version="1.0" encoding="utf-8"?> <android.support. ...

  2. Android网络开发之实时获取最新数据

    在实际开发中更多的是需要我们实时获取最新数据,比如道路流量.实时天气信息等,这时就需要通过一个线程来控制视图的更新. 示例:我们首先创建一个网页来显示系统当前的时间,然后在Android程序中每隔5秒 ...

  3. Android RecyclerView嵌套RecyclerView

    原理 RecyclerView嵌套RecyclerView的条目,项目中可能会经常有这样的需求,但是我们将子条目设置为RecyclerView之后,却显示不出来.自己试了很久,终于找到了原因:必须先设 ...

  4. WebSocket 实时更新mysql数据到页面

    使用websocket的初衷是,要实时更新mysql中的报警信息到web页面显示 没怎么碰过web,代码写的是真烂,不过也算是功能实现了,放在这里也是鞭策自己,web也要多下些功夫 准备 引入依赖 & ...

  5. Python tkinter库将matplotlib图表显示在GUI窗口上,并实时更新刷新数据

    代码 1 ''' 2 使用matplotlib创建图表,并显示在tk窗口 3 ''' 4 import matplotlib.pyplot as plt 5 from matplotlib.pylab ...

  6. Web实时更新客户端数据

    1        轮询方式实现客户端数据及时更新 在基于Web的即时通信.股票行情这样的系统中,需要客户端能够及时更新内容.由于B/S架构的特性(Http连接是无状态连接, 即服务器处理完客户的请求, ...

  7. solr实时更新mysql数据的方法

    第一步:创建core core是solr的特有概念,每个core是一个查询数据,.索引等的集合体,你可以把它想象成一个独立数据库,我们创建一个新core:名字[core1] 进入linux命令行,进入 ...

  8. WinForm DataGridView实时更新表格数据

    前言 一个特殊的项目没有用第三方控件库,但用到了DataGridView,由于是客户端产生的数据,所以原始数据源就是一个集合. 根据需要会向集合中添加数据项,或是修改某些数据项的值,但DataGrid ...

  9. Jquery无刷新实时更新表格数据

    html代码: <style> .editbox { display:none } .editbox { font-size:14px; width:70px; background-co ...

随机推荐

  1. Elasticsearch学习系列之配置文件详解

    ################################### Cluster ################################### #定义集群名称,默认是elasticse ...

  2. IntelliJ IDEA在行尾增加分号

    IntelliJ IDEA在行尾增加分号 Ctrl+Shift+Enter - 本身的含义是自动完成,如果需要的话,会在行尾添加分号:

  3. Codeforces Round #271 (Div. 2) D. Flowers (递推 预处理)

    We saw the little game Marmot made for Mole's lunch. Now it's Marmot's dinner time and, as we all kn ...

  4. 如何在其他js 引入main.js 中 vue 的实例?

    1.原因解析 经测试发现,代码先执行了 index.js >>  main.js >> Home.vue scr/api/index.js src/main.js src/co ...

  5. react 执行 yarn build 页面无法显示

    资源文件路径问题 如果你使用create-react-app创建项目,执行命令 yarn build 后,直接以静态方式打开build文件夹内的index.html,会看到页面显示出现问题,打开con ...

  6. 科普:google的数字图书馆

    https://books.google.com/ngrams Google Ngram Viewer,她利用google所拥有的所有图书作为资源,为你提供单词和短语历年使用次数的展示图标.数据化了数 ...

  7. 第一章:Android系统介绍android虚拟机

    学习android,我们是要了解他的历史的,这里我也就不在累述什么大家都知道的东东了,简单的介绍下内部的相关内容: 1:android虚拟机 我们学习java知道java用的是JVM虚拟机,而开发An ...

  8. SpringMVC_2

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=" ...

  9. [测试]单元测试框架NUnit

    说到测试,相信大家都或多或少了解. 按照各自分类,就自己知道包括 A.单元测试.集成测试.系统测试 B.白盒测试.黑盒测试 C.压力测试.性能测试.安全测试 ...... 反正是太多太多.就做开发以来 ...

  10. 【BJOI 2018】 求和

    [题目链接] 点击打开链接 [算法] 预处理i^k的前缀和,对于每次询问,树上倍增即可 时间复杂度 : O(nk + mlog(n)) [代码] #include<bits/stdc++.h&g ...