ListView适配器拧紧项目高度

时间:2013-07-26 22:59:04

标签: java android listview adapter

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

Gallery is here

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

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

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

所以适配器似乎认为“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>

1 个答案:

答案 0 :(得分:1)

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

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

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

    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();以便适配器重新创建视图。