2013-08-07 38 views
4

我正在處理擴展ViewGroup的類來安排GridView的查看項目。Android:在ViewGroup中複製視圖元素

我可以很容易地在它裏面添加一個新的景觀項目:

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

但我想複製查看項目時,一個項目被拖過另一個。 我試圖通過

addView(getChildAt(index)) 

來複制該項目,這顯示了異常錯誤

指定的孩子已經有一個父。你必須對孩子的父母第一

調用removeView()我也試圖將所有視圖中的項目存儲在列表中,調用的方法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分離該視圖,並在該類內部複製它的多個副本(複製)。

任何幫助表示讚賞。

回答

1

謝謝你回答S.D和Ivan。

經過漫長的休息之後,我可以找到自己的答案,並在腦海中保留這些解決方案。

直接無法在視圖中添加克隆方法,並添加接口使代碼更復雜。

即使我的要求是克隆圖像被動態添加和來源未知的視圖。

必須完成一些技巧才能複製視圖, 首先獲取視圖的另一個實例,並在第二個視圖上覆制諸如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); 
1

複製對象需要很好的實現clone()方法。

我不認爲Android的視圖類做得很好,所以你可能需要創建一個自定義類型的視圖,它可以產生自己的副本。 View類確實有保存/恢復狀態的方法:使用onSaveInstanceState()onRestoreInstanceState(),您可以使用它複製View的狀態。

此外,您需要照顧在該視圖上註冊的事件偵聽器。

2

首先,您試圖再次添加同一個對象,這並沒有什麼意義 - 新視圖必須是單獨的對象,您必須首先複製原始對象,例如,採用.clone()方法。

但是,不幸的是,即使你做了,也不能將克隆的視圖添加到ViewGroup,這是爲什麼。

你唯一的例外是ViewGroupchecking your View's parent for null 結果所以,爲了增加克隆的觀點,你必須到您的視圖的mParent成員設置null,你不能這樣做,因爲直接,做的方法這是不公開的:View.assignParent()

你可以嘗試克隆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另一種實現方式,你是好去無必須修改你的容器的行爲。