it-swarm.com.ru

CardView layout_width = "match_parent" не соответствует ширине родительского RecyclerView

У меня есть фрагмент с содержит 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

Обратите внимание, что это было запущено на эмуляторе, а не на реальном устройстве.

Я что-то не так делаю или это ошибка?

113
ProgrAmmar

Документы для inflate:

Раздуть новую иерархию представлений из указанного ресурса xml. Выдает InflateException, если есть ошибка.

Параметры
resource Идентификатор ресурса макета XML для загрузки (например, R.layout.main_page) root
view быть родителем сгенерированной иерархии (если attachToRoot имеет значение true), или же просто объект, который предоставляет набор значений LayoutParams для корня возвращаемой иерархии (если attachToRoot имеет значение ложный.)
attachToRoot Следует ли привязывать завышенную иерархию к корневому параметру? Если false, root используется только для создания правильного подкласса LayoutParams для корневого представления в XML. Возвращает корневой вид завышенной иерархии. Если был указан root и attachToRoot имеет значение true, это root; в противном случае это корень завышенного XML-файла.

Здесь важно не указывать истину, а указывать родителя :

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

Предоставление представления parent позволяет инфлятору знать, какие макеты использовать. Если указать параметр false, то он не должен подключать его к родителю. Это то, что RecyclerView сделает для вас.

275
nhaarman

Используйте RelativeLayout в качестве непосредственного родителя для CardView.

<RelativeLayout 
    Android:layout_width="match_parent" ... >
    <CardView 
        Android:layout_width="match_parent" ... >
    </CardView>
</RelativeLayout>
54
Ganesh Kanna

Это сработало для меня,

 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);
11
anurag_dake

Как я это сделал:

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, как только вы получите вид карты, получите ширину экрана, а затем установите соответствующий параметр макета для вида карты.

6
Rahul

Похоже, это исправлено в 'com.Android.support:recyclerview-v7:23.2.1'

Смотрите: RecyclerView wrap_content для дальнейшего обсуждения.

5
speedynomads

Просто установите новые параметры макета

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

Реализация по умолчанию заставляет использовать 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);
}
3
issamux

Это работает для меня

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

Используйте 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">

У меня сработало

1
Vladimir Salguero