พารามิเตอร์ LayoutInflater attachToRoot หมายถึงอะไร


201

LayoutInflater.inflateเอกสารไม่ตรงชัดเจนกับผมเกี่ยวกับวัตถุประสงค์ของattachToRootพารามิเตอร์

attachToRoot : ว่าควรแนบลำดับชั้นที่สูงเกินจริงไปที่พารามิเตอร์รูทหรือไม่? หากเป็นเท็จรูตจะใช้เพื่อสร้างคลาสย่อยที่ถูกต้องของ LayoutParams สำหรับมุมมองรูทใน XML

มีคนช่วยอธิบายรายละเอียดเพิ่มเติมโดยเฉพาะสิ่งที่รูตคือและอาจแสดงตัวอย่างของการเปลี่ยนแปลงพฤติกรรมระหว่างtrueและfalseค่า?


1
ที่เกี่ยวข้อง: ความรู้สึกของ LayoutInflater
blahdiblah

คำตอบ:


157

ตอนนี้หรือไม่ตอนนี้

ความแตกต่างที่สำคัญระหว่างพารามิเตอร์ "สาม" attachToRoot เป็นจริงหรือเท็จคือสิ่งนี้

เมื่อคุณใส่ attachToRoot

จริง:เพิ่มมุมมองเด็กไปยังผู้ปกครองRIGHT NOW
เท็จเพิ่มมุมมองเด็กที่พ่อแม่ไม่ได้ตอนนี้
เพิ่มในภายหลัง `

เมื่อเป็นที่ต่อมา ?

นั่นคือเมื่อคุณใช้เช่น parent.addView(childView)

ความเข้าใจผิดที่พบบ่อยคือถ้าพารามิเตอร์ attachToRoot เป็นเท็จมุมมองลูกจะไม่ถูกเพิ่มไปยังผู้ปกครอง ผิด
ทั้งสองกรณีมุมมองลูกจะถูกเพิ่มใน parentView มันเป็นเพียงเรื่องของเวลา

inflater.inflate(child,parent,false);
parent.addView(child);   

เทียบเท่ากับ

inflater.inflate(child,parent,true);

ใหญ่ไม่ไม่
คุณไม่ควรส่ง attachToRoot เป็นจริงเมื่อคุณไม่รับผิดชอบในการเพิ่มมุมมองลูกไปยังพาเรนต์
เช่นเมื่อเพิ่มแฟรกเมนต์

public View onCreateView(LayoutInflater inflater,ViewGroup parent,Bundle bundle)
  {
        super.onCreateView(inflater,parent,bundle);
        View view = inflater.inflate(R.layout.image_fragment,parent,false);
        .....
        return view;
  }

หากคุณส่งพารามิเตอร์ที่สามเป็นจริงคุณจะได้รับ IllegalStateException เนื่องจากผู้ชายคนนี้

getSupportFragmentManager()
      .beginTransaction()
      .add(parent, childFragment)
      .commit();

เนื่องจากคุณได้เพิ่มส่วนย่อยของเด็กใน onCreateView () โดยไม่ได้ตั้งใจ โทรเพิ่มจะบอกคุณว่ามุมมองของเด็กจะเพิ่มไปยังผู้ปกครองดังนั้นIllegalStateException
ที่นี่คุณจะไม่รับผิดชอบในการเพิ่ม childView FragmentManager เป็นผู้รับผิดชอบ ดังนั้นมักจะส่งเท็จในกรณีนี้

หมายเหตุ:ฉันได้อ่านแล้ว parentView จะไม่ได้รับ childView touchEvents ถ้า attachToRoot เป็นเท็จ แต่ฉันยังไม่ได้ทดสอบ


6
มีประโยชน์มากโดยเฉพาะในส่วนที่เกี่ยวกับFragmentManagerขอขอบคุณ!
CybeX

94

หากตั้งค่าเป็นจริงเมื่อโครงร่างของคุณขยายเกินจริงจะถูกเพิ่มไปยังลำดับชั้นการดูของ ViewGroup ที่ระบุในพารามิเตอร์ที่ 2 เป็นชายด์โดยอัตโนมัติ ตัวอย่างเช่นหากพารามิเตอร์รูทเป็นLinearLayoutมุมมองที่สูงเกินจริงของคุณจะถูกเพิ่มโดยอัตโนมัติเป็นลูกของมุมมองนั้น

หากตั้งค่าเป็นเท็จแสดงว่าเลย์เอาต์ของคุณจะขยายออก แต่จะไม่ถูกแนบไปกับเลย์เอาต์อื่น


17
ฉันสับสน ฉันได้รับ "เด็กที่ระบุแล้วมีข้อผิดพลาดของผู้ปกครอง" จนกว่าฉันจะอ่านคำตอบนี้ซึ่งสั่งให้ฉันใช้falseสำหรับattachToRootในช่วงที่ชิ้นส่วนของฉันonCreateViewนี้แก้ปัญหาและยังรูปแบบของชิ้นส่วนที่สามารถมองเห็นและใช้งาน ที่นี่หรือไม่
Jeff Axelrod

67
เนื่องจากแฟรกเมนต์แนบโครงร่างที่ส่งคืนจาก onCreateView โดยอัตโนมัติ ดังนั้นหากคุณแนบมันด้วยตนเองใน onCreateView มุมมองของคุณจะถูกแนบกับผู้ปกครอง 2 คน (ซึ่งก่อให้เกิดข้อผิดพลาดที่คุณพูดถึง)
โจเซฟเอิร์ล

11
ฉันสับสนเล็กน้อยที่นี่ @JosephEarl คุณพูดว่าถ้าตั้งไว้trueมุมมองจะถูกแนบกับพารามิเตอร์ตัวที่ 2 ซึ่งก็คือcontainerแต่ถ้าอย่างนั้นคุณพูดว่าแฟรกเมนต์เชื่อมต่อโดยอัตโนมัติonCreateView()ดังนั้นเพื่อความเข้าใจของฉันพารามิเตอร์ตัวที่สามไม่มีประโยชน์falseเสมอ?
unmultimedio

5
คุณส่งคืนมุมมองใน oncreateview จากนั้นจะถูกแนบโดยอัตโนมัติ หากคุณตั้งค่าแนบเป็นจริงจะเกิดข้อผิดพลาดขึ้น อย่างไรก็ตามเมื่อคุณขยายมุมมองในสถานการณ์แบบสแตนด์อโลนคุณสามารถเลือกแนบมุมมองเข้ากับคอนเทนเนอร์ได้โดยอัตโนมัติด้วยการตั้งค่าเป็นจริง ฉันแทบจะไม่เคยตั้งให้เป็นจริงแม้ว่าฉันจะเพิ่มมุมมองตัวเองเสมอ
frostymarvelous

7
@unmultimedio onCreateViewมันก็เป็นเพียงประโยชน์สำหรับดูรากที่ส่งกลับโดย หากคุณขยายโครงร่างเพิ่มเติมในมุมมองรูตนั้นหรือพองตัวในบริบทอื่น (เช่นในกิจกรรม) แสดงว่ามีประโยชน์
Joseph Earl

36

ดูเหมือนว่าข้อความจำนวนมากในการตอบสนอง แต่ไม่มีรหัสนั่นคือเหตุผลที่ฉันตัดสินใจที่จะรื้อฟื้นคำถามเก่านี้ด้วยตัวอย่างรหัสในการตอบสนองหลาย ๆ คนที่กล่าวถึง:

หากตั้งค่าเป็นจริงเมื่อโครงร่างของคุณขยายเกินจริงจะถูกเพิ่มไปยังลำดับชั้นการดูของ ViewGroup ที่ระบุในพารามิเตอร์ที่ 2 เป็นชายด์โดยอัตโนมัติ

สิ่งที่จริงหมายถึงในรหัส (สิ่งที่โปรแกรมเมอร์ส่วนใหญ่เข้าใจ) คือ:

public class MyCustomLayout extends LinearLayout {
    public MyCustomLayout(Context context) {
        super(context);
        // Inflate the view from the layout resource and pass it as child of mine (Notice I'm a LinearLayout class).

        LayoutInflater.from(context).inflate(R.layout.child_view, this, true);
    }
}

โปรดสังเกตว่าโค้ดก่อนหน้านี้กำลังเพิ่มเลย์เอาต์R.layout.child_viewเป็นชายด์MyCustomLayoutเนื่องจากattachToRootparam อยู่trueและกำหนด params เลย์เอาต์ของพาเรนต์ในลักษณะเดียวกับที่ฉันจะใช้โดยทางaddViewโปรแกรมหรือเหมือนกับว่าฉันทำสิ่งนี้ใน xml:

<LinearLayout>
   <View.../>
   ...
</LinearLayout>

รหัสต่อไปนี้อธิบายสถานการณ์เมื่อผ่านattachRootเป็นfalse:

LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setLayoutParams(new LayoutParams(
    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
linearLayout.setOrientation(LinearLayout.VERTICAL);
    // Create a stand-alone view
View myView = LayoutInflater.from(context)
    .inflate(R.layout.ownRootView, null, false);
linearLayout.addView(myView);

ในรหัสก่อนหน้านี้คุณระบุว่าคุณต้องการmyViewให้มันเป็นวัตถุรากของตัวเองและไม่ต้องแนบมันกับผู้ปกครองใด ๆ ในภายหลังเราเพิ่มมันเป็นส่วนหนึ่งของLinearLayoutแต่สำหรับสักครู่มันเป็นมุมมองแบบสแตนด์อะโลน (ไม่มีผู้ปกครอง)

สิ่งเดียวกันที่เกิดขึ้นกับ Fragments คุณสามารถเพิ่มพวกมันไปยังกลุ่มที่มีอยู่แล้วและเป็นส่วนหนึ่งของมันหรือแค่ผ่านพารามิเตอร์:

inflater.inflate (R.layout.fragment, null, false);

เพื่อระบุว่ามันจะเป็นของตัวเอง


1
จากทั้งหมดนี้เป็นประโยชน์มากที่สุด
Wahib Ul Haq

26

เอกสารและคำตอบก่อนหน้านี้ทั้งสองควรจะพอเพียงแค่ความคิดบางอย่างจากฉัน

inflateวิธีการที่ใช้ในการขยายไฟล์รูปแบบ ด้วยเลย์เอาต์ที่สูงเกินจริงเหล่านั้นคุณต้องสามารถแนบโดยตรงกับพาเรนต์ViewGroupหรือเพียงแค่ขยายลำดับชั้นการดูจากไฟล์เลย์เอาต์นั้นและทำงานกับมันนอกลำดับชั้นการดูแบบปกติ

ในกรณีแรกattachToRootพารามิเตอร์จะต้องมีการตั้งค่าเป็นtrue(หรือง่ายมากใช้inflateวิธีการที่ใช้รูปแบบไฟล์และผู้ปกครองรากViewGroup(ไม่ใช่null)) ในกรณีนี้การViewคืนค่าเป็นเพียงวิธีการViewGroupส่งผ่านในเมธอดViewGroupซึ่งจะเพิ่มลำดับชั้นมุมมองที่สูงเกินจริง

สำหรับตัวเลือกที่สองการคืนค่าViewเป็นรูทViewGroupจากไฟล์เลย์เอาต์ หากคุณจำการสนทนาครั้งสุดท้ายของเราจากinclude-mergeคำถามคู่นี่เป็นหนึ่งในเหตุผลสำหรับmergeข้อ จำกัด ของ (เมื่อไฟล์เลย์เอาต์ที่mergeเป็นรูตขยายเกินจริงคุณต้องระบุพาเรนต์และattachedToRootต้องตั้งค่าเป็นtrue) หากคุณมีไฟล์เลย์เอาต์ที่มีรูทmergeแท็กและattachedToRootถูกตั้งค่าfalseเป็นinflateเมธอดจะไม่มีอะไรให้ส่งคืนเนื่องจากmergeไม่มีค่าเทียบเท่า นอกจากนี้ตามที่เอกสารระบุว่าinflateเวอร์ชันที่มีการattachToRootตั้งค่าfalseเป็นสิ่งสำคัญเนื่องจากคุณสามารถสร้างลำดับชั้นมุมมองได้อย่างถูกต้องLayoutParamsจากผู้ปกครอง สิ่งนี้มีความสำคัญในบางกรณีซึ่งโดดเด่นที่สุดกับลูกของAdapterViewคลาสย่อยของViewGroupที่addView()ไม่สนับสนุนวิธีการตั้งค่า ฉันแน่ใจว่าคุณจำได้ว่าใช้บรรทัดนี้ในgetView()วิธีการ:

convertView = inflater.inflate(R.layout.row_layout, parent, false);

บรรทัดนี้รับรองว่าR.layout.row_layoutไฟล์ที่สูงเกินจริงมีการแก้ไขLayoutParamsจากAdapterViewคลาสย่อยที่ตั้งไว้บนรูViewGroupRelativeLayoutถ้าคุณจะไม่ได้รับการทำเช่นนี้คุณอาจมีปัญหาบางอย่างกับรูปแบบไฟล์ถ้ารากเป็น TableLayout/TableRowยังมีพิเศษและที่สำคัญบางอย่างและคุณควรตรวจสอบให้แน่ใจมุมมองในพวกเขามีความถูกต้องLayoutParamsLayoutParams


18

ตัวผมเองก็ยังสับสนเกี่ยวกับสิ่งที่เป็นวัตถุประสงค์ที่แท้จริงของattachToRootในinflateวิธีการ หลังจากการศึกษา UI เล็กน้อยในที่สุดฉันก็ได้รับคำตอบ:

ผู้ปกครอง:

ในกรณีนี้คือวิดเจ็ต / โครงร่างที่ล้อมรอบวัตถุมุมมองที่คุณต้องการขยายโดยใช้ findViewById ()

attachToRoot:

แนบมุมมองเข้ากับพาเรนต์ (รวมไว้ในลำดับชั้นพาเรนต์) ดังนั้นกิจกรรมแบบสัมผัสใด ๆ ที่มุมมองรับจะถูกถ่ายโอนไปยังมุมมองพาเรนต์ ตอนนี้มันขึ้นอยู่กับผู้ปกครองไม่ว่าจะต้องการสร้างความบันเทิงเหตุการณ์เหล่านั้นหรือไม่สนใจ หากตั้งค่าเป็นเท็จพวกเขาจะไม่ถูกเพิ่มเป็นลูกโดยตรงของผู้ปกครองและผู้ปกครองไม่ได้รับกิจกรรมการสัมผัสใด ๆ จากมุมมอง

หวังว่าสิ่งนี้จะช่วยขจัดความสับสน


คุณได้รับคำตอบแล้วที่นี่: stackoverflow.com/questions/22326314/…
Neon Warge

11

ฉันเขียนคำตอบนี้เพราะแม้หลังจากผ่านหน้า StackOverflow หลายหน้าฉันไม่สามารถเข้าใจได้อย่างชัดเจนว่า ด้านล่างเป็นวิธีพอง () ในคลาส LayoutInflater

View inflate (int resource, ViewGroup root, boolean attachToRoot)

ลองดูที่activity_main.xmlไฟล์button.xmlรูปแบบและMainActivity.javaฉันไฟล์ที่สร้าง

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

</LinearLayout>

button.xml

<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    LayoutInflater inflater = getLayoutInflater();
    LinearLayout root = (LinearLayout) findViewById(R.id.root);
    View view = inflater.inflate(R.layout.button, root, false);
}

เมื่อเราเรียกใช้รหัสเราจะไม่เห็นปุ่มในเค้าโครง นี่เป็นเพราะรูปแบบปุ่มของเราไม่ได้ถูกเพิ่มเข้าไปในเค้าโครงกิจกรรมหลักเนื่องจาก attachToRoot ถูกตั้งค่าเป็นเท็จ

LinearLayout มีเมธอด addView (มุมมองมุมมอง)ซึ่งสามารถใช้เพื่อเพิ่ม Views ไปยัง LinearLayout สิ่งนี้จะเพิ่มเค้าโครงปุ่มลงในเค้าโครงกิจกรรมหลักและทำให้ปุ่มปรากฏเมื่อคุณเรียกใช้รหัส

root.addView(view);

ลองลบบรรทัดก่อนหน้าและดูว่าเกิดอะไรขึ้นเมื่อเราตั้ง attachToRoot เป็นจริง

View view = inflater.inflate(R.layout.button, root, true);

อีกครั้งเราจะเห็นว่ารูปแบบปุ่มสามารถมองเห็นได้ นี่เป็นเพราะ attachToRoot แนบเค้าโครงที่พองตัวกับแม่ที่ระบุโดยตรง ซึ่งในกรณีนี้คือรูท LinearLayout ที่นี่เราไม่จำเป็นต้องเพิ่มมุมมองด้วยตนเองเหมือนที่เราทำในกรณีก่อนหน้าด้วยวิธีการ addView (มุมมองมุมมอง)

เหตุใดผู้คนจึงได้รับ IllegalStateException เมื่อตั้งค่า attachToRoot ว่าเป็นจริงสำหรับ Fragment

นี่เป็นเพราะแฟรกเมนต์คุณได้ระบุตำแหน่งที่จะวางโครงร่างแฟรกเมนต์ของคุณในไฟล์กิจกรรมของคุณ

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .add(R.id.root, fragment)
    .commit();

การเพิ่ม (int parent แฟรกเมนต์แฟรกเมนต์)เพิ่มแฟรกเมนต์ที่มีโครงร่างไปยังโครงร่างพาเรนต์ หากเราตั้ง attachToRoot เป็นจริงคุณจะได้รับ IllegalStateException: เด็กที่ระบุมี parent แล้ว เนื่องจากเลย์เอาต์ของแฟรกเมนต์ถูกเพิ่มไปยังเค้าโครงพาเรนต์ในเมธอด add ()

คุณควรส่ง false สำหรับ attachToRoot เสมอเมื่อคุณขยายแฟรกเมนต์ เป็นหน้าที่ของ FragmentManager ที่จะเพิ่มลบและแทนที่ Fragments

กลับไปที่ตัวอย่างของฉัน ถ้าเราทำทั้งสองอย่าง

View view = inflater.inflate(R.layout.button, root, true);
root.addView(view);

ในบรรทัดแรก LayoutInflater แนบเค้าโครงปุ่มกับเค้าโครงรูทและส่งกลับวัตถุมุมมองซึ่งมีเค้าโครงปุ่มเหมือนกัน ในบรรทัดที่สองเราเพิ่มวัตถุมุมมองเดียวกันลงในเค้าโครงรูทหลัก ผลลัพธ์นี้ใน IllegalStateException เดียวกับที่เราเห็นด้วย Fragments (ชายด์ที่ระบุมี parent แล้ว)

โปรดจำไว้ว่ามีวิธีการเติมข้อมูลเกินพิกัดอีกอันหนึ่งซึ่งตั้งค่า attachToRoot เป็นจริงตามค่าเริ่มต้น

View inflate (int resource, ViewGroup root)

คำอธิบายที่เรียบง่ายและชัดเจนสิ่งที่ฉันกำลังมองหา!
flyingAssistant

10

มีความสับสนมากมายในหัวข้อนี้เนื่องจากเอกสารประกอบสำหรับวิธีการพอง ()

โดยทั่วไปถ้า attachToRoot ถูกตั้งค่าเป็นจริงไฟล์เลย์เอาต์ที่ระบุในพารามิเตอร์แรกจะขยายและแนบมากับ ViewGroup ที่ระบุในพารามิเตอร์ที่สอง ณ ขณะนั้น เมื่อ attachToRoot เป็นเท็จไฟล์เลย์เอาต์จากพารามิเตอร์แรกจะขยายและกลับมาเป็นมุมมองและสิ่งที่แนบมุมมองใด ๆ จะเกิดขึ้นในเวลาอื่น

สิ่งนี้อาจไม่ได้มีความหมายอะไรมากนักเว้นแต่คุณจะเห็นตัวอย่างมากมาย เมื่อเรียก LayoutInflater.inflate () ภายในเมธอด onCreateView ของ Fragment คุณจะต้องส่งค่า false สำหรับ attachToRoot เนื่องจากกิจกรรมที่เชื่อมโยงกับ Fragment นั้นมีส่วนเกี่ยวข้องกับการเพิ่มมุมมองของ Fragment หากคุณขยายและเพิ่มมุมมองไปยังมุมมองอื่นด้วยตนเองในเวลาต่อมาเช่นด้วยเมธอด addView () คุณจะต้องส่งค่า false สำหรับ attachToRoot เนื่องจากไฟล์แนบจะมาในภายหลัง

คุณสามารถอ่านเกี่ยวกับตัวอย่างเฉพาะอื่น ๆ ที่เกี่ยวข้องกับไดอะล็อกและมุมมองที่กำหนดเองในโพสต์บล็อกที่ฉันเขียนเกี่ยวกับหัวข้อนี้

https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/


4

attachToRootตั้งค่าเป็นจริงหมายถึงinflatedViewจะเพิ่มลงในลำดับชั้นของมุมมองพาเรนต์ ดังนั้นอาจเป็น "เห็น" และสัมผัสเหตุการณ์สัมผัส (หรือการดำเนินการ UI อื่น ๆ ) โดยผู้ใช้ ไม่เช่นนั้นมันเพิ่งถูกสร้างขึ้นไม่ได้ถูกเพิ่มไปยังลำดับชั้นการดูใด ๆ ดังนั้นจึงไม่สามารถมองเห็นหรือจัดการเหตุการณ์การสัมผัสได้

สำหรับนักพัฒนา iOS ใหม่สำหรับ Android attachToRootตั้งค่าเป็นจริงหมายความว่าคุณเรียกวิธีนี้:

[parent addSubview:inflatedView];

ถ้าจะไปคุณอาจถาม: ทำไมฉันควรจะผ่านมุมมองของผู้ปกครองถ้าผมตั้งattachToRootเพื่อfalse? เป็นเพราะองค์ประกอบรูทในทรี XML ของคุณต้องการมุมมองพาเรนต์เพื่อคำนวณ LayoutParams บางรายการ (เช่นพาเรนต์ที่ตรงกัน)


0

เมื่อคุณกำหนดพาเรนต์ attachToRoot จะกำหนดว่าคุณต้องการให้ตัวเติมลมเชื่อมต่อกับพาเรนต์จริงหรือไม่ ในบางกรณีนี้ทำให้เกิดปัญหาเช่นใน ListAdapter มันจะทำให้เกิดข้อยกเว้นเพราะรายการพยายามที่จะเพิ่มมุมมองในรายการ แต่มันบอกว่ามันได้แนบมาแล้ว ในกรณีอื่น ๆ ที่คุณเพียงแค่ขยายมุมมองตัวเองเพื่อเพิ่มไปยังกิจกรรมมันอาจจะมีประโยชน์และช่วยให้คุณประหยัดบรรทัดของรหัส


1
ไม่ได้ให้ภาพที่ชัดเจนซึ่งเป็นคำตอบที่ดี
Prakhar1001

0

ตัวอย่างเช่นเรามีImageViewเป็นและLinearLayout RelativeLayoutLinearLayout เป็นลูกของ RelativeLayout มุมมองลำดับชั้นจะเป็น

RelativeLayout
           ------->LinearLayout

และเรามีไฟล์เลย์เอาต์แยกต่างหากสำหรับ ImageView

image_view_layout.xml

แนบกับราก:

//here container is the LinearLayout

    View v = Inflater.Inflate(R.layout.image_view_layout,container,true);
  1. ที่นี่ v มีการอ้างอิงของรูปแบบภาชนะเช่น LinearLayout.and ถ้าคุณต้องการตั้งค่าพารามิเตอร์เช่นsetImageResource(R.drawable.np);ของ ImageView คุณจะต้องค้นหามันโดยการอ้างอิงของผู้ปกครองเช่นview.findById()
  2. พาเรนต์ของ v จะเป็น FrameLayout
  3. LayoutParams จะเป็นของ FrameLayout

ไม่ยึดติดกับรูท:

//here container is the LinearLayout
    View v = Inflater.Inflate(R.layout.image_view_layout,container,false);
  1. ที่นี่ v ไม่มีเค้าโครงคอนเทนเนอร์อ้างอิง แต่อ้างอิงโดยตรงไปยัง ImageView ที่ขยายเกินจริงเพื่อให้คุณสามารถตั้งค่าพารามิเตอร์ได้view.setImageResource(R.drawable.np);โดยไม่ต้องอ้างอิงfindViewByIdซ้ำ แต่มีการระบุ container เพื่อให้ ImageView รับ LayoutParams ของ container ดังนั้นคุณสามารถพูดได้ว่าการอ้างอิงของ container นั้นเป็นแค่ LayoutParams เท่านั้น
  2. ดังนั้นในกรณีเฉพาะผู้ปกครองจะเป็นโมฆะ
  3. LayoutParams จะเป็นของ LinearLayout

0

attachToRoot ตั้งค่าเป็นจริง:

หาก AttachToRoot ถูกตั้งค่าเป็น true ดังนั้นไฟล์เลย์เอาต์ที่ระบุในพารามิเตอร์แรกจะถูกขยายและแนบกับ ViewGroup ที่ระบุในพารามิเตอร์ที่สอง

ลองนึกภาพเราระบุปุ่มในไฟล์เลย์เอาต์ XML ที่มีความกว้างของเลย์เอาต์และความสูงของเลย์เอาต์ที่กำหนดเป็น match_parent

<Button xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/custom_button">
</Button>

ตอนนี้เราต้องการเพิ่มปุ่มนี้ลงใน LinearLayout โดยทางโปรแกรมภายใน Fragment หรือ Activity หาก LinearLayout ของเราเป็นตัวแปรสมาชิกอยู่แล้ว mLinearLayout เราสามารถเพิ่มปุ่มได้ดังต่อไปนี้:

inflater.inflate(R.layout.custom_button, mLinearLayout, true);

เราระบุว่าเราต้องการขยายปุ่มจากแฟ้มทรัพยากรรูปแบบ จากนั้นเราบอก LayoutInflater ว่าเราต้องการแนบไฟล์กับ mLinearLayout พารามิเตอร์โครงร่างของเราได้รับการยกย่องเพราะเรารู้ว่าปุ่มได้รับการเพิ่มเข้าไปใน LinearLayout ประเภทของเลย์เอาต์ของปุ่มควรเป็นแบบ LinearLayout.LayoutParams

attachToRoot ตั้งค่าเป็นเท็จ (ไม่จำเป็นต้องใช้เท็จ)

หาก AttachToRoot ถูกตั้งค่าเป็นเท็จดังนั้นไฟล์เลย์เอาต์ที่ระบุในพารามิเตอร์แรกจะขยายออกและไม่ได้เชื่อมต่อกับ ViewGroup ที่ระบุในพารามิเตอร์ที่สอง แต่มุมมองที่ขยายเกินจริงจะได้รับ LayoutParams ของพาเรนต์ซึ่งทำให้มุมมองนั้น


มาดูกันว่าคุณต้องการตั้งค่า attachToRoot เป็นเท็จหรือไม่ ในสถานการณ์สมมตินี้มุมมองที่ระบุในพารามิเตอร์แรกของ inflate () ไม่ได้เชื่อมต่อกับ ViewGroup ในพารามิเตอร์ที่สอง ณ เวลานี้

เรียกคืนตัวอย่างปุ่มของเราจากก่อนหน้าซึ่งเราต้องการแนบปุ่มที่กำหนดเองจากไฟล์เลย์เอาต์ไปยัง mLinearLayout เรายังคงสามารถแนบปุ่มของเราเพื่อ mLinearLayout โดยส่งผ่านเป็นเท็จสำหรับ attachToRoot - เราเพียงแค่เพิ่มมันเองด้วยตนเองในภายหลัง

Button button = (Button) inflater.inflate(R.layout.custom_button,    mLinearLayout, false);
mLinearLayout.addView(button);

โค้ดสองบรรทัดนี้เทียบเท่ากับสิ่งที่เราเขียนไว้ก่อนหน้านี้ในโค้ดหนึ่งบรรทัดเมื่อเราส่งเป็น true สำหรับ attachToRoot โดยผ่านเท็จเราบอกว่าเราไม่ต้องการแนบมุมมองของเรากับราก ViewGroup เพียงแค่ เรากำลังบอกว่ามันจะเกิดขึ้นในบางจุดในเวลา ในตัวอย่างนี้เวลาอีกจุดหนึ่งเป็นเพียงวิธี addView () ที่ใช้ต่ำกว่าเงินเฟ้อทันที

ตัวอย่าง attachToRoot ที่ผิดต้องใช้งานเพิ่มอีกเล็กน้อยเมื่อเราเพิ่ม View ลงใน ViewGroup ด้วยตนเอง

attachToRoot ตั้งค่าเป็นเท็จ (จำเป็นต้องมีเท็จ)

เมื่อขยายและส่งคืนมุมมองของแฟรกเมนต์ใน onCreateView () ต้องแน่ใจว่าผ่านเป็นเท็จสำหรับ attachToRoot ถ้าคุณผ่านจริงคุณจะได้รับ IllegalStateException เพราะเด็กที่ระบุมีพ่อแม่อยู่แล้ว คุณควรระบุว่ามุมมองส่วนใดของคุณจะถูกนำกลับไปไว้ในกิจกรรมของคุณ เป็นหน้าที่ของ FragmentManager ที่จะเพิ่มลบและแทนที่ Fragments

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment =  fragmentManager.findFragmentById(R.id.root_viewGroup);

if (fragment == null) {
fragment = new MainFragment();
fragmentManager.beginTransaction()
    .add(R.id.root_viewGroup, fragment)
    .commit();
}

คอนเทนเนอร์ root_viewGroup ที่จะเก็บแฟรกเมนต์ของคุณในกิจกรรมของคุณคือพารามิเตอร์ ViewGroup ที่มอบให้คุณใน onCreateView () ในแฟรกเมนต์ของคุณ นอกจากนี้ยังเป็น ViewGroup ที่คุณส่งผ่านไปยัง LayoutInflater.inflate () อย่างไรก็ตาม FragmentManager จะจัดการแนบมุมมอง Fragment ของคุณไปยัง ViewGroup นี้ คุณไม่ต้องการแนบมันสองครั้ง ตั้ง attachToRoot เป็นเท็จ

public View onCreateView(LayoutInflater inflater, ViewGroup  parentViewGroup, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout,     parentViewGroup, false);

return view;
}

เหตุใดเราจึงให้ ViewGroup หลักของ Fragment ในครั้งแรกถ้าเราไม่ต้องการแนบไว้ใน onCreateView () ทำไมวิธี inflate () จึงขอให้ ViewGroup รูท?

ปรากฎว่าแม้ว่าเราจะไม่เพิ่มมุมมองที่พองใหม่ของเราลงใน ViewGroup หลักทันทีเราก็ควรใช้ LayoutParams ของผู้ปกครองเพื่อให้มุมมองใหม่กำหนดขนาดและตำแหน่งเมื่อใดก็ตามที่มีการแนบท้ายที่สุด

ลิงก์: https://youtu.be/1Y0LlmTCOkM?t=409


0

เพียงแบ่งปันบางจุดที่ฉันพบขณะทำงานในหัวข้อนี้

นอกจากคำตอบที่ได้รับการยอมรับแล้วฉันต้องการบางประเด็นที่อาจเป็นประโยชน์ได้บ้าง

ดังนั้นเมื่อผมใช้attachToRootเป็นจริงในมุมมองที่ถูกส่งกลับเป็นประเภทViewGroupรากเช่นเดียวกับผู้ปกครอง ViewGroup ซึ่งผ่านเป็นพารามิเตอร์สำหรับพอง (layoutResource, ViewGroup, attachToRoot)วิธีการไม่ได้จากประเภทรูปแบบซึ่งก็ผ่านไปได้ แต่ในattachToRootเป็นเท็จเราได้รับประเภทฟังก์ชันคืนของรูทกรุ๊ปของlayoutResourceนั้น

ให้ฉันอธิบายด้วยตัวอย่าง:

ถ้าเรามีLinearLayoutเป็นเลย์เอาต์หลักแล้วเราต้องการเพิ่มTextViewในมันผ่านฟังก์ชันขยาย

จากนั้นในการใช้attachToRootเป็นฟังก์ชั่นพองจริงคืนค่ามุมมองของประเภทLinearLayout

ในขณะที่ใช้attachToRootเนื่องจากฟังก์ชั่นinflate เท็จจะส่งคืนมุมมองของประเภทTextView

หวังว่าการค้นพบนี้จะช่วยได้บ้าง ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.