为选定列表项提供自定义视图的最佳方法

时间:2015-02-20 14:05:43

标签: android android-adapter android-adapterview

目标:对所选项目进行完全自定义布局,考虑到一次只能选择单个项目。

我不想让getViewTypeCount / getItemViewType参与选择,因为它们已经在此适配器中用于不同目的。

一个显而易见的选择是通过将适配器修改为以下内容来扩展自定义布局以指示所选项目:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
         ViewHolder holder;
         ... 
         // initialize convertView, holder, regular stuff

         // Now, the questionable part:

        if (position == mSelectedPosition) {
           // use custom layout to indicate highlight/selection
           convertView = inflater.inflate(R.layout.custom_selection_layout, parent, false);
        } else {
            // clear up selection 
            // also convertView could be recycled view and be of unexpected type 
        }
    }

在性能方面不应该太糟糕,因为只选择/夸大单个项目,但问题是convertedView可以是两种不同的类型,并且需要额外的演员/支票。
这种方法是不受欢迎的吗?

另一个选项可能是:将{/ 1}}中选定/未选定版本的布局组合在一起,并根据item_layout条件动态隐藏/显示其中一个版本。 这是个好主意吗?

最终,这样做的正确方法是什么?

由于

1 个答案:

答案 0 :(得分:1)

我会选择第一种方法。您的自定义布局应仅应用于整个列表中的一个视图,因此您唯一需要做的就是避免可以回收此类视图。我使用这种方法在列表中的特定点加载分隔符,我发现没有性​​能问题。

另一方面,让 - 让我们这么说 - 两者中的布局和改变可见性对我来说似乎不是最好的选择,因为你的观看者会变得很大(你需要携带所有里面的视图,我猜)在整个列表中只有一个孩子的好处。所有循环的,未经选择的观点每次都会面对位置检查,这对于大多数(除了一个)的情况都是不必要的。


对于识别视图一旦被回收,可能的方法是使用标签。

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

    if (position == mSelectedPosition) {
       convertView = inflater.inflate(R.layout.custom_selection_layout, parent, false);
       //here you upload convertView without the ViewHolder pattern, by using findViewById();
       //it's legit IMO because it gets called just once for the whole list.
       convertView.setTag("SELECTED_VIEW");
       return convertView;
    }

     ViewHolder holder;
     if (convertView == null || convertView.getTag("SELECTED_VIEW")) {
         //this convertView is not good. We inflate the regular layout
         convertView = inflater.inflate( ... );
     }

     //regular stuff
     ...
}