簡體   English   中英

刪除視圖不起作用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM