RecyclerView неправильно расширяет элементы - PullRequest
0 голосов
/ 10 ноября 2019

У меня есть такой макет:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="6dp"
    android:id="@+id/shift_main_layout"
    android:orientation="vertical"
    android:background="@android:color/white">
    <ScrollView
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_gravity="top"
        android:layout_weight="1">
        <RelativeLayout
            android:id="@+id/recycle_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="top">
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/coworker_recycler"
                android:layout_centerHorizontal="true"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
        </RelativeLayout>
    </ScrollView>

   <LinearLayout
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center_horizontal">
       <com.google.android.material.button.MaterialButton
           android:id="@+id/remove_operator"
           style="@style/customIconButton"
           android:layout_width="wrap_content"
           android:layout_height="25dp"
           app:icon="@drawable/ic_remove_black_24dp" />
       <com.google.android.material.button.MaterialButton
           android:id="@+id/add_operator"
           style="@style/customIconButton"
           android:layout_width="wrap_content"
           android:layout_height="25dp"
           app:icon="@drawable/ic_add_black_24dp" />
   </LinearLayout>

Элементы Recycler Viewer coworker_recycler выглядят так:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:paddingStart="0.5dp"
        android:paddingEnd="0.5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:id="@+id/shift_layout">
        <!--region Cells-->
        <!--Ora00 Row-->
        <TextView
            android:id="@+id/ora00"
            style="@style/cell_style"/>
        <!--Ora01 Row-->
        <TextView
            android:id="@+id/ora01"
            style="@style/cell_style"/>
        <!--Ora02 Row-->
        <TextView
            android:id="@+id/ora02"
            style="@style/cell_style"/>
        <!--Ora03 Row-->
        <TextView
            android:id="@+id/ora03"
            style="@style/cell_style"/>
        <!--Ora04 Row-->
        <TextView
            android:id="@+id/ora04"
            style="@style/cell_style"/>
        <!--Ora05 Row-->
        <TextView
            android:id="@+id/ora05"
            style="@style/cell_style"/>
        <!--Ora06 Row-->
        <TextView
            android:id="@+id/ora06"
            style="@style/cell_style"/>
        <!--Ora07 Row-->
        <TextView
            android:id="@+id/ora07"
            style="@style/cell_style"/>
        <!--Ora08 Row-->
        <TextView
            android:id="@+id/ora08"
            style="@style/cell_style"/>
        <!--Ora09 Row-->
        <TextView
            android:id="@+id/ora09"
            style="@style/cell_style"/>
        <!--Ora10 Row-->
        <TextView
            android:id="@+id/ora10"
            style="@style/cell_style"/>
        <!--Ora11 Row-->
        <TextView
            android:id="@+id/ora11"
            style="@style/cell_style"/>
        <!--Ora12 Row-->
        <TextView
            android:id="@+id/ora12"
            style="@style/cell_style"/>
        <!--Ora13 Row-->
        <TextView
            android:id="@+id/ora13"
            style="@style/cell_style"/>
        <!--Ora14 Row-->
        <TextView
            android:id="@+id/ora14"
            style="@style/cell_style"/>
        <!--Ora15 Row-->
        <TextView
            android:id="@+id/ora15"
            style="@style/cell_style"/>
        <!--Ora16 Row-->
        <TextView
            android:id="@+id/ora16"
            style="@style/cell_style"/>
        <!--Ora17 Row-->
        <TextView
            android:id="@+id/ora17"
            style="@style/cell_style"/>
        <!--Ora18 Row-->
        <TextView
            android:id="@+id/ora18"
            style="@style/cell_style"/>
        <!--Ora19 Row-->
        <TextView
            android:id="@+id/ora19"
            style="@style/cell_style"/>
        <!--Ora20 Row-->
        <TextView
            android:id="@+id/ora20"
            style="@style/cell_style"/>
        <!--Ora21 Row-->
        <TextView
            android:id="@+id/ora21"
            style="@style/cell_style"/>
        <!--Ora22 Row-->
        <TextView
            android:id="@+id/ora22"
            style="@style/cell_style"/>
        <!--Ora23 Row-->
        <TextView
            android:id="@+id/ora23"
            style="@style/cell_style"/>
        <!--endregion-->
    </LinearLayout>
</LinearLayout>

и ячейкастиль элементов TextView:

<style name="cell_style" parent="android:Widget.TextView">
    <item name="android:layout_marginTop">1dp</item>
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_gravity">center_horizontal</item>
    <item name="android:layout_height">@dimen/cell_height</item>
</style>

Адаптер средства просмотра Recycler:

import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.hearth.Model.ShiftModel;
import com.example.hearth.R;
import com.example.hearth.ViewHolder.ShiftViewHolder;
import com.squareup.picasso.Picasso;

