โทร RemoveView () บนแม่ของเด็กก่อน


138

พื้นหลังเล็กน้อยก่อน:

ฉันมีเค้าโครงภายใน scrollview ในตอนแรกเมื่อผู้ใช้เลื่อนบนหน้าจอ 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 อย่างชัดเจนบนพาเรนต์

คำตอบ:


289

สารละลาย:

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

ใช้องค์ประกอบลูกเพื่อรับการอ้างอิงถึงผู้ปกครอง ส่งพาเรนต์ไปยัง ViewGroup เพื่อให้คุณเข้าถึงเมธอด removeView และใช้สิ่งนั้น

ขอบคุณ @Dongshengcn สำหรับการแก้ปัญหา


1
วิธีแก้ปัญหานั้นถูกต้อง แต่ทำไม "scollView.removeView (scrollChildLayout)" ไม่ทำงาน? เส้นสองเส้นไม่ควรเหมือนกันหรือไม่
andrea.rinaldi

@ andrea.spot ดูเหมือนscrollView.removeView(scrollChildLayout)จะพยายามลบลูกของ scrollView ไม่ใช่เพื่อเอา ​​scrollView ตัวเองออกจาก ViewGroup แม่
Dmitry Gryazin

1
@ user25 ฉันรู้ว่ามันอาจจะสายเกินไปสำหรับคุณ แต่ข้อยกเว้นตัวชี้โมฆะเนื่องจากผู้ปกครองว่างเปล่าซึ่งหมายความว่ามุมมองไม่ได้แนบมากับผู้ปกครองใด ๆ เนื่องจากไม่มีผู้ปกครองตั้งแต่เริ่มต้นจึงไม่มีสิ่งใดที่จะลบ 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

คุณแน่ใจหรือว่ามันเป็นพาเรนต์ที่คุณเรียกใช้ removeView () / removeAllViews () ฉันกำลังทำสิ่งที่คล้ายกันมากและมันได้ผลสำหรับฉัน
dongshengcn

4
คุณสามารถดูผู้ปกครองได้โดยดูที่: view.getParent () developer.android.com/reference/android/view/
dongshengcn

@ 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 ที่บอกฉัน) removeViewเป็นส่วนหนึ่งของViewManagerอินเทอร์เฟซ และไม่ควรใช้คลาสที่เป็นรูปธรรมเมื่อมีอินเตอร์เฟสที่เหมาะสมอย่างสมบูรณ์


3

สิ่งที่คุณต้องทำคือโพสต์ () Runnable ที่ทำ addView ()


ใช้งานไม่ได้ นี่คือสิ่งที่ฉันพยายาม: scrollView.removeView (scrollChildLayout); scrollView.setVisibility (View.GONE); parentLayout.post (Runnable ใหม่ () {@Override โมฆะสาธารณะวิ่ง () {parentLayout.addView (scrollChildLayout);}});
kasgoku

1

ฉันกำลังเรียก parentView.removeView (childView) และ childView ยังคงปรากฏ ในที่สุดฉันก็รู้ว่าวิธีการบางอย่างถูกทริกเกอร์สองครั้งและเพิ่ม childView ลงใน parentView สองครั้ง

ดังนั้นใช้ parentView.getChildCount () เพื่อกำหนดจำนวนเด็กที่ผู้ปกครองมีก่อนที่คุณจะเพิ่มมุมมองและหลังจากนั้น หากเด็กถูกเพิ่มหลายครั้งเกินไปเด็กส่วนใหญ่ด้านบนจะถูกลบและคัดลอก childView ยังคงอยู่ - ซึ่งดูเหมือนว่า removeView จะทำงานแม้ว่ามันจะเป็น

นอกจากนี้คุณไม่ควรใช้ 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

Kotlin ลดความซับซ้อนของการแคสติ้งหลักด้วยการas?คืนค่า null ถ้าด้านซ้ายเป็นโมฆะหรือการแคสต์ล้มเหลว

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

โซลูชั่นเสริม Kotlin

หากคุณต้องการทำให้สิ่งนี้ง่ายยิ่งขึ้นคุณสามารถเพิ่มส่วนขยายนี้ได้

childView.removeSelf()

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

มันจะไม่ทำอะไรอย่างปลอดภัยหากมุมมองนี้เป็นโมฆะมุมมองพาเรนต์เป็นโมฆะหรือมุมมองพาเรนต์ไม่ใช่วิวเวอร์

หมายเหตุ:หากคุณต้องการให้ลบมุมมองลูกโดยผู้ปกครองอย่างปลอดภัยให้เพิ่มสิ่งนี้:

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

0

นอกจากนี้คุณยังสามารถทำได้โดยการตรวจสอบว่าวิธีการดูดัชนี indexOfView ถ้าวิธี indexOfView ส่งกลับ -1 แล้วเราสามารถใช้

detachViewFromParent ของ ViewGroup (v); ตามด้วย removeDetachedView ของ ViewGroup (v, จริง / เท็จ);


0

สิ่งที่ฉันทำผิดดังนั้นฉันจึงได้รับข้อผิดพลาดนี้คือฉันไม่ได้สร้างอินเทอร์แอกทีฟแบบไดนามิกและเพิ่มเด็กเข้าไปในนั้นเพื่อรับข้อผิดพลาดนี้


0

นี่คือทางออกของฉัน

ให้บอกว่าคุณมีสองอันTextViewsแล้วเอาไปใส่LinearLayout(ตั้งชื่อll) คุณจะใส่นี้อีกLinerLayoutLinerLayout

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

เมื่อคุณต้องการสร้างโครงสร้างนี้คุณต้องให้ parent เป็นมรดก

หากคุณต้องการใช้ใน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.