【问题标题】:Duplicated layout reference in list view列表视图中的重复布局参考
【发布时间】:2011-10-14 19:13:49
【问题描述】:

我的列表视图发生了一件非常奇怪的事情。我正在创建一个带有按钮和一个 editText 的 ListView。

它的配置是这样的:[Button] [EditText] [Button],这些按钮的作用类似于“增量器”和“减量器”,每次单击以 1 个单位更新 EditText 的数值。 问题是,当我单击一个按钮时,几乎每次更改另一个列表视图元素的 editText (单击项的 editText 也会更改)。如果我单击这个错误更改项目的按钮,它也会更改第一个的 editText。它们基本上具有相同的按钮和editText引用,尽管它们具有带有数据的textView,并且它们之间的数据不同。

为了完成我创建和自定义的适配器:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if(convertView == null) {
            convertView = mInflater.inflate(R.layout.lastproduct_row, null);
            holder = new ViewHolder();
            holder.btnAddQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_add_qtd);
            holder.btnSubQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_sub_qtd);
            holder.etQuantidade = (EditText) convertView.findViewById(R.lastproduct_row.et_quantidade);                

            TextView tv;

            holder.tvList = new TextView[PRODUCTROW_INT_KEY.length];

            for(int i = 0; i < PRODUCTROW_INT_KEY.length; i++) {
                tv = (TextView) convertView.findViewById(PRODUCTROW_INT_KEY[i]);
                holder.tvList[i] = tv;                  
            }

            convertView.setTag(holder);
        }
        else {
            holder = (ViewHolder) convertView.getTag();
        }

        HashMap<String, String> hm = productsList.get(position);
        String key = hm.get(CODIGO_KEY);

        for(int i = 0; i < PRODUCTROW_INT_KEY.length; i++) {
            holder.tvList[i].setText(hm.get(PRODUCTROW_STR_KEY[i]));
        }

        holder.btnAddQtd.setTag(key+QTD_FLAG+ADD_ACTION);
        holder.btnSubQtd.setTag(key+QTD_FLAG+SUB_ACTION);
        holder.btnAddQtd.setOnClickListener(handle);
        holder.btnSubQtd.setOnClickListener(handle);

        if(novosEstoques.containsKey(key)) {
            holder.etQuantidade.setText(MyParseFunctions.parseCentesimal(novosEstoques.get(key).getQuantidade()));
        }

        return convertView;
    }

    class ViewHolder {
        private TextView []tvList;
        private Button btnAddQtd, btnSubQtd;
        private Button btnAddQtVol, btnSubQtVol;
        private EditText etQuantidade, etQtVolume;
    }

我向按钮添加了 onClick 侦听器,使用我的 listView 元素 ID(与其他信息连接)设置它们的标签。然后在我的事件监听器中,我只需获取按钮父视图(一个 LinearLayout)并使用 getViewAt() 从中获取 EditText:

    @Override
    public void onClick(View v) {
        String tag = (String) v.getTag();

        if(tag.contains(QTD_FLAG)) {
            String []info = ((String) v.getTag()).split(QTD_FLAG);
            float qtd;
            LinearLayout ll = (LinearLayout) v.getParent();
            ll.setBackgroundColor(Color.rgb(0, 128, 30));
            EditText et = (EditText) ll.getChildAt(2);

            qtd = Float.parseFloat(et.getText().toString().replace(",", "."));

            if(info[1].equals(ADD_ACTION)) {
                qtd++;

            }
            else if(info[1].equals(SUB_ACTION)) {
                if(qtd > 0)
                    qtd--;
            }

            Log.d("TESTE", "MODIFICAR KEY = "+info[0]);
            et.setText(qtd+"");
        }           
    }

我在此示例中使用 setBackgroundColor 来确认 LinearLayout 实例在 lisView 中重复。当我点击一个按钮时,它会被绘制在 2 个不同的列表视图项中。

任何人都可以指出我可以这样做吗?我发现有人有重复的 ListView 项目,我不知道这是不是我的情况,因为我的 ListView 中有 TextView,而且它们不相等,只有带有按钮和 editText 的 LinearLayout 部分是“共享的”。


