[英]RemoveView not working
我有一個不尋常的錯誤。 我在自定義視圖組中有這個。 該方法接收一個視圖並將其添加到布局中,但我不斷收到相同的錯誤:
if((ViewGroup)view.getParent() != null){
((ViewGroup)view.getParent()).removeView(view);
}
addView(view); <--- Breakpoints puts the error on this line
錯誤是:
java.lang.IllegalStateException: 指定的孩子已經有一個父母。 您必須首先在孩子的父級上調用 removeView()。
在此周圍使用斷點表明“視圖”即使在父級上調用 removeView 后仍保留對其父級的引用..
有些人建議使用 runnable 在將其添加到視圖之前等待幾秒鍾。 我還沒有嘗試過這個,因為它看起來更像是一個黑客而不是解決方案。無論哪種方式,我都希望有人能夠提供幫助
謝謝!
PS:這並不重要,但我添加的這個視圖的父級是我制作的自定義網格布局,它的父級是一個viewpager。
編輯:
我做了更多的斷點和調試,從它的外觀來看,網格有效地從其子列表中刪除了視圖(調試),但子視圖在其 mParent 變量(調試)中保留了對同一網格的引用。 這怎么可能
編輯:
在活動中:
Button button = new Button(mContext);
button.setOnClickListener(mClickListener);
(...)
Random random = new Random();
button.setText(random.nextInt(9999) + " ");
mCurrentGridLayout.addCustomView(button);
在 CustomGridLayout 視圖組類中:
public void addCustomView(View view){
if((ViewGroup)view.getParent() != null){
((ViewGroup)view.getParent()).removeView(view);
}
addView(view);
}
我在嘗試創建自定義橫幅時遇到了同樣的問題。 我相信這是因為布局期間的動畫,這就是延遲可以工作的原因。 就我而言,我創建了一個自定義視圖組類來消除動畫延遲:
private class BannerLayout extends LinearLayout {
public BannerLayout(Context context) {
super(context);
}
@Override
protected void removeDetachedView(View child, boolean animate) {
super.removeDetachedView(child, false);
}
}
一旦我這樣做了,一切都按預期進行。
希望能幫助到你!
我遇到了同樣的問題, Iree的回答對我很有幫助。 原因是布局過渡的動畫,但如果我將其設置為null,我將丟失過渡動畫。 所以我所做的是添加一個布局轉換監聽器,這樣你就可以在轉換完成時監聽,然后將視圖添加到它的新父級。
使用 Java
LayoutTransition layoutTransition = ((ViewGroup)view.getParent()).getLayoutTransition();
layoutTransition.addTransitionListener(new TransitionListener(){
@Override
public void startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
}
@Override
public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
// now you can add the same view to another parent
addView(view);
}
});
使用 Kotlin
val layoutTransition = (view.parent as ViewGroup).layoutTransition
layoutTransition.addTransitionListener(object : LayoutTransition.TransitionListener {
override fun startTransition(transition: LayoutTransition?,container: ViewGroup?,view: View?,transitionType: Int) {
}
override fun endTransition(transition: LayoutTransition?,container: ViewGroup?,view: View?,transitionType: Int) {
// now you can add the same view to another parent
addView(view)
}
})
如果您必須處理具有layoutTransition
或不具有的viewGroups
,您可以執行以下操作:
/**
* When we don't have [LayoutTransition] onEnd is called directly
* Or
* function [onEnd] will be called on endTransition and when
* the parent is the same as container and view parent is null,
* and will remove also the transition listener
*/
private fun doOnParentRemoved(parent: ViewGroup, onEnd: () -> Unit) {
val layoutTransition = parent.layoutTransition
if (layoutTransition == null) {
onEnd.invoke()
return
}
val weakListener = WeakReference(onEnd)
layoutTransition.addTransitionListener(object : LayoutTransition.TransitionListener {
override fun startTransition(
transition: LayoutTransition?,
container: ViewGroup?,
view: View?,
transitionType: Int
) {
}
override fun endTransition(
transition: LayoutTransition?,
container: ViewGroup?,
view: View?,
transitionType: Int
) {
transition?.removeTransitionListener(this)
weakListener.get()?.invoke()
}
})
}
這是您可以使用它的方式:
sourceLayout.removeView(textView)
doOnParentRemoved(sourceLayout) {
// do your stuff when view has no parent
// add more logic to check is your view who called it in case of multiple views
}
我建議仔細檢查您的實現,因為有時不能保證調用endTransition
或動畫可以在中間停止。 就我而言,我在拖放操作中使用了它
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.