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.

Параметр Ідентифікатор
ресурсу для ресурсу макета XML для завантаження (наприклад, R.layout.main_page) кореневого
виду root, який є батьківським згенерованою ієрархією (якщо attachToRoot є правдою), або ж просто об'єктом, який надає набір значень LayoutParams для root повернутої ієрархії (якщо attachToRoot невірно.)
attachToRoot Чи слід завищену ієрархію додавати до кореневого параметра? Якщо значення false, root використовується лише для створення правильного підкласу LayoutParams для кореневого перегляду в XML. Повертає кореневий вигляд завищеної ієрархії. Якщо root був поставлений і attachToRoot є правдою, це root; інакше це корінь завищеного файлу XML.

Тут важливо , щоб НЕ поставити так, але нічого поставити батько:

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

Подання подання parentдає можливість інфлятору знати, які параметри компонування використовувати. Подання falseпараметра вказує йому ще не приєднувати його до батьківського. Ось що RecyclerViewбуде робити для вас.


4
Рішення не працює для мене , тому що ListView - х layout_widthбуло wrap_content. Це дивно, оскільки це не повинно впливати на перегляд списку! Тож я розумію, що коли ви вказуєте помилку як параметр для layoutinflater, ListView додає елементи списку до ListView з параметрами макета, що відповідають самому ListView! : 0
reubenjohn

1
Ви можете опублікувати трохи більше коду, тому що я думаю, що я роблю те саме, але насправді це не працює
rodi

1
Я надуваю те, як ти не працює для мене пропозиція та match_parent.
Zapnologica

3
Я думаю, що правильне розуміння полягає в тому, що при встановленні attachToRoot на false, вам потрібно поставити об'єкт із визначеним значенням LayoutParams. Цей об'єкт не обов'язково є батьківським. "... просто об'єкт, який надає набір значень LayoutParams для кореня повернутої ієрархії (якщо attachToRoot помилковий.) ..." Але я не розумію, чому інфлятор не може прочитати LayoutParams, визначені в CardView, але потрібно інший параметр об'єкта, щоб повідомити його?
hjchin

1
Якщо я використовую нестандартний вигляд, як з цим боротися? Я маю на увазіViewHolder onCreateViewHolder(...) { View v = new MyItemView(parent.getContext); return new ViewHolder(v); }
Кросс

65

Використовуйте RelativeLayout як безпосередній батько CardView.

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

Так, здавалося, це працює і для мене. Я використовував LinearLayout, і вищенаведена пропозиція не працювала, оскільки я вже робив саме це (тобто не прив’язувався до root, а надав батьків). Ви повинні робити як RelativeLayout +, не приєднуючи батьківського, а надаючи його.
кругляки

1
Це працює для мене, але я не знаю, чому це може вирішити проблему. Хтось може пояснити, чому?
Джонні

1
минули віки, андроїд х виробляється, все ж помилка не виправлена!
Мухаммед Надері

найпростіший спосіб.
Абдурахман

У мене була подібна проблема, і це працювало на мене, щоб виправити ширину перегляду моєї картки, але у мене є аналогічна проблема з висотою? Чи можете ви запропонувати мені щось для цього також?

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
будь ласка, покращуйте це трохи. В основному написано "Спробуйте це"
Дрю

Додано пояснення. Будь ласка, перевірте, і якщо вам потрібна додаткова допомога, прокоментуйте тут.
Рахул


4

Просто встановіть нові параметри компонування

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

Я виявив це робити в onBindViewHolder () корисним під час використання користувацького класу перегляду, який успадковується від ConstraintLayout.
Расмус

Це не є гарною відповіддю, оскільки маржа, встановлена ​​для макета, буде впливати.
Емі Роз

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

2

Це працює для мене

View view = inflator.inflate(R.layout.layout_item, ***null***, false);

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">

Це працювало для мене


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.