【问题标题】:Clickable element in custom ListView row自定义 ListView 行中的可点击元素
【发布时间】:2015-01-07 10:34:05
【问题描述】:

我创建了一个带有自定义行的 ListView,并且在每个自定义行中我希望特定的 TextView 是可点击的。在我的自定义适配器的 getView 方法中,我为我的 TextView 设置了一个 onClickListener 并根据需要实现了 onClick(View v)。这就是问题出现的地方。

在 onClick(View v) 中,我需要相对于适配器数据单击的 TextView 行的位置(与 getView() 的位置参数不同)。在阅读了堆栈溢出,特别是这个article之后,获取被点击的TextView行的位置所需的魔法代码是:

final int position = listView.getPositionForView(v);

这段代码效果很好,每次我单击特定行的 TextView 时,都会返回正确的位置。但是,当我旋转手机以更改配置然后单击 TextView 的 any 时,返回的位置始终为 -1。将手机旋转回原始配置也可以保持这种在按下任何 TextView 时返回 -1 的行为。

查看 getPositionForView 的文档,如果视图“不对应于列表项(或当前不可见)”,似乎返回 -1(INVALID_POSITION)。为什么会这样?显然,我什至能够点击 TextView,视图必须在屏幕上可见。

如果重要的话,我正在使用 convertView 和 ViewHolder 模式来优化 ListView。

我错过了什么?

更新: 只是为了帮助更好地可视化,这是我的 getView 大致的样子

getView(int position, View convertView, ViewGroup parent) {
        final CustomViewHolder holder;
        View = rowView;
        if (convertView == null) {
            rowView = inflater.inflate(R.layout.listitem, parent, false);
            holder = new CustomViewHolder(rowView);

            holder.textview.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    final int position = listView.getPositionForView(v);
                    //position is always -1 after configuration change
                    Log.d(TAG, "Like button pushed at position: " + position);

                }
            });
            rowView.setTag(postHolder);
        } else {
            rowView = convertView;
            postHolder = (PostListUserPostHolder) convertView.getTag();
        }

        //fill list item with data
    }
    return rowView;
}

更新 #2 我似乎已经找到了解决办法。我没有将片段对 ListView 的引用传递给适配器,而是将片段本身的引用传递给适配器。然后我在片段中提供了一个 getter 方法来获取 ListView,然后使用该行:

final int position = fragment.getListView().getPositionForView(v);

我会认为这与我所做的基本相同,但似乎并非如此。如果有人可能对可能发生的事情有所了解,将不胜感激。否则,我很高兴代码现在按预期工作!

【问题讨论】:

    标签: android listview


    【解决方案1】:
    getView(int position, View convertView, ViewGroup parent) {
            final CustomViewHolder holder;
    
        if (convertView == null) {
            rowView = inflater.inflate(R.layout.listitem, parent, false);
            holder = new CustomViewHolder();
            convertView .setTag(holder );
        }
        else {
    
            holder= (CustomViewHolder ) convertView.getTag();
        }
    
            holder.textview.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    final int position = listView.getPositionForView(v);
                    //position is always -1 after configuration change
                    Log.d(TAG, "Like button pushed at position: " + position);
    
                }
            });
    
        } 
    
        //fill list item with data
    }
    return convertView;
    

    }

    【讨论】:

      【解决方案2】:

      您的 getView() 有点奇怪。您的持有人的字段textview 从未初始化?

      持有者的用处是限制findViewById方法的使用。

      这是我会使用的骨架:

      static class ViewHolder {
        public TextView textview;
      }
      
      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
         View rowView = convertView;
      
         // reuse views
        if (rowView == null) {
             LayoutInflater inflater = context.getLayoutInflater();
             rowView = inflater.inflate(R.layout.listitem, null);
             // configure view holder
             ViewHolder viewHolder = new ViewHolder();
             viewHolder.textview= (TextView) rowView.findViewById(R.id.textview);
             rowView.setTag(viewHolder);
        }
        else {
      
            ViewHolder holder = (ViewHolder) rowView.getTag();
        }
      
         // fill data
         holder.textview.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  final int position = listView.getPositionForView(v);
                  //position is always -1 after configuration change
                  Log.d(TAG, "Like button pushed at position: " + position);
      
              }
          });
      
          return rowView;
       }
      } 
      

      希望它能解决你的问题!

      祝你有美好的一天!

      【讨论】:

      • 是的,ViewHolder 的所有 findViewById 都在一个单独的类中,因此它们不是在 getView() 中编写的。我似乎找到了解决方案,所以我将更新 OP。
      猜你喜欢
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-09
      • 2014-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多