首先在孩子的父母上调用removeView()

时间:2011-06-29 20:31:36

标签: android scrollview

首先是一点背景:

我在scrollview中有一个布局。首先,当用户在屏幕上滚动时,滚动视图滚动。但是,在一定量的滚动之后,我要禁用滚动视图上的滚动,将“滚动焦点”移动到子布局内的webview上。这样,scrollview会将所有滚动事件粘贴到其中的webview中。

因此,对于解决方案,当达到滚动阈值时,我从scrollview中删除子布局并将其放在scrollview的父级中。(并使scrollview不可见)。

// Remove the child view from the scroll view
scrollView.removeView(scrollChildLayout);

// Get scroll view out of the way
scrollView.setVisibility(View.GONE);

// Put the child view into scrollview's parent view
parentLayout.addView(scrollChildLayout);

一般理念:( - >表示包含)

之前:parentlayout - > scrollview - > scrollChildLayout

之后:parentLayout - > scrollChildLayout

上面的代码给了我这个例外:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
           at android.view.ViewGroup.addViewInner(ViewGroup.java:1976)
           at android.view.ViewGroup.addView(ViewGroup.java:1871)
           at android.view.ViewGroup.addView(ViewGroup.java:1828)
           at android.view.ViewGroup.addView(ViewGroup.java:1808)

你知道发生了什么吗?我显然在父母身上调用了removeView。

11 个答案:

答案 0 :(得分:281)

解决方案:

((ViewGroup)scrollChildLayout.getParent()).removeView(scrollChildLayout);
//scrollView.removeView(scrollChildLayout);

使用child元素获取对父元素的引用。将父级转换为ViewGroup,以便您可以访问removeView方法并使用它。

感谢@Dongshengcn提供的解决方案

答案 1 :(得分:22)

首先尝试从父视图中删除scrollChildLayout吗?

scrollview.removeView(scrollChildLayout)

或者从父视图中删除所有子项,然后重新添加它们。

scrollview.removeAllViews()

答案 2 :(得分:19)

onCreate with activity或onCreateView with fragment。

 if (view != null) {
    ViewGroup parent = (ViewGroup) view.getParent();
    if (parent != null) {
        parent.removeView(view);
    }
}
try {
    view = inflater.inflate(R.layout.fragment_main, container, false);
} catch (InflateException e) {

}

答案 3 :(得分:16)

好的,叫我偏执,但我建议:

  final android.view.ViewParent parent = view.getParent ();

  if (parent instanceof android.view.ViewManager)
  {
     final android.view.ViewManager viewManager = (android.view.ViewManager) parent;

     viewManager.removeView (view);
  } // if

没有instanceof的投射似乎是错误的。并且(感谢IntelliJ IDEA告诉我)removeViewViewManager界面的一部分。当一个完全合适的界面可用时,不应该强迫一个具体的类。

答案 4 :(得分:3)

你所要做的就是post()一个执行addView()的Runnable。

答案 5 :(得分:2)

科特林溶液

Kotlin使用as?简化了父转换,如果左侧为null或转换失败,则返回null。

(childView.parent as? ViewGroup)?.removeView(childView)

Kotlin扩展解决方案

如果要进一步简化此操作,可以添加此扩展名。

childView.removeSelf()

fun View?.removeSelf() {
    this ?: return
    val parentView = parent as? ViewGroup ?: return
    parentView.removeView(this)
}

如果此视图为null,父视图为null或父视图不是ViewGroup,则它将安全地不执行任何操作

注意::如果您还希望家长安全删除子视图,请添加以下内容:

fun ViewGroup.removeViewSafe(toRemove: View) {
    if (contains(toRemove)) removeView(toRemove)
}

答案 6 :(得分:1)

我正在调用parentView.removeView(childView)并且仍在显示childView。我终于意识到一个方法以某种方式被触发两次,并将childView添加到parentView两次。

因此,使用parentView.getChildCount()来确定父项在添加视图之前和之后的子项数。如果孩子被添加的次数太多,那么最顶层的孩子将被移除并且复制的childView仍然存在 - 看起来即使它正在工作,removeView仍在工作。

此外,您不应使用View.GONE删除视图。如果它被真正删除了,那么你就不需要隐藏它,否则它仍然在那里而你只是将它隐藏起来:(

答案 7 :(得分:1)

在我的情况下,我有BaseFragment,所有其他片段都继承自此。

所以我的观点是在OnDestroyView()方法

中添加这一行
@Override
public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    if (mRootView == null)
    {
        mRootView = (inflater == null ? getActivity().getLayoutInflater() : inflater).inflate(mContentViewResourceId, container, false);
    }
....////
}

@Override
public void onDestroyView()
{
    if (mRootView != null)
    {
        ViewGroup parentViewGroup = (ViewGroup) mRootView.getParent();

        if (parentViewGroup != null)
        {
            parentViewGroup.removeAllViews();
        }
    }

    super.onDestroyView();
}

答案 8 :(得分:0)

您也可以通过检查View的indexOfView方法来完成 如果indexOfView方法返回-1,那么我们可以使用。

ViewGroup的detachViewFromParent(v); 其次是 ViewGroup的removeDetachedView(v,true / false);

答案 9 :(得分:0)

我做错了所以我得到了这个错误是因为我没有实例化动态布局并为其添加子项所以得到了这个错误

答案 10 :(得分:0)

这是我的解决方案。

假设您有两个TextViews并将它们放在LinearLayout(名为ll)上。您将此LinerLayout放在另一个LinerLayout上。

< lm Linear Layout> 
       < ll Linear Layout> 
             <name Text view>
             </name Text view>
             <surname Text view>
             </surname Text view>
       </ll Linear Layout> 
</lm Linear Layout> 

如果要创建此结构,则需要将父级作为继承。

如果您想在onCreate方法this中使用它,那就足够了。

否则这是solition:

LinerLayout lm = new LinearLayout(this); // You can use getApplicationContext() also
LinerLayout ll = new LinearLayout(lm.getContext());
TextView name = new TextView(ll.getContext());
TextView surname = new TextView(ll.getContext());