0

我有一个 ListView ,我想在其中显示来自多个适配器的项目,例如SimpleCursorAdapter来自不同查询的两个 s。每个适配器都有自己的布局,不必相同。

我尝试使用以下包装类:

public class MultiListAdapter implements ListAdapter {

    private List<ListAdapter> adapters;

    private static class PositionResult {
        ListAdapter adapter;
        int position;
        PositionResult(ListAdapter adapter, int position) {
            this.adapter = adapter;
            this.position = position;
        }
    }

    private PositionResult getInternalPosition(int position) {
        int i = 0;
        int result = position;
        for (ListAdapter adapter: adapters) {
            int count = adapter.getCount();
            if (result < count) {
                return new PositionResult(adapter, result);
            }
            result -= count;
            ++i;
        }
        return null;
    }

    public MultiListAdapter(List<ListAdapter> adapters) {
        this.adapters = adapters;
    }

    @Override
    public int getCount() {
        int result = 0;
        int i = 0;
        for (ListAdapter adapter: adapters) {
            int c = adapter.getCount();
            result += c;
        }
        return result;
    }

    @Override
    public Object getItem(int position) {
        PositionResult p = getInternalPosition(position);
        return p.adapter.getItem(p.position);
    }

    @Override
    public long getItemId(int position) {
        PositionResult p = getInternalPosition(position);
        return p.adapter.getItemId(p.position);
    }

    @Override
    public int getItemViewType(int position) {
        PositionResult p = getInternalPosition(position);
        return p.adapter.getItemViewType(p.position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        PositionResult p = getInternalPosition(position);
        return p.adapter.getView(p.position, convertView, parent);
    }

    @Override
    public int getViewTypeCount() {
        int result = 0;
        for (ListAdapter adapter: adapters) {
            result += adapter.getViewTypeCount();
        }
        return result;
    }

    @Override
    public boolean hasStableIds() {
        for (ListAdapter adapter: adapters) {
            if (!adapter.hasStableIds()) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean isEmpty() {
        for (ListAdapter adapter: adapters) {
            if (!adapter.isEmpty()) {
                return false;
            }
        }
        return true;
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        for (ListAdapter adapter: adapters) {
            adapter.registerDataSetObserver(observer);
        }

    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        for (ListAdapter adapter: adapters) {
            adapter.unregisterDataSetObserver(observer);
        }
    }

    @Override
    public boolean areAllItemsEnabled() {
        for (ListAdapter adapter: adapters) {
            if (!adapter.areAllItemsEnabled()) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean isEnabled(int position) {
        PositionResult p = getInternalPosition(position);
        return p.adapter.isEnabled(p.position);
    }

}

如果我在每个列表中只有几个元素,这将有效。但是如果它有更多,并且我需要滚动,那么列表就会完全中断,显示混合的元素,当我单击它们时,它们甚至给我的位置与实际位置不同。

上面的代码有什么问题?

4

1 回答 1

1

问题是该getItemViewType()方法为不同的视图返回相同的值,尽管实际的视图类型不同。这使得系统尝试重用不同类型的视图。

该方法应如下所示:

private int getMaxViewType() {
    int result = 1;
    for (ListAdapter adapter: adapters) {
        result = Math.max(result, adapter.getViewTypeCount());
    }
    return result;
}

@Override
public int getItemViewType(int position) {
    PositionResult p = getInternalPosition(position);
    return p.adapterId*getMaxViewType() + p.adapter.getItemViewType(p.position);
}
于 2012-09-13T12:57:08.397 回答