java - 将适配器创建为 CustomView

  显示原文与译文双语对照的内容
0 0

我一直在尝试联机查找任何解决方案或示例有关如何做到这一点,但却什么也不有找到什么类似于我的问题

我有一个 LinearLayout我希望一辈子add/remove ViewsArrayList数据更改。

从我了解到的,唯一的办法就是创建 CustomView通过扩展 AdapterView并使用 ArrayAdapter.

可惜我不懂正确的数据流来解决这个问题。

哪里中指定 CustomView哪个View是容器? 可以我只是看 CustomViewLinearLayout那时我将已经实现?

编辑: 我强调我不需要 ListView. 我需要它的 CustomView

时间:原作者:2个回答

0 0

你无需扩展AdapterView生成你的adapter在自定义视图中的意见。 你可以扩展 LinearLayout并处理适配器。 最简单的方法将如下所示:

public class CustomAdapterView extends LinearLayout {
    private Adapter adapter;
    private final DataSetObserver observer = new DataSetObserver() {
        @Override
        public void onChanged() {
            refreshViewsFromAdapter();
        }
        @Override
        public void onInvalidated() {
            removeAllViews();
        }
    };
    public CustomAdapterView(Context context) {
        super(context);
    }
    public CustomAdapterView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public CustomAdapterView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    public Adapter getAdapter() {
        return adapter;
    }
    public void setAdapter(Adapter adapter) {
        if (this.adapter != null) {
            this.adapter.unregisterDataSetObserver(observer);
        }
        this.adapter = adapter;
        if (this.adapter != null) {
            this.adapter.registerDataSetObserver(observer);
        }
        initViewsFromAdapter();
    }
    protected void initViewsFromAdapter() {
        removeAllViews();
        if (adapter != null) {
            for (int i = 0; i < adapter.getCount(); i++) {
                addView(adapter.getView(i, null, this), i);
            }
        }
    }
    protected void refreshViewsFromAdapter() {
        int childCount = getChildCount();
        int adapterSize = adapter.getCount();
        int reuseCount = Math.min(childCount, adapterSize);
        for (int i = 0; i < reuseCount; i++) {
            adapter.getView(i, getChildAt(i), this);
        }
        if (childCount < adapterSize) {
            for (int i = childCount; i < adapterSize; i++) {
                addView(adapter.getView(i, null, this), i);
            }
        } else if (childCount > adapterSize) {
            removeViews(adapterSize, childCount);
        }
    }
}

与上述代码相同,只是一个简单的范例,它不会处理局面适配器.g返回不同类型的视图( e 。 Adapter#getViewTypeCount()返回大于1 ) 。

当然所有方法都定义为adding/removing LinearLayout可用视图,使他们能撞到适配器处理。 则可以将其禁用通过throw UnsupportedOperationException :

    @Override
    public void addView(View child) {
        throw new UnsupportedOperationException(
                "You cannot add views directly without adapter!");
    }

( 等等对于所有其他add/remove方法) 或通过重写它们来操作适配器是后备数据集( 其中定义应该强行实现自定义接口允许这些修改Adapter旁边接口) 。 在这两种情况下,请记住在代码中调用remove方法从超类添加适配器处理。

编辑: 并扩展与支持Adapter LinearLayout viewTypesCount是简单实现:

class CustomAdapterViewTypedImpl extends LinearLayout {
    private Adapter adapter;
    private SparseArray<List<View>> typedViewsCache = new SparseArray<List<View>>();
    private final DataSetObserver observer = new DataSetObserver() {
        @Override
        public void onChanged() {
            refreshViewsFromAdapter();
        }
        @Override
        public void onInvalidated() {
            removeAllViews();
        }
    };
    public CustomAdapterViewTypedImpl(Context context) {
        super(context);
    }
    public CustomAdapterViewTypedImpl(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public CustomAdapterViewTypedImpl(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    public Adapter getAdapter() {
        return adapter;
    }
    public void setAdapter(Adapter adapter) {
        if (this.adapter != null) {
            this.adapter.unregisterDataSetObserver(observer);
        }
        this.adapter = adapter;
        if (this.adapter != null) {
            this.adapter.registerDataSetObserver(observer);
        }
        initViewsFromAdapter();
    }
    protected void initViewsFromAdapter() {
        typedViewsCache.clear();
        removeAllViews();
        View view;
        if (adapter != null) {
            for (int i = 0; i < adapter.getCount(); i++) {
                view = adapter.getView(i, null, this);
                addToTypesMap(adapter.getItemViewType(i), view, typedViewsCache);
                addView(view, i);
            }
        }
    }
    protected void refreshViewsFromAdapter() {
        SparseArray<List<View>> typedViewsCacheCopy = typedViewsCache;
        typedViewsCache = new SparseArray<List<View>>();
        removeAllViews();
        View convertView;
        int type;
        for (int i = 0; i < adapter.getCount(); i++) {
            type = adapter.getItemViewType(i);
            convertView = shiftCachedViewOfType(type, typedViewsCacheCopy);
            convertView = adapter.getView(i, convertView, this);
            addToTypesMap(type, convertView, typedViewsCache);
            addView(convertView, i);
        }
    }
    private static void addToTypesMap(int type, View view, SparseArray<List<View>> typedViewsCache) {
        List<View> singleTypeViews = typedViewsCache.get(type);
        if(singleTypeViews == null) {
            singleTypeViews = new ArrayList<View>();
            typedViewsCache.put(type, singleTypeViews);
        }
        singleTypeViews.add(view);
    }
    private static View shiftCachedViewOfType(int type, SparseArray<List<View>> typedViewsCache) {
        List<View> singleTypeViews = typedViewsCache.get(type);
        if(singleTypeViews != null) {
            if(singleTypeViews.size() > 0) {
                return singleTypeViews.remove(0);
            }
        }
        return null;
    }
}
原作者:
0 0

有调查 AdapterView 实现。 其主要为你Extending DataSetobserver 794行。

仅仅给你一个大致的想法,
1 ) 创建类扩展DataSetObserver探密自定义视图类。

2 ) 自己Declare Interface从自定义视图用于获取View/Data细节并让你CustomAdapter实现它。

3 ) Whenever中发生更改时Array调用onChanged( ) /onInvalidated( DatSetObserver在自定义的) 。

如果你真的认真AdapterView然后按照此链接

原作者:
...