我对我的 getView 方法进行了一些更改,它现在可以工作了!似乎每次调用 getView 方法时,我根本无法保证我的 editTexts 将被正确填充,我没有意识到这一点。因此,我进行的每个 getView 调用都设置了 editText 值,如果用户编辑 ET 值,我将其存储在 HashMap 中以在 getView 中恢复,如果 HashMap 中没有给定 editText 的条目,则将其设置为默认值值(零):

    ...
    if(convertView == null) {
            holder = new ViewHolder();
            holder.btnAddQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_add_qtd);
            holder.btnSubQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_sub_qtd);
            holder.etQuantidade = (EditText) convertView.findViewById(R.lastproduct_row.et_quantidade); 

            //Now it is easier to get etQuantidade reference in button
            //click handle, I just have to do:
            //    public onClick(View v) {
            //        EditText etButtonAssociated = (EditText) v.getTag();
            //        ...
            //    }
            holder.btnAddQtd.setTag(holder.etQuantidade);
            holder.btnSubQtd.setTag(holder.etQuantidade);

            holder.btnAddQtd.setOnClickListener(handle);
            holder.btnSubQtd.setOnClickListener(handle);
            ...
    }
    else {
        ...
    }
    holder.etQuantidade.setTag(key);

    if(novosEstoques.containsKey(key)) {
        holder.etQuantidade.setText(MyParseFunctions.parseCentesimal(novosEstoques.get(key).getQuantidade()));
    }
    else {
        holder.etQuantidade.setText("0");
    }

    return convertView;

【问题讨论】:

  • onClick 中的“et”在哪里?
  • 感谢您加入 StackOverflow。您的问题很好地组合在一起,所以让我们看看如何为您找到答案。 :)
  • @mozarty 我用这一行来做:EditText et = (EditText) ll.getChildAt(2);

标签: android listview duplicates custom-adapter


【解决方案1】:

以色列,

查看您的代码后,我想知道您做出的实施决定。由于每个按钮都“绑定”到特定的EditText,您是否考虑将那些ButtonsTag 设置为EditTextTag 可以是任何 Object,包括 UI 元素。这对于动态 UI 元素特别有用,例如运行时填充列表。

由于这是在您的 Adapter 中处理的,因此您不必担心重复的父母等。此外,您可以避免担心“找到”onClick() 中的控件,因为您会拥有它(它是标签)。我不确定您的项目到底需要什么,但这似乎是一个潜在可行的解决方案,除非您需要那些 Buttons 来完成其他任务。

注意事项 完成后请确保删除标签对EditText 的引用。否则,您将面临泄漏一些内存的风险。

模糊逻辑

【讨论】:

  • 您好,谢谢您的提示!它使代码更好,但重复的引用仍然存在=/我将我的 EditText 作为按钮的标签,并将一个 id 作为 editText 标签(我需要为每个 listView 元素存储这个 id)。当我开始我的活动并更改一些editText值(通常是第一个ET)时,另一个也会更改它的值(通常是我编辑第一个时当前视图之外的ET元素)。所以我把我的 id 作为标签放在每个 EditText 中,并在编辑时在 Toast 中显示它。令我惊讶的是,身份证是不同的!所以我认为问题出在我的适配器上。
  • 听起来很像。至少这让你知道从哪里开始。我会很快检查你的适配器...看看有没有什么突出的。
  • 以色列,您会考虑发布您的更新代码吗?特别是您的 getView() 和 onClick()?
  • 哦,我明白了!它看起来有点脏,但我让它工作,我认为这是通常的方法。我将更新问题,并对其进行改进。
  • 很高兴您找到了解决方案。它不是“脏”的,它是标准的 MVC(模型、视图、控制器)设计模式。您的视图(列表)不知道也不关心数据的来源,因此它不会以同样的方式“绑定”。您的适配器将您的模型(数据)应用于视图(列表)。但是(模型)实际上是由其他一些结构(Hashmap、数组、数据库等)控制的。一开始看起来有点尴尬,但你会越来越明白。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多