CardView layout_width =“ match_parent” ไม่ตรงกับความกว้างของ RecyclerView หลัก


123

ฉันมีส่วนที่มี RecyclerView พร้อม layout_width = "match_parent":

<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity$PlaceholderFragment" />

รายการใน RecyclerView คือ CardView ที่มี layout_width = "match_parent":

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    card_view:cardCornerRadius="4dp">

    <TextView
        android:layout_gravity="center"
        android:id="@+id/info_text"
        android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="match_parent"
        android:textAppearance="?android:textAppearanceLarge"/>
</android.support.v7.widget.CardView>

ฉันขยายมุมมองรายการดังต่อไปนี้:

public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        CardView v = (CardView) LayoutInflater.from(parent.getContext())
                .inflate(R.layout.card_listitem, null, true);

        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

แต่เมื่อฉันเรียกใช้แอป CardView จะแสดงผลเป็น wrap_content ดังที่แสดงด้านล่าง:

CardsBug

โปรดทราบว่าสิ่งนี้ทำงานบนโปรแกรมจำลองไม่ใช่อุปกรณ์จริง

ฉันทำอะไรผิดพลาดหรือเป็นบั๊ก?


เมื่อขยาย CardView คุณกำลังจัดหามุมมองหลักด้วยพารามิเตอร์จริงหรือไม่
nhaarman

สวัสดี @NiekHaarman โปรดดูการแก้ไข ฉันเพิ่มรหัสพอง และใช่ฉันได้ส่งผ่านพารามิเตอร์จริง
ProgrAmmar

คำตอบ:


291

เอกสารสำหรับinflate:

ขยายลำดับชั้นมุมมองใหม่จากทรัพยากร xml ที่ระบุ พ่น InflateException หากมีข้อผิดพลาด

ID
รีซอร์สพารามิเตอร์สำหรับรีซอร์สโครงร่าง XML ที่จะโหลด (เช่น
มุมมองรูท R.layout.main_page) เพื่อเป็นพาเรนต์ของลำดับชั้นที่สร้างขึ้น (ถ้า attachToRoot เป็นจริง) หรือมิฉะนั้นอ็อบเจ็กต์ที่จัดเตรียมชุดของค่า LayoutParams สำหรับ root ของลำดับชั้นที่ส่งคืน (ถ้า attachToRoot เป็นเท็จ)
attachToRoot ควรแนบลำดับชั้นที่สูงเกินจริงกับพารามิเตอร์ root หรือไม่ ถ้าเป็นเท็จรูทจะใช้เพื่อสร้างคลาสย่อยที่ถูกต้องของ LayoutParams สำหรับมุมมองรูทใน XML เท่านั้น ส่งคืนมุมมองรากของลำดับชั้นที่สูงเกินจริง หากมีการระบุรูทและ attachToRoot เป็นจริงนี่คือรูท มิฉะนั้นจะเป็นรูทของไฟล์ XML ที่สูงเกินจริง

เป็นสิ่งสำคัญที่นี่ที่จะไม่ต้องจัดหาจริง แต่ต้องจัดหาผู้ปกครอง:

LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_listitem, parent, false);

การจัดหาparentView ช่วยให้ Inflater รู้ว่าควรใช้เค้าโครงใด การระบุfalseพารามิเตอร์บอกว่ายังไม่แนบพารามิเตอร์กับพาเรนต์ นั่นคือสิ่งที่RecyclerViewจะทำเพื่อคุณ


4
การแก้ปัญหาไม่ได้ทำงานสำหรับฉันเพราะ ListView ของเป็นlayout_width wrap_contentมันแปลกเพราะสิ่งนี้ไม่ควรส่งผลต่อมุมมองรายการ! ดังนั้นความเข้าใจของฉันก็คือเมื่อคุณระบุ false เป็นพารามิเตอร์ให้กับ layoutinflater ListView จะเพิ่มรายการลงใน ListView ด้วยพารามิเตอร์เลย์เอาต์ที่ตรงกับ ListView เอง! : 0
reubenjohn

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

1
ฉันกำลังขยายคำแนะนำของคุณและ match_parent ไม่ได้ผลสำหรับฉัน
Zapnologica

