먼저 자녀의 부모에서 removeView ()를 호출하십시오.


138

먼저 작은 배경 :

스크롤보기 안에 레이아웃이 있습니다. 처음에 사용자가 화면을 스크롤하면 스크롤보기가 스크롤됩니다. 그러나 일정량의 스크롤 후, 스크롤보기에서 스크롤을 비활성화하고 "스크롤 포커스"를 자식 레이아웃 내부의 웹 뷰로 이동했습니다. 이렇게하면 스크롤보기가 고정되고 모든 스크롤 이벤트가 내부의 웹보기로 이동합니다.

따라서 솔루션의 경우 스크롤 임계 값에 도달하면 스크롤보기에서 자식 레이아웃을 제거하고 스크롤보기의 부모에 배치합니다 (스크롤보기를 보이지 않게 만듭니다).

// 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를 명확하게 호출하고 있습니다.

답변:


289

해결책:

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

자식 요소를 사용하여 부모에 대한 참조를 얻습니다. removeView 메소드에 액세스하여 사용할 수 있도록 상위를 ViewGroup으로 캐스트하십시오.

솔루션을위한 @Dongshengcn에게 감사합니다


1
해결책은 맞지만 "scollView.removeView (scrollChildLayout)"가 작동하지 않는 이유는 무엇입니까? 두 줄이 같아야합니까?
andrea.rinaldi

@ andrea.spot처럼 보인다 scrollView.removeView(scrollChildLayout)상위 뷰 그룹에서있는 ScrollView 자체를 제거하기 위해,있는 ScrollView의 자식을 제거하지 않는 시도
드미트리 Gryazin

1
@ user25 나는 이것이 u에 너무 늦다는 것을 알고 있지만 null 포인터 예외는 부모가 비어 있기 때문에보기가 부모에 연결되지 않았 음을 의미합니다. 처음에는 부모가 없으므로 제거 할 것이 없습니다. if (mAdView.getParent()!=null) ((ViewGroup) mAdView.getParent()).removeView(mAdView);
Tarek

@kasgoku 도와주세요. 버튼 클릭시 상대 레이아웃으로 조각을 표시하려고합니다. 그러나 "오류가 지정된 자식에는 이미 부모가 있습니다. 먼저 자식의 부모에서 removeView ()를 호출해야합니다."라는 오류가 표시됩니다. 이 문제를 해결하는 방법?
Imranrana07

채팅 응용 프로그램 중 하나 인 응용 프로그램에서도이 오류가 발생했습니다. 이 문제를 해결하려고합니다. 해당 아이콘은 제거되었지만 이미지를 업로드하려면 아이콘이 다시 필요합니다. ( stackoverflow.com/q/58117428/10971384 ) 이것은 내 질문 링크입니다
Thangapandi

21

먼저 부모보기에서 scrollChildLayout을 제거 해보십시오.

scrollview.removeView(scrollChildLayout)

또는 부모보기에서 모든 자식을 제거하고 다시 추가하십시오.

scrollview.removeAllViews()

위의 질문에서 이미 코드에서 removeView를 호출하고 있습니다. removeAllViews ()도 작동하지 않습니다.
kasgoku 2016 년

removeView () / removeAllViews ()를 호출하는 부모입니까? 나는 매우 비슷한 일을하고 있으며 그것은 나를 위해 일하고있다.
dongshengcn 2016 년


@dongshengcn 도와주세요. 버튼 클릭시 상대 레이아웃으로 조각을 표시하려고합니다. 그러나 "오류가 지정된 자식에는 이미 부모가 있습니다. 먼저 자식의 부모에서 removeView ()를 호출해야합니다."라는 오류가 표시됩니다. 이 문제를 해결하는 방법?
Imranrana07

19

활동으로 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) {

}

15

좋아, 편집증이라고 부르지 만 나는 제안한다.

  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인터페이스의 일부입니다 . 완벽하게 적합한 인터페이스를 사용할 수있을 때 구체적인 클래스로 캐스트해서는 안됩니다.


3

addView ()를 수행하는 Runnable을 post ()하면됩니다.


작동하지 않았다. 이것이 내가 시도한 것입니다. scrollView.removeView (scrollChildLayout); scrollView.setVisibility (View.GONE); parentLayout.post (new Runnable () {@Public void run () 재정의 {parentLayout.addView (scrollChildLayout);}});
kasgoku 2016 년

1

parentView.removeView (childView)를 호출했지만 childView가 계속 표시되었습니다. 결국 메서드가 두 번 트리거되고 childView를 parentView에 두 번 추가했다는 것을 깨달았습니다.

따라서 parentView.getChildCount ()를 사용하여 뷰를 추가하기 전과 후에 부모가 가진 자식 수를 결정하십시오. 자식이 너무 많이 추가되면 최상위 자식이 제거되고 childView 사본이 남아 있습니다.

또한 View.GONE을 사용하여보기를 제거해서는 안됩니다. 그것이 정말로 제거되면 그것을 숨길 필요가 없습니다. 그렇지 않으면 여전히 거기 있으며 자신에게서 숨기고 있습니다 :(


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

다음 조각을 선택하고 너무 빨리 다시 누르셨습니까?
iamthevoid

1

코 틀린 솔루션

Kotlin은을 사용하여 부모 캐스팅을 단순화 as?하고 왼쪽이 null이거나 캐스팅이 실패하면 null을 반환합니다.

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

코 틀린 확장 솔루션

이것을 더 단순화하려면이 확장을 추가 할 수 있습니다.

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

0

indexOfView 메소드가 -1을 반환하면 View의 indexOfView 메소드를 확인하여 사용할 수 있습니다.

ViewGroup의 detachViewFromParent (v); 뒤에 ViewGroup의 removeDetachedView (v, true / false);


0

내가 잘못하고 그래서이 오류가 발생했습니다. 동적 레이아웃을 인스턴스화하지 않고 자식을 추가했기 때문에이 오류가 발생했습니다.


0

여기 내 해결책이 있습니다.

두 개가 있다고 말하고 ( ) TextViews에 두십시오 . 이것을 다른 곳에 놓을 것 입니다.LinearLayoutllLinerLayoutLinerLayout

< 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충분합니다.

그렇지 않으면 여기에 해결책이 있습니다.

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());
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.