如何从ListView中获取项目以不在Android中使用循环视图?

时间:2015-01-28 00:02:52

标签: android android-listview

我目前有一个在item_exercise.xml中有条件显示的buttons_row:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/item_exercise"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:minHeight="?android:attr/listPreferredItemHeight"
                >

    <RelativeLayout
        android:id="@+id/text_row"
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <TextView
            android:id="@+id/exercise_name_value"
            style="@style/h5"
            android:text="@string/no_exercise"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="24dp"
            android:gravity="center_vertical"
            android:layout_centerVertical="true"
            android:layout_toStartOf="@+id/item_nav_image"
            />

        <ImageView
            android:id="@+id/item_nav_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_marginEnd="12dp"
            android:src="@drawable/ic_action_expand"
            android:contentDescription="@string/nav_expand_collapse"
            android:layout_centerVertical="true"
            />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/buttons_row"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/text_row"
        android:visibility="gone"
        >

        <ImageButton
            android:id="@+id/exercise_rename_btn"
            android:layout_width="120dp"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_action_mic"
            android:contentDescription="@string/rename"
            android:layout_marginStart="10dp"
            />

        <ImageButton
            android:id="@+id/exercise_delete_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_action_discard"
            android:contentDescription="@string/delete"
            android:layout_alignParentEnd="true"
            />
    </RelativeLayout>

</RelativeLayout>

我正在使用ViewHolder模式,当我从列表中删除练习时遇到问题,因为回收的视图(显示了buttons_row)被回收到另一个item_exercise项目上。我想知道如何解决这个问题?

Adapter.java:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    if (convertView == null) {
        convertView = View.inflate(mContext, R.layout.item_exercise, null);
        holder = new ViewHolder();
        holder.rithmId = 0;
        holder.exerciseName = (TextView) convertView.findViewById(R.id.exercise_name_value);
        holder.renameButton = (ImageButton) convertView.findViewById(R.id.exercise_rename_btn);
        holder.deleteButton = (ImageButton) convertView.findViewById(R.id.exercise_delete_btn);
        holder.buttonsRow = (RelativeLayout) convertView.findViewById(R.id.buttons_row);
        holder.navImage = (ImageView) convertView.findViewById(R.id.item_nav_image);
        holder.navShown = EXPAND;
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    final BaseAdapter baseAdapter = this;
    final ActiveRithm rithm = (ActiveRithm) getItem(position);
    holder.rithmId = rithm.getRithmID();
    holder.exerciseName.setText(rithm.getName());
    holder.displayNavCorrectly();

    convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            holder.toggleNav();
        }
    });

    holder.deleteButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //brings up confirmation dialog to delete this exercise/rithm
        }
    });
    return convertView;
}



static class ViewHolder {
    public int rithmId;
    public TextView exerciseName;
    public ImageButton renameButton;
    public ImageButton deleteButton;
    public String navShown;
    public RelativeLayout buttonsRow;
    public ImageView navImage;

    public void toggleNav() {
        Log.d(TAG, "navShown: " + navShown);
        if (navShown != null && navShown.equals(EXPAND)) {
            // display buttons
            buttonsRow.setVisibility(View.VISIBLE);
            // change image to be collapse
            navImage.setImageResource(R.drawable.ic_action_collapse);
            navShown = COLLAPSE;
        } else {
            // hide buttons
            buttonsRow.setVisibility(View.GONE);
            // change the image to be expand
            navImage.setImageResource(R.drawable.ic_action_expand);
            navShown = EXPAND;
        }
    }

    /**
     * Sometimes when you delete a rithm, the holder does not display the correct navigation
     * This method makes sure that recycled views are being displayed correctly.
     */
    public void displayNavCorrectly() {
        Log.d(TAG, "displayNavCorrectly: " + navShown);

        if (navShown != null && navShown.equals(EXPAND)) {
            // Hide buttons and image should be expand
            buttonsRow.setVisibility(View.GONE);
            navImage.setImageResource(R.drawable.ic_action_expand);
        } else {
            buttonsRow.setVisibility(View.VISIBLE);
            navImage.setImageResource(R.drawable.ic_action_collapse);
        }
    }
}

我认为我的displayNavCorrectly()方法会解决问题,但事实并非如此。我需要存储“状态”吗?我的对象内的UI?或者有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

最简单的方法是废弃回收视图并每次都给新视图充气。但这对于表现并不好。

总体而言,持有者模式用于避免在视图相同时调用findViewById查找视图。所以你不应该在你的持有人中拥有rithmId和navShown。

之后,您应该设置视图的状态。如果可以改变按钮的可见性,则可以为每个视图设置它。在您的情况下,您似乎希望隐藏或显示按钮。所以你的数据(在你的情况下是ActiveRithm)应该记住,而不是你的持有者。

所以当你得到你的对象时,用它来设置当前视图的当前状态

final ActiveRithm rithm = (ActiveRithm) getItem(position);
if (rithm.showingButtons) {
     holder.buttonsRow.setVisibility(View.VISIBLE);
} else {
     holder.buttonsRow.setVisibility(View.GONE);
}

然后在点击中,不要操纵持有者,而是操纵持有人的观点和数据的状态。

convertView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
          rithm.showingButtons = !rithm.showingButtons;
          if (rithm.showingButtons) {
              holder.buttonsRow.setVisibility(View.VISIBLE);
           } else {
              holder.buttonsRow.setVisibility(View.GONE);
           }
    }
});