문제

I want to change the row layout when an specific button(action) is made.

public class DbCursorAdapter extends CursorAdapter {
private View selectedView;
private boolean isListSingleColumn = true;

private Cursor mCursor;
private final LayoutInflater mInflater;

private static final int TYPE_ITEM_SINGLE_COLUMN = 0;
private static final int TYPE_ITEM_MULTI_COLUMN = 1;

/**
 * DbCursorAdapter constructor
 * 
 * @param context
 *            - The context
 * @param cursor
 *            - The cursor used to make queries
 */
public DbCursorAdapter(Context context, Cursor cursor) {
    super(context, cursor, false);
    this.mContext = context;
    this.mCursor = cursor;
    this.mInflater = LayoutInflater.from(context);
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    final ViewHolder holder = (ViewHolder) view.getTag();

    String collection = mCursor.getString(mCursor
            .getColumnIndex(DatabaseHelper.COLUMN_COLLECTION));
    String fileName = mCursor.getString(mCursor
            .getColumnIndex(DatabaseHelper.COLUMN_FILE_NAME));

    holder.title.setText(fileName);

    if (collection.equals("true")) {
        // different folder icon for multi-column list
        holder.icon
                .setImageResource(isListSingleColumn ? R.drawable.ic_file_folder2
                        : R.drawable.ic_file_folder);
        holder.details.setText("");
    } else {
        String extension = fileName
                .substring(fileName.lastIndexOf(".") + 1);
        extension = extension.toLowerCase();

        String size = mCursor.getString(mCursor
                .getColumnIndex(DatabaseHelper.COLUMN_RESOURCE_LENGTH));
        String actualSize = MemoryManagerHelper.getInstance().getFileSize(
                Float.parseFloat(size));

        holder.icon.setImageResource(Utils.INSTANCE
                .getImageResourceForFileType(extension));
        holder.details.setText(actualSize);
    }
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
    /*
     * Inflates the item layout. Stores resource IDs in a in a ViewHolder
     * class to prevent having to look them up each time bindView() is
     * called.
     */
    final View itemView = mInflater.inflate(
            isListSingleColumn ? R.layout.explorer_row_single_column
                    : R.layout.explorer_row_multi_column, viewGroup, false);

    final ViewHolder holder = new ViewHolder();
    holder.title = (TextView) itemView.findViewById(R.id.rowtitle);
    holder.details = (TextView) itemView.findViewById(R.id.rowSubtitle);
    holder.icon = (ImageView) itemView.findViewById(R.id.icon);

    itemView.setTag(holder);
    return itemView;
}

@Override
public int getItemViewType(int position) {
    return isListSingleColumn ? TYPE_ITEM_SINGLE_COLUMN
            : TYPE_ITEM_MULTI_COLUMN;
}

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public void changeCursor(Cursor cursor) {
    super.changeCursor(cursor);
    this.mCursor = cursor;
}

/**
 * @return <b>true</b> if there is an item selected, <b>false</b> otherwise.
 */
public boolean getSelectedItemState() {
    return null == selectedView ? false : true;
}

/**
 * Set the selected item.
 * 
 * @param view
 *            The item which will be set as selected
 */
public void setSelectedItem(View view) {
    selectedView = view;
    view.setBackgroundResource(R.drawable.explorer_row_selected);
}

/**
 * If any item is selected we clear that item.
 */
public void clearSelectedItem() {
    if (null != selectedView) {
        selectedView.setBackgroundResource(android.R.color.transparent);
        // invalidate the selected item
        selectedView = null;
    }
}

private class ViewHolder {
    private TextView title;
    private TextView details;
    private ImageView icon;
}

public boolean isListSingleColumn() {
    return isListSingleColumn;
}

public void setListSingleColumn(boolean isListSingleColumn) {
    this.isListSingleColumn = isListSingleColumn;
}

The problem is that the layout isn't changed correctly for all items, some are displayed with the layout changed and some aren't. Also, when scrolling the layout for the items seem to change, sometimes it takes the correct layout, sometimes it takes the wrong layout.

I added an little workaround, detecting when the wrong layout is used and I tried to manually create the correct view, but this doesn't seem work.

Here is how I call my CursorAdapter:

/**
     * Change the number of columns the list view will upgrade.
     * 
     * @param item
     *            - The menu action button for the toggle option
     */
    private void changeGridColumns(MenuItem item) {
        if (isListSingleColumn) {
            listview.setNumColumns(2);
            item.setIcon(R.drawable.ic_menu_listgrid2);
            mAdapter.setListSingleColumn(false);
            mAdapter.notifyDataSetChanged();
        } else {
            // Set to display list with only 1 column
            listview.setNumColumns(1);
            item.setIcon(R.drawable.ic_menu_listgrid);
            mAdapter.setListSingleColumn(true);
            mAdapter.notifyDataSetChanged();
        }
        isListSingleColumn = !isListSingleColumn;
        mAdapter.clearSelectedItem();
    }

How can I fix this issue?

도움이 되었습니까?

해결책

That's not how you should be managing the layout change of the items. You should use the getItemViewType() and getViewTypeCount methods:

public static final int SINGLE = 0;
public static final int MULTIPLE = 1;

@Override
public int getItemViewType(int position) {          
    return isListSingleColumn ? SINGLE : MULTIPLE; // call notifyDataSetChanged when you modify isListSingleColumn
}

@Override
public int getViewTypeCount() {     
    return 2;
}

// in the newView() method:
final int position = cursor.getPosition();
final int type = getItemViewType(position);
View itemView 
if (type == SINGLE) {
    itemView = mInflater.inflate(R.layout.explorer_row_single_column, viewGroup, false);
} else {
   itemView = mInflater.inflate(R.layout.explorer_row_multi_column, viewGroup, false);
}
// rest of the code

Also, as its name implies, the bindView() method is to be used to bind data to the row view that you receive, I don't see why did you built the item's row again there.

다른 팁

I think I fixed the issue by using overriding getItemViewType method:

@Override
public int getItemViewType(int position) {
    return isListSingleColumn ? TYPE_ITEM_SINGLE_COLUMN
            : TYPE_ITEM_MULTI_COLUMN;
}

@Override
public int getViewTypeCount() {
    return 2;
}

I will also updated the code.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top