簡體   English   中英

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

[英]Call removeView() on the child's parent first

先說一點背景:

我在滾動視圖中有一個布局。 首先,當用戶在屏幕上滾動時,滾動視圖會滾動。 但是,經過一定量的滾動后,我要禁用滾動視圖上的滾動,將“滾動焦點”移動到子布局內的 webview 上。 這樣,滾動視圖和所有滾動事件 go 都會粘在其中的 webview 上。

因此,對於一個解決方案,當達到滾動閾值時,我從滾動視圖中刪除子布局並將其放在滾動視圖的父級中。(並使滾動視圖不可見)。

// 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 。

解決方案:

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

使用子元素獲取對父元素的引用。 將父級強制轉換為 ViewGroup,以便您可以訪問 removeView 方法並使用它。

感謝@Dongshengcn 的解決方案

嘗試先從其父視圖中刪除 scrollChildLayout 嗎?

scrollview.removeView(scrollChildLayout)

或者從父視圖中刪除所有子視圖,然后再次添加它們。

scrollview.removeAllViews()

在帶有活動的 onCreate 或帶有片段的 onCreateView 中。

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

}

好吧,叫我偏執狂,但我建議:

  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界面的一部分。 當一個完全合適的接口可用時,不應將其轉換為具體的 class。

Kotlin 解決方案

Kotlin 使用 as 簡化父級轉換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)
}

您所要做的就是 post() 一個執行 addView() 的 Runnable。

我正在調用 parentView.removeView(childView) 並且 childView 仍在顯示。 我最終意識到一個方法以某種方式被觸發了兩次,並將 childView 添加到 parentView 兩次。

因此,在添加視圖之前和之后使用 parentView.getChildCount() 來確定父級有多少個子級。 如果孩子被添加太多次,那么最上面的孩子將被刪除,並且副本 childView 仍然存在——看起來 removeView 正在工作,即使它是。

此外,您不應該使用 View.GONE 來刪除視圖。 如果它真的被移除了,那么你就不需要隱藏它,否則它仍然存在,你只是對自己隱藏它:(

就我而言,我有 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();
}

您也可以通過檢查 View 的 indexOfView 方法來做到這一點,如果 indexOfView 方法返回 -1 則我們可以使用。

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

我做錯了什么所以我得到這個錯誤是我沒有實例化動態布局並添加孩子所以得到這個錯誤

這是我的解決方案。

假設您有兩個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> 

當您想要創建此結構時,您需要將父級指定為 inheritance。

如果你想在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());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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