import java.util.List;

import jp.wasabeef.picasso.transformations.CropCircleTransformation;

public class ShiftMapAdapter extends RecyclerView.Adapter {

    private Context context;

    private List<ShiftModel> shiftModelList;

    int operatorShow;

    private int Hour(double ora) {
        return ora == 0 ? R.drawable.hour_empty : (ora == 0.5 ? R.drawable.hour_half : R.drawable.hour_full);
}

public ShiftMapAdapter(Context context, List<ShiftModel> shiftModelList, int operatorShow) {
    this.context = context;
    this.shiftModelList = shiftModelList;
    this.operatorShow = operatorShow;
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    View itemView = LayoutInflater.from(context).inflate(R.layout.layout_shift_container, parent, false);

    GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)itemView.getLayoutParams();

    float itemWidth = pxToDp(parent.getMeasuredWidth());

    lp.width = dpToPx((itemWidth)/operatorShow);

    itemView.setLayoutParams(lp);

    return new ShiftViewHolder(itemView);
}

public int dpToPx(float dp) {
    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
    return px;
}

public float pxToDp(float px) {
    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    float dp = px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT);
    return dp;
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {

    ShiftViewHolder vh = (ShiftViewHolder)holder;

    Handler myHandler = new Handler();

    myHandler.post(() -> {

        vh.ora00.setBackgroundResource(Hour(shiftModelList.get(position).getOra00()));
        vh.ora01.setBackgroundResource(Hour(shiftModelList.get(position).getOra01()));
        vh.ora02.setBackgroundResource(Hour(shiftModelList.get(position).getOra02()));
        vh.ora03.setBackgroundResource(Hour(shiftModelList.get(position).getOra03()));
        vh.ora04.setBackgroundResource(Hour(shiftModelList.get(position).getOra04()));
        vh.ora05.setBackgroundResource(Hour(shiftModelList.get(position).getOra05()));
        vh.ora06.setBackgroundResource(Hour(shiftModelList.get(position).getOra06()));
        vh.ora07.setBackgroundResource(Hour(shiftModelList.get(position).getOra07()));
        vh.ora08.setBackgroundResource(Hour(shiftModelList.get(position).getOra08()));
        vh.ora09.setBackgroundResource(Hour(shiftModelList.get(position).getOra09()));
        vh.ora10.setBackgroundResource(Hour(shiftModelList.get(position).getOra10()));
        vh.ora11.setBackgroundResource(Hour(shiftModelList.get(position).getOra11()));
        vh.ora12.setBackgroundResource(Hour(shiftModelList.get(position).getOra12()));
        vh.ora13.setBackgroundResource(Hour(shiftModelList.get(position).getOra13()));
        vh.ora14.setBackgroundResource(Hour(shiftModelList.get(position).getOra14()));
        vh.ora15.setBackgroundResource(Hour(shiftModelList.get(position).getOra15()));
        vh.ora16.setBackgroundResource(Hour(shiftModelList.get(position).getOra16()));
        vh.ora17.setBackgroundResource(Hour(shiftModelList.get(position).getOra17()));
        vh.ora18.setBackgroundResource(Hour(shiftModelList.get(position).getOra18()));
        vh.ora19.setBackgroundResource(Hour(shiftModelList.get(position).getOra19()));
        vh.ora20.setBackgroundResource(Hour(shiftModelList.get(position).getOra20()));
        vh.ora21.setBackgroundResource(Hour(shiftModelList.get(position).getOra21()));
        vh.ora22.setBackgroundResource(Hour(shiftModelList.get(position).getOra22()));
        vh.ora23.setBackgroundResource(Hour(shiftModelList.get(position).getOra23()));

    });
}

@Override
public int getItemCount() {
    return shiftModelList.size();
    }
}

Я использую operatorShow в методе onCreateViewHolder для установки ширины элементов =1/6 экрана устройства.

Держатель вида:

import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.example.hearth.R;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;

public class ShiftViewHolder extends RecyclerView.ViewHolder {

    Unbinder unbinder;

