【问题标题】:Android listView cell recycling with variable-sized cellsAndroid listView 单元格回收与可变大小的单元格
【发布时间】:2014-01-24 15:57:18
【问题描述】:

我有一个列表视图。单元格具有可变高度。这在回收电池时会导致问题——回收的电池可能有错误的高度。关闭回收会使滚动太不稳定。如何在回收电池的同时获得正确的高度?

编辑:各地的高度各不相同。没有可能的值的简短列表。

【问题讨论】:

  • 每一行都有不同的大小吗?或者即使你有不同的高度,你知道你会有多少不同的高度?
  • 你用过getitemviewtype吗?
  • 我认为您的问题没有解决方案(无限不同的类型+回收)。无论如何,我赞成这个问题,所以让我们看看是否会出现一些有趣的答案
  • 我不明白如何在不需要引用每种类型的情况下拥有大量类型?这是真实案例还是假设案例?你能提供更多细节吗?
  • 高度取决于单元格中文字的高度。

标签: android listview


【解决方案1】:

两格类型

通常问题来自getView。我不确定您真正在寻找什么,因为您没有提供自定义适配器。但是,我给你一个例子,有 2 种不同的单元格类型,但单元格只包含一个文本视图。

在这种情况下,所有单元格都已通过回收充分调整。仔细阅读并扩展/修改以满足您的需求。

在你的CustomAdapter

private final class CustomArrayAdapter extends ArrayAdapter<String> {
    //the fastest is to get the layout inflater once and not each time getView is called
    private LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    public CustomArrayAdapter(Context context, int resource, int textViewResourceId, String[] objects) {
        super(context, resource, textViewResourceId, objects);
    }

    ...

    //here depending on the item position determine if cell is of type 1 or 2
    @Override
    public int getItemViewType(int position) {
        if (/* your type 1 criteria is match */) {
            return TYPE_1;
        } else {
            return TYPE_2;
        }
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        int type = getItemViewType(position);
        if (convertView == null) {
            holder = new ViewHolder();
            switch (type) {
                case TYPE_1:
                    convertView = mInflater.inflate(R.layout.row_of_type_1, parent, false);
                    holder.text = (TextView) convertView.findViewById(R.id.textview_type_1);
                    break;
                case TYPE_2:
                    convertView = mInflater.inflate(R.layout.row_of_type_2, parent, false);
                    holder.text = (TextView) convertView.findViewById(R.id.textview_type_2);
                    break;
             }
             convertView.setTag(holder);
         } else {
             holder = (ViewHolder) convertView.getTag();
         }

         //get the text for that specific cell and set it
         holder.text.setText(getMyCustomTextForThisCell());

         return convertView;
    }
}

static class ViewHolder {     
    TextView text;
}

单细胞型

如果您只需要一种类型的单元格,其中包含一个文本视图,并希望在所有单元格中放置不同长度的文本,并且单元格会自动调整其高度,只需在您的 CustomAdapter

private final class CustomArrayAdapter extends ArrayAdapter<String> {
    //the fastest is to get the layout inflater once and not each time getView is called
    private LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    public CustomArrayAdapter(Context context, int resource, int textViewResourceId, String[] objects) {
        super(context, resource, textViewResourceId, objects);
    }

    ...

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;

        if (convertView == null) {
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.row_type, parent, false);
            holder.text = (TextView) convertView.findViewById(R.id.textview_in_your_row);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        //get the text for that specific cell and set it
        holder.text.setText(getMyCustomTextForThisCell());

        return convertView;
    }
}

static class ViewHolder {     
    TextView text;
}

单元格布局

在示例中,我给出的文件 row_type.xml(您的行的布局文件)应该如下所示:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textview_in_your_row"
    android:paddingLeft="6dp"
    android:paddingRight="6dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

不要忘记android:layout_height="wrap_content",否则单元格不会调整大小


旁白

此旁注没有讨论 OP 问题,但是如果人们因为标题中的 细胞回收 词而来到这里,他们可能会对我给出一个完整的回收示例这一事实感兴趣此处带有 EditText 的单元格

The content of EditText contained into a Android ListView isn't saved

【讨论】:

  • 您的方法将是 IF OP 未添加的方法:“各地的高度各不相同。没有可能值的简短列表。 "
  • 我不明白这一点。他所说的“各地不同”是什么意思。我的意思是,我首先遇到了只有一种类型的回收问题,因为我没有在正确的地方进行 setTag。
  • 我不能确定,但​​我怀疑他的意思是所有视图都可以有不同的类型。由于两个视图需要具有相同的类型才能相互转换,如果它们都具有不同的类型,那么回收将无济于事
  • 它们都是同一种类型,因为它们的内容是同一种东西。但是,根据文本的长度,高度可能很高也可能很短。
  • 因此,如果我理解正确,您有一个带有 textview 的单元格并想要显示文本,但每个单元格都有不同长度的文本?如果是这样,那正是我的代码所做的。删除第二种类型并仅使用一种即可。重用的事情是获取标签并将标签设置在正确的位置。
【解决方案2】:

这是我使用 Xamarin 解决它的方法。

public override View GetView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        int type = GetItemViewType(position);
        if (convertView == null)
        {
            holder = new ViewHolder();
            convertView = context.LayoutInflater.Inflate(Resource.Layout.my_row_layout, parent, false);
            holder.myTextView = FindViewById<TextView>(Resource.Id.viewRow);
            convertView.Tag = holder;
        }
        else 
        {
            holder = (ViewHolder)convertView.Tag;
            int heightWeWant = heights[type];
            if (holder.myTextView.Height != heightWeWant) //height we have isn't what we want
            {
                AbsListView.LayoutParams parms = new AbsListView.LayoutParams(LinearLayout.LayoutParams.MatchParent, heightWeWant); //Width, Height //resize the view to the height we want
                convertView.LayoutParameters = parms;
            }
            convertView.Tag = holder;
        }

        holder.myText = "Some text here";

        return convertView;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多