【问题标题】:ListView adapter screws up item heightsListView 适配器搞砸了项目高度
【发布时间】:2013-07-27 22:45:29
【问题描述】:

我有一个自定义BaseAdapter 用于ListView。行的通常布局看起来像第一张图片。

Gallery is here

但列表也可以有第二行字符串为空的项目,如第二张图片,如果第二行字符串的长度等于 0,则调用第二行视图的 setVisibility(View.GONE) 方法。

当列表中填满项目时,需要滚动查看最底部的项目,然后向下滚动,发现只有一行的项目,然后滚动回到顶部,其中一些-订单项可能会丢失第二行,就像第三张图片一样。

当从列表中删除一个项目时会发生类似的事情 - 位于其位置的项目将获得已删除项目的高度 - 就像第四张图片一样(忘记彩色条)。

因此,适配器似乎认为“Cookies”项目与“Something”项目......或其他东西相同。 为什么会这样?我该如何解决?

Another gallery to show exactly what happens

适配器代码:

public class CounterItemAdapter extends BaseAdapter{
    private Activity activity;
    private ArrayList<CounterItem> data;
    private SQLiteOpenHelper helper;
    private static LayoutInflater inflater = null;

    public CounterItemAdapter(Activity activity, ArrayList<CounterItem> data, SQLiteOpenHelper helper) {
        this.activity = activity;
        this.data = data;
        this.helper = helper;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return data.size();
    }


    @Override
    public CounterItem getItem(int position) {
        return data.get(position);
    }
    @Override
    public long getItemId(int position) {
        return getItem(position).getId();
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        if(convertView == null)
            view = inflater.inflate(R.layout.counter_list_item, null);
        TextView nameView = (TextView)view.findViewById(R.id.nameView);
        TextView descView = (TextView)view.findViewById(R.id.descView);
        final TextView countView = (TextView)view.findViewById(R.id.countView);
        ImageButton plusButton = (ImageButton)view.findViewById(R.id.plusButton);


        final CounterItem counterItem;
        counterItem = data.get(position);

        nameView.setText(counterItem.getName());
        if(counterItem.getDesc().length() == 0){
            descView.setVisibility(View.GONE);
            Log.d(HomeActivity.DEBUG_TAG, "GONE " + counterItem.getName() + ", LENGTH " + counterItem.getDesc().length());
        }else
            descView.setText(counterItem.getDesc());

        countView.setText(counterItem.getCount() + "");
        plusButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                counterItem.increment(helper.getWritableDatabase());
                countView.setText(counterItem.getCount() + "");
            }
        });
        View categoryView = view.findViewById(R.id.category);
        String colors[] = {"#ff99cc00",
                "#ff00ddff",
                "#ffffbb33",
                "#ffaa66cc",
                "#ffcc0000"};
        Random rand = new Random();
        String color = colors[rand.nextInt(colors.length)];
        categoryView.setBackgroundColor(Color.parseColor(color));

        return view;
    }
}

行布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:baselineAligned="false"
                android:descendantFocusability="blocksDescendants"
        >
    <LinearLayout
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_toLeftOf="@+id/linearLayout" android:layout_centerVertical="true"
            android:gravity="center_vertical" android:paddingLeft="12dp" android:paddingRight="12dp"
            android:paddingBottom="8dp" android:paddingTop="8dp" android:id="@+id/linearLayout1">
        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Counter name"
                android:id="@+id/nameView"
                android:textSize="16dp"/>
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
                  android:id="@+id/descView"
                  android:textSize="16dp"
                  android:textColor="@color/dividerGrey"
                  android:text="wtf"/>
    </LinearLayout>
    <LinearLayout
            android:orientation="horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:id="@+id/linearLayout" android:gravity="center_vertical" android:layout_centerVertical="true"
            android:paddingTop="8dp" android:paddingBottom="8dp">
        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="13"
                android:id="@+id/countView"
                android:textSize="30dp"
                android:layout_marginRight="13dp" android:textColor="@color/dividerGrey"/>
        <View android:layout_width="0.5dp" android:layout_height="48dp"
              android:background="@color/dividerGrey" android:id="@+id/plusDivider"/>
        <ImageButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/plusButton"
                android:src="@drawable/ic_button_increment"
                style="@android:style/Widget.Holo.Light.ActionButton"
                android:contentDescription="@string/plus_button"/>
    </LinearLayout>
</RelativeLayout>

【问题讨论】:

  • 让我们看看你适配器的代码。我认为问题可能在于您如何处理视图回收。

标签: java android listview adapter


【解决方案1】:

我想你在 ListView 中使用 ViewHolder 模式对吧? 我不想解释这个模式的全部用法,因为还有很多其他好的教程。

所以你描述的情况发生了,因为 listAdapter 重用了为每个对象膨胀的 convertView,所以如果你的 listview 的最后一个对象为你的第二行设置了 setVisibility(View.Gone) ,那么当你向上滚动所有其他孩子时变得可见的也将具有可见性(View.Gone)。

一个简单的解决方法是为每一行设置可见性 像这样:

    if (convertView == null) {
        convertView = (View) inflater.inflate(R.layout.view_item, null);
        viewHolder = new ViewHolder();
        viewHolder.itemName = (TextView) convertView.findViewById(R.id.item_name);
        viewHolder.secondLine = (TextView) convertView.findViewById(R.id.second_line)
        convertView.setTag(viewHolder);
    }
    else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    if(<-- your condition here-->){
        secondLine.setVisibility(View.VISIBLE);
    }
    else{
        secondLine.setVisibility(View.GONE);
    }

现在您已经为适配器添加了代码,我相信您的错误就在这里:

        if(counterItem.getDesc().length() == 0){
            descView.setVisibility(View.GONE);
            Log.d(HomeActivity.DEBUG_TAG, "GONE " + counterItem.getName() + ", LENGTH " + counterItem.getDesc().length());
        }else {
            **descView.setVisibility(View.VISIBLE);**
            descView.setText(counterItem.getDesc());
        }

如果需要,您应该添加代码以再次将其设置为可见,因为您的代码在其中一行消失时会永远消失。

更新

同样对于您的第二个问题,每当您从列表视图中删除一个项目时,您应该从适配器中删除该项目并调用 notifyDataSetChanged();为了让适配器重新创建视图。

【讨论】:

  • 我明天试试。谢谢!
  • 第一个画廊第四张图的情况如何?
  • 那里是什么情况导致我无法理解:)
  • “第二行”文本视图的文本被截断:/
  • 是您的项目布局的 layout_height 和 desc TextView 设置为“wrap_content”吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-13
  • 1970-01-01
  • 2010-11-01
  • 2020-10-13
相关资源
最近更新 更多