自定义ListView行中的可单击元素

时间:2015-01-07 10:34:06

标签: android listview

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

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

final int position = listView.getPositionForView(v);

此代码非常有效,每次单击特定行的TextView时,都会返回正确的位置。但是,当我旋转手机以更改配置然后单击TextView的任何时,返回的位置始终为-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);

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

2 个答案:

答案 0 :(得分:0)

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;

}

答案 1 :(得分:0)

你的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;
 }
} 

希望它能解决你的问题!

度过愉快的一天!