gpt4 book ai didi

java - 为 CustomView 创建适配器

转载 作者:搜寻专家 更新时间:2023-10-30 19:40:19 25 4
gpt4 key购买 nike

我一直在尝试在线寻找任何解决方案或示例,但找不到任何与我的问题相似的内容。

我有一个 LinearLayout,当 ArrayList 数据更改时,我想在其中添加/删除 Views

据我所知,唯一的方法是通过扩展 AdapterView 并使用 ArrayAdapter 创建一个 CustomView

很遗憾,我不了解解决此问题的正确数据流。

我在 CustomView 的什么地方指定哪个 View 是容器?我可以在 LinearLayout 上实现 CustomView 吗?

编辑:我强调 - 我不需要 ListView。我需要它用于 CustomView

最佳答案

您无需扩展 AdapterView 即可从自定义 View 中的适配器生成 View 。您可以扩展 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);
}
}
}

由于上面的代码只是一个简单的例子,它不处理适配器返回不同类型 View 的情况(例如 Adapter#getViewTypeCount() 返回大于 1 的数字)。

当然,所有为添加/删除 View 定义的 LinearLayout 方法都可用,因此它们可能会与您的适配器处理发生冲突。您可以通过抛出 UnsupportedOperationException 来禁用它们:

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

(对于所有其他添加/删除方法等等),或通过覆盖它们来操作适配器的支持数据集(应该强制实现您自定义的接口(interface),允许在 Adapter 接口(interface)旁边进行此类修改)。在这两种情况下,请记住在您的代码中从父类(super class)调用添加删除方法以进行适配器处理。

编辑:以及通过支持适配器的 viewTypesCount 扩展 LinearLayout 的简单实现:

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;
}
}

关于java - 为 CustomView 创建适配器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14550309/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com