Android: Duplicating a View item in a ViewGroup

I am working on a class that extends ViewGroup to order View items for a GridView.

I can easily add a new View element inside:

ImageView view = new ImageView(context); view.setImageBitmap(BitmapFactory.decodeResource( getResources(), R.drawable.ic_launcher)); addView(view); 

Or removing a View item is also easy

 removeViewAt(remove_index) 

Changing an item can be done using

 addView(new_index, removeViewAt(old_index)); 

but I want to duplicate the View element when one element is dragged on top of another. I tried to duplicate an item

 addView(getChildAt(index)) 

And it shows an exception error

The specified child already has a parent. You must first call removeView () on the parent parent

I also tried to save all view elements in the list, called the removeAllView () method, and added the views in the class again.

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

This still shows an exception error, as indicated above:

Bloating a view may work, but I want to copy the same view without accessing an external resource.

So, I want the method to separate this view from the parent ViewGroup and make several copies (duplicates) inside the class.

Any help is appreciated.

+4
source share
3 answers

Thanks for the answer S.D. and Ivan.

After a long break, I was able to find my own answer, keeping these decisions in my mind.

The Clone method cannot be directly added to the view, and adding an interface complicates the codes.

Even my requirement was to clone a view for which the image was dynamically added and the source unknown.

Some tricks should only be done to copy the view, first of all, get a second instance of viewing and copying properties, such as drawable, background, padding, etc. on the second.

The solution was much simpler using the following codes.

 // 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); 
+1
source

Firstly, you are again trying to add the same object, which does not really make sense - the new view should be a separate object, you will have to duplicate the original first, for example. using the .clone() method.

But unfortunately, even if you did, you could not add a cloned view to the ViewGroup , which is why.

The exception you get is the result of the ViewGroup checking the View parent for null So, to add the cloned view, you need to set your mParent element to null , which you cannot do directly, because the method that does this is not public: View .assignParent ()

You can try to clone the View after calling .removeViewAt() so that it does not have a parent during cloning, then add the original view back to it and then add the clone to the desired location, but as an SD, you will need to bother a bit with cloning, and this method is very unclear and will require a ViewGroup to relay 2 times.

The best solution is to assign a tag to each view containing the necessary information to create another view like this and use it when you need to clone.

I would do something like this:

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

For any additional view or group that you want to use instead of a single ImageView , just create a different ViewCloner implementation and you will be fine going without changing the behavior of your container.

+2
source

Duplicating an object requires a good implementation of the clone() method.

I don't think Android view classes do this well, so you may need to create your own view type that can create a copy of itself. View class has methods for saving / restoring state: with onSaveInstanceState () and onRestoreInstanceState() , which you can use to copy the View state.

In addition, you will need to take care of event listeners registered in this view.

+1
source

Source: https://habr.com/ru/post/1495689/


All Articles