RemoveView无法正常工作

时间:2014-04-06 02:35:17

标签: android viewgroup

我遇到了一个不寻常的错误。我在自定义视图组中有这个。该方法接收一个视图并将其添加到布局,但我不断收到相同的错误:

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添加到视图之前使用runnable等待几秒钟。我没有尝试过这个,因为它似乎更像是一个黑客而不是一个解决方案。无论哪种方式,我希望有人可以帮助

谢谢!

PS:并不是说它应该重要,但我添加的这个视图的父级是我制作的自定义网格布局,其父级是一个viewpager。

编辑:

我做了一些断点和调试,从它的外观来看,网格有效地从子列表中删除了视图(debug),但子视图在其mParent变量(debug)中保持对同一网格的引用。这怎么可能

编辑:

活动:

Button button = new Button(mContext);
button.setOnClickListener(mClickListener);
(...)
Random random = new Random();
button.setText(random.nextInt(9999) + " ");

mCurrentGridLayout.addCustomView(button);

在CustomGridLayout viewgroup类中:

public void addCustomView(View view){
    if((ViewGroup)view.getParent() != null){
        ((ViewGroup)view.getParent()).removeView(view);
    }

    addView(view);
}

3 个答案:

答案 0 :(得分:9)

尝试创建自定义横幅时遇到了同样的问题。我相信这是因为布局过程中的动画,这就是延迟可以起作用的原因。在我的例子中,我创建了一个自定义的viewgroup类来消除动画延迟:

private class BannerLayout extends LinearLayout {
  public BannerLayout(Context context) {
     super(context);
  }

  @Override
  protected void removeDetachedView(View child, boolean animate) {
     super.removeDetachedView(child, false);
  }
}

一旦我这样做,一切都按预期工作。

希望它有所帮助!

答案 1 :(得分:0)

我遇到了同样的问题,Iree的回答确实对我有所帮助。原因是布局过渡的动画,但是如果我将其值设置为 null ,我将丢失过渡动画。因此,我要做的就是添加一个布局过渡侦听器,这样您可以在过渡完成时侦听该侦听器,然后将视图添加到其新的父级。

使用Java

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

使用Kotlin

a=sum(x in i for i in l)
print(a)

答案 2 :(得分:0)

如果您必须处理具有 viewGroups 或不具有 layoutTransition/** * 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

我建议仔细检查您的实现,因为有时可能会发生 # Input = élèvàtòr ôpëràtör # Output = ??l??v??t??r ??p??r??t??r use utf8; use open qw(:std :utf8); { while (<STDIN>) { $line = $_; # remove long span (), <> $line =~ s/[\(\)]//g; # remove long span [] with everything in between while ($line =~ s/\[[^\[\]]*\]//g) {;} while ($line =~ s/\<[^\<\>]*\>//g) {;} printf("$line"); } } 不能保证被调用或动画可能会在中间停止。就我而言,我在拖放操作中使用了它