    @BindView(R.id.ora00)
    public
    TextView ora00;
    @BindView(R.id.ora01)
    public
    TextView ora01;
    @BindView(R.id.ora02)
    public
    TextView ora02;
    @BindView(R.id.ora03)
    public
    TextView ora03;
    @BindView(R.id.ora04)
    public
    TextView ora04;
    @BindView(R.id.ora05)
    public
    TextView ora05;
    @BindView(R.id.ora06)
    public
    TextView ora06;
    @BindView(R.id.ora07)
    public
    TextView ora07;
    @BindView(R.id.ora08)
    public
    TextView ora08;
    @BindView(R.id.ora09)
    public
    TextView ora09;
    @BindView(R.id.ora10)
    public
    TextView ora10;
    @BindView(R.id.ora11)
    public
    TextView ora11;
    @BindView(R.id.ora12)
    public
    TextView ora12;
    @BindView(R.id.ora13)
    public
    TextView ora13;
    @BindView(R.id.ora14)
    public
    TextView ora14;
    @BindView(R.id.ora15)
    public
    TextView ora15;
    @BindView(R.id.ora16)
    public
    TextView ora16;
    @BindView(R.id.ora17)
    public
    TextView ora17;
    @BindView(R.id.ora18)
    public
    TextView ora18;
    @BindView(R.id.ora19)
    public
    TextView ora19;
    @BindView(R.id.ora20)
    public
    TextView ora20;
    @BindView(R.id.ora21)
    public
    TextView ora21;
    @BindView(R.id.ora22)
    public
    TextView ora22;
    @BindView(R.id.ora23)
    public
    TextView ora23;

    public ShiftViewHolder(@NonNull View itemView) {
        super(itemView);

        unbinder = ButterKnife.bind(this, itemView);
    }
}

Я называю все так во фрагменте:

public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    shiftsViewModel = ViewModelProviders.of(this).get(ShiftsViewModel.class);

    selectedDate = "2019-11-12";

    setHasOptionsMenu(true);

    View root = inflater.inflate(R.layout.fragment_shifts, container, false);

    unbinder = ButterKnife.bind(this, root);

    //Count how many columns are created in the recycle

    addOperator.setOnClickListener(view -> {

        int adapterItemsCount = shiftMapAdapter.getItemCount();

        if (operatorShow < adapterItemsCount) {

            operatorShow++;

            getMap(selectedDate);
        }
        else {
            Toast.makeText(getContext(), "Can't add more columns", Toast.LENGTH_SHORT).show();
        }
    });

    removeOperator.setOnClickListener(view -> {

        if (operatorShow > 5) {

            operatorShow--;

            getMap(selectedDate);
        }
        else {
            Toast.makeText(getContext(), "Can't remove more columns", Toast.LENGTH_SHORT).show();
        }
    });

    initialize();

    getMap(selectedDate);
    return root;
}


private void getMap(String selectedDate) {

    shiftsViewModel.getCoworkerList(selectedDate).observe(getActivity(), shiftModel -> {

        shiftMapAdapter = new ShiftMapAdapter(ShiftsFragment.this.getContext(), shiftModel, operatorShow);

        coworker_recycler.setAdapter(shiftMapAdapter);
        coworker_recycler.setLayoutAnimation(layoutAnimationController);
    });
}

private void initialize() {
    layoutAnimationController = AnimationUtils.loadLayoutAnimation(getContext(), R.anim.layout_item_from_left);
    coworker_recycler.setHasFixedSize(true);
    coworker_recycler.setLayoutManager(new GridLayoutManager(getContext(), 1, RecyclerView.HORIZONTAL, false));
}

enter image description here

Проблема в том, что когда мне нужно добавить больше столбцов, например, 8, элементы расширяются неправильно.

enter image description here

Заметно, что на правом краю есть зеленые пиксели, как на картинке.

Любая помощь в том, что я делаю неправильно, или любое предложение, чтобы лучше расширить поровну элементыRecyclerViewer?

1 Ответ

1 голос
/ 13 ноября 2019
float itemWidth = pxToDp(parent.getMeasuredWidth());
lp.width = dpToPx((itemWidth)/operatorShow);

Когда вы делите itemWidth на operatorShow, ответ, скорее всего, будет дробным, в зависимости от ширины экрана. Поскольку ширина указана в целых числах, вы теряете точность. '.

Я объясню это здесь, если приведенное выше не имеет смысла:

Подробнееподробное объяснение:
Предположим, ширина равна 640, а если количество столбцов равно 6, то:

itemWidth = 640/6 = 106.6666 = 106 (fractional part dropped since pixel is the smallest unit)

Теперь для каждого элемента ваша ширина равна точно 106 ,Теперь давайте посчитаем, сколько места заняли бы все 6 столбцов, если бы каждый занял 106:

106 * 6 = 636  //Notice that our actual width was 640 so we lost 4 pixels in precision

Как видите, поскольку мы отбросили дробную часть, мы потеряли 4 точности . Эти 4 пикселя пропущены в конце, и поэтому вы видите следующие столбцы, когда представление пытается заполнить пустое пространство.

Что с этим делать?
Вы можетеуменьшите количество столбцов до коэффициента ширины устройства, как в примере выше, если деление на 6 дает дробь, попробуйте с 5 и продолжайте снижаться, пока не найдете один. Если это нарушает функциональность приложения, я боюсь, что это не поможет, так как пиксели / dps не могут быть дробными.

...