Сделать ширину горизонтальных элементов просмотра ресайклера 70% ширины экрана

Я пытаюсь создать этот эффект

Design image

Я использую вид переработчика, но моя проблема в том, что каждая карта составляет 100% ширины экрана, а не 70%.

Вот код XML для каждого элемента

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rowLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/scale_20dp">

    <LinearLayout
        android:id="@+id/button_parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <android.support.v7.widget.CardView
            android:id="@+id/card_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android:id="@+id/currentYear"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:background="@drawable/paymentscreengrey"
                android:gravity="center"
                android:orientation="vertical"
                android:paddingLeft="35dp"
                android:paddingTop="@dimen/scale_50dp">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/scale_20dp"
                    android:text="****   ****   ****   5432"
                    android:textColor="@color/white"
                    android:textSize="@dimen/scale_20dp" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="2345"
                    android:textColor="@color/white"
                    android:textSize="@dimen/scale_16dp" />

Ответ 1

Если вы хотите, чтобы первый элемент был выровнен по левому краю (то есть воспроизведите то, что на скриншоте), создайте подкласс LinearLayoutManager и переопределите три метода generate*LayoutParams. Вот как я это сделал: https://gist.github.com/bolot/6f1838d29d5b8a87b5fcadbeb53fb6f0.

class PeekingLinearLayoutManager : LinearLayoutManager {
    @JvmOverloads
    constructor(context: Context?, @RecyclerView.Orientation orientation: Int = RecyclerView.VERTICAL, reverseLayout: Boolean = false) : super(context, orientation, reverseLayout)

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)

    override fun generateDefaultLayoutParams() =
        scaledLayoutParams(super.generateDefaultLayoutParams())

    override fun generateLayoutParams(lp: ViewGroup.LayoutParams?) =
        scaledLayoutParams(super.generateLayoutParams(lp))

    override fun generateLayoutParams(c: Context?, attrs: AttributeSet?) =
        scaledLayoutParams(super.generateLayoutParams(c, attrs))

    private fun scaledLayoutParams(layoutParams: RecyclerView.LayoutParams) =
        layoutParams.apply {
            when(orientation) {
                HORIZONTAL -> width = (horizontalSpace * ratio).toInt()
                VERTICAL -> height = (verticalSpace * ratio).toInt()
            }
        }

    private val horizontalSpace get() = width - paddingStart - paddingEnd

    private val verticalSpace get() = height - paddingTop - paddingBottom

    private val ratio = 0.9f // change to 0.7f for 70%
}

Это решение основано на вдохновляющем элементе линейного макета (т.е. размещать все элементы на экране) https://gist.github.com/heinrichreimer/39f9d2f9023a184d96f8.

Кстати, если вы просто хотите показывать элементы слева и справа, в то время как текущий элемент находится по центру, вы можете добавить отступы к виду рециркулятора и установить clipToPadding на false. В этом случае вам даже не нужен собственный менеджер макетов.

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:paddingStart="16dp"
    android:paddingEnd="16dp"
    android:clipToPadding="false"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">

Ответ 2

Два способа сделать это на самом деле.

1) Используйте настраиваемое представление для вашего переработанного представления. Переопределите onMeasure, чтобы вернуть его ширину как 70 процентов экрана.

2) В вашем адаптере Recycler View, когда вы создаете представление, его ширина будет составлять 70 процентов от ширины экрана.

В любом случае вы получите размер экрана с дисплея и просто умножьте ширину на.7. В первом случае вы установите это как EXACT измеренную ширину, а во втором вы установите его в параметре layout. Второй, наверное, немного проще.

Ответ 3

У меня была аналогичная проблема, когда у меня был фрагмент с горизонтальным RecyclerView и я хотел, чтобы каждая ширина элемента представления составляла треть экрана пользователя. Решил его, добавив в конструктор нашего класса ViewHolder следующее:

    private class OurViewHolder extends RecyclerView.ViewHolder {
        ...

        public OurViewHolder (LayoutInflater inflater, ViewGroup parent) {
            super (inflater.inflate (R.layout.list_item_layout, parent, false));

            // This code is used to get the screen dimensions of the user device
            DisplayMetrics displayMetrics = new DisplayMetrics();
            getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
            int width = displayMetrics.widthPixels;
            int height = displayMetrics.heightPixels;

            // Set the ViewHolder width to be a third of the screen size, and height to wrap content
            itemView.setLayoutParams(new RecyclerView.LayoutParams(width/3, RecyclerView.LayoutParams.WRAP_CONTENT));

            ...
        }

        ...

Ответ 4

Попробуйте изменить LinearLayout с PercentRelativeLayout чтобы "обернуть" RecyclerView а затем установить его ширину до 70%.

Измените это:

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

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/rv"
        />

</LinearLayout>

С этим:

<android.support.percent.PercentRelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            app:layout_widthPercent="70%"
            android:id="@+id/rv"
            />

РЕДАКТИРОВАТЬ

Поскольку библиотека поддержки Percent поставляется вместе с Android Support Library 23, пожалуйста, убедитесь, что вы обновили библиотеку поддержки Android в SDK Manager до последней версии (фактически 24). А затем добавьте зависимость, как build.gradle ниже в файле build.gradle:

compile 'com.android.support:percent:24.0.0'