我遇到了一个不寻常的错误。我在自定义视图组中有这个。该方法接收一个视图并将其添加到布局,但我不断收到相同的错误:
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);
}
答案 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");
}
}
不能保证被调用或动画可能会在中间停止。就我而言,我在拖放操作中使用了它