我正在研究扩展ViewGroup的类,以安排GridView的View项目。
我可以通过以下方式轻松添加新的View项目:
ImageView view = new ImageView(context);
view.setImageBitmap(BitmapFactory.decodeResource( getResources(), R.drawable.ic_launcher));
addView(view);
或删除查看项目也很容易
removeViewAt(remove_index)
交换项目可以通过
完成addView(new_index, removeViewAt(old_index));
但我希望在将一个项目拖过另一个项目时复制View项目。 我试图通过
复制该项目addView(getChildAt(index))
这显示异常错误
指定的孩子已经有父母。您必须首先在孩子的父母上调用removeView()
我还尝试将所有视图项存储在List中,称为方法removeAllView()并再次在类中添加视图。
ArrayList<View> children = new ArrayList<View>();
for (int i = 0; i < getChildCount(); i++){
children.add(getChildAt(i));
}
children.add(getChildAt(index)); // duplicate this item
removeAllViews();
for (int i = 0; i < children.size(); i++){
addView(children.get(i));
}
这仍然显示如上所述的异常错误:
视图膨胀可能有效但我想复制相同的视图而不需要外部资源。
所以我想让方法从父ViewGroup中分离出View,并在类中复制(复制)它。
感谢任何帮助。
答案 0 :(得分:2)
首先,你试图再次添加同一个对象,这实际上没有意义 - 新视图必须是一个单独的对象,你必须首先复制原始对象,例如使用.clone()
方法。
但是,不幸的是,即使您这样做了,也无法将克隆视图添加到ViewGroup
,这就是原因。
您获得的例外情况是ViewGroup
checking your View
's parent for null
的结果
因此,为了添加克隆视图,您必须将视图的mParent
成员设置为null
,这是您无法直接执行的,因为执行此操作的方法不公开:{{ 3}}
您可以尝试在调用View
后克隆.removeViewAt()
,以便在克隆时没有父级,然后将原始视图添加回其位置,然后继续将克隆添加到所需位置,但作为SD提到你必须有一些克隆的麻烦加上这种方式非常模糊,需要ViewGroup
重新布局2次。
更好的解决方案是为每个视图分配一个标记,其中包含创建另一个视图所需的信息,并在需要克隆时使用它。
我会做这样的事情:
public interface ViewCloner {
public View clone(Context context);
}
public static class ImageViewCloner implements ViewCloner {
private int mImgResId;
public ImageViewCloner(int imgResourceId) {
this.mImgResId = imgResourceId;
}
@override
public View clone(Context context) {
ImageView view = new ImageView(context);
view.setImageBitmap(BitmapFactory.decodeResource( context.getResources(), mImgResId));
// Add the tag to the clone as well, so it, too, can be cloned
view.setTag(new ImageViewCloner(mImgResId));
return view;
}
}
// When creating the original view
int resId = R.drawable.ic_launcher;
ImageView view = new ImageView(context);
view.setImageBitmap(BitmapFactory.decodeResource( getResources(), resId));
view.setTag(new ImageViewCloner(resId));
// When cloning the view
ViewCloner vc = (ViewCloner) getChildAt(index).getTag();
View clone = vc.clone(getContext());
addView(clone);
对于您要使用的任何其他视图或组而不是单个ImageView
,只需创建ViewCloner
的另一个实现,您就可以不必修改容器的行为。
答案 1 :(得分:1)
复制对象需要良好实现clone()
方法。
我不认为Android的视图类做得很好,因此您可能需要创建一个可以生成自身副本的自定义视图类型。 View
类确实有保存/恢复状态的方法:使用onSaveInstanceState ()
和onRestoreInstanceState()
可以用来复制View的状态。
此外,您需要处理在该视图上注册的事件侦听器。
答案 2 :(得分:1)
感谢S.D和Ivan的答案。
经过漫长的休息后,我可以找到自己的答案,将这些解决方案记在心里。
直接无法在视图中添加Clone方法,添加界面会使代码更加复杂。
甚至我的要求是克隆动态添加图像且源未知的视图。
必须完成一些技巧才能复制视图, 首先得到另一个视图实例,并在第二个上复制属性,如drawable,background,padding等。
使用以下代码可以更轻松地解决问题。
// Create new Instance of imageView
ImageView view = new ImageView(context);
// Get the original view
ImageView org = (ImageView)getChildAt(index);
// Copy drawable of that image
view.setImageDrawable(org.getDrawable());
// Copy Background of that image
view.setBackground(org.getBackground());
// Copy other required properties
....
// Lastly add that view
addView(view);