3
ฉันคิดว่าความเข้าใจที่ถูกต้องคือเมื่อคุณตั้งค่า attachToRoot เป็นเท็จคุณต้องจัดหาวัตถุที่มีค่า LayoutParams ที่กำหนดไว้ วัตถุนั้นไม่จำเป็นต้องเป็นผู้ปกครอง "... เป็นเพียงวัตถุที่ให้ชุดของค่า LayoutParams สำหรับรูทของลำดับชั้นที่ส่งคืน (ถ้า attachToRoot เป็นเท็จ) ... " แต่ฉันไม่เข้าใจว่าทำไม inflater ไม่สามารถอ่าน LayoutParams ที่กำหนดไว้ใน CardView ได้ แต่ต้องการ พารามิเตอร์ออบเจ็กต์อื่นเพื่อแจ้งให้ทราบหรือไม่
hjchin

1
ถ้าฉันใช้มุมมองแบบกำหนดเองจะจัดการกับมันอย่างไร ฉันหมายถึงViewHolder onCreateViewHolder(...) { View v = new MyItemView(parent.getContext); return new ViewHolder(v); }
Kross

66

ใช้ RelativeLayout เป็นพาเรนต์ไปยัง CardView ทันที

<RelativeLayout 
    android:layout_width="match_parent" ... >
    <CardView 
        android:layout_width="match_parent" ... >
    </CardView>
</RelativeLayout>

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

1
มันได้ผลสำหรับฉัน แต่ฉันไม่รู้ว่าทำไมวิธีนี้สามารถแก้ปัญหาได้ ไม่มีใครสามารถอธิบายได้ว่าทำไม?
Johnny

1
มันผ่านมานานแล้ว android x อยู่ระหว่างการผลิต แต่ยังไม่ได้รับการแก้ไขข้อบกพร่อง!
มูฮัมหมัด Naderi

วิธีที่ง่ายที่สุด
Abdurahman Popal

ฉันมีปัญหาที่คล้ายกันและสิ่งนี้ได้ผลสำหรับฉันในการแก้ไขความกว้างของมุมมองการ์ดของฉัน แต่ฉันมีปัญหาที่คล้ายกันกับความสูง? คุณช่วยแนะนำบางอย่างให้ฉันด้วยได้ไหม

12

สิ่งนี้ได้ผลสำหรับฉัน

 View viewHolder= LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item, null, false);
 viewHolder.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));
 return new ViewOffersHolder(viewHolder);

6

วิธีที่ฉันทำคือ:

View view = mInflater.inflate(R.layout.row_cardview, null, true);
            WindowManager windowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
            int width = windowManager.getDefaultDisplay().getWidth();
            view.setLayoutParams(new RecyclerView.LayoutParams(width, RecyclerView.LayoutParams.MATCH_PARENT));

คำอธิบาย: ใน onCreateViewHolde ของคุณเมื่อคุณได้รับมุมมองการ์ดรับความกว้างของหน้าจอจากนั้นตั้งค่าพารามิเตอร์เลย์เอาต์ตามมุมมองการ์ด


1
โปรดปรับปรุงเล็กน้อย โดยทั่วไปแล้วจะบอกว่า "ลองสิ่งนี้"
Drew

เพิ่มคำอธิบาย โปรดตรวจสอบและหากต้องการความช่วยเหลือเพิ่มเติมแสดงความคิดเห็นได้ที่นี่
Rahul


4

เพียงตั้งค่าพารามิเตอร์เค้าโครงใหม่

view.setLayoutParams(new RecyclerView.LayoutParams(
    RecyclerView.LayoutParams.MATCH_PARENT,
    RecyclerView.LayoutParams.WRAP_CONTENT
));

ฉันพบว่าการทำสิ่งนี้ใน onBindViewHolder () มีประโยชน์เมื่อใช้คลาสมุมมองแบบกำหนดเองที่สืบทอดมาจาก ConstraintLayout
Rasmusob

ไม่ใช่คำตอบที่ดีเพราะระยะขอบที่ถูกกำหนดให้กับเค้าโครงจะได้รับผลกระทบ
Emi Raz

4

การใช้งานตามค่าเริ่มต้นบังคับให้ใช้wrap_contentในตัวจัดการโครงร่างเริ่มต้น:

  @Override
public LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
}

สิ่งที่คุณต้องทำคือแทนที่วิธีนี้ใน LayoutManager ของคุณดังนี้:

  @Override
public LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
}


1

ใช้ card_view: contentPadding ด้วยค่าลบ

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    card_view:contentPadding="-4dp"
    card_view:cardElevation="0dp"
    android:layout_height="wrap_content">

มันได้ผลสำหรับฉัน


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