简体   繁体   中英

How to implement horizontal & vertical chain type concept in recyclerview gridlayout?

As always I have read through several posts on this topic across this site. If this truly is duplication I will delete this question. Majority of cases on here are dealing with orientation changes or looking to amend fixed values depending on the screensize. I am not worried about fixing width and height values.

What I want to achieve is a 6x10 grid which fills the screen no matter what size it is (orientation is fixed to portrait)

Here is my recyclerview item, I started with wrap content on the views and then tried match parent, neither makes any difference. On a small screen it fits fine and on a large screen it sits in the middle but is the same size.

I know I can't directly create a chain in my recyclerview item xml because I need to make a chain out of more than 1 view. I attempted to manually set the main layout with spread chain and a weight of 1 and then set the layout to 0dp, ran the code and obviously it didnt work

So, key question, is there a way to simply write the item xml so that it is dynamic or do we always have to create a subclass of sorts to generate different layouts per screensize?

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="2dp">

    <LinearLayout
        android:id="@+id/layout_background"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginEnd="4dp"
        android:layout_marginBottom="3dp"
        android:background="@drawable/level_background"
        android:gravity="center_vertical"
        android:orientation="vertical"
        android:padding="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/TV_Level"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center|center_horizontal|center_vertical"
            android:textColor="@color/sub_level_button_text_color" />

        <RatingBar
            android:id="@+id/ratingBar"
            style="@style/Widget.AppCompat.RatingBar.Small"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:backgroundTint="@color/StarOutline"
            android:isIndicator="true"
            android:numStars="3"
            android:progressTint="@color/StarOutline"
            android:stepSize="0.5" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

大屏幕截图

To further assist with this here is my adapter

package com.maxcell.sumitup


import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.RatingBar
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView



class LevelsAdaptor(private val onClick:(id:Int,mainLevel:Int,subLevel:Int,stars:Float,bonusGame:Boolean,type:Int)->Unit) : ListAdapter<Levels, LevelsAdaptor.LevelsViewHolder>(LevelsComparator()) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LevelsViewHolder {
        val view: View = LayoutInflater.from(parent.context)
            .inflate(R.layout.rv_storymode_items, parent, false)
        return LevelsViewHolder(view)
    }

    override fun onBindViewHolder(holder: LevelsViewHolder, position: Int) {
        val current = getItem(position)
        holder.bind(
            current.id,
            current.mainLevel,
            current.subLevel,
            current.stars,
            current.unlocked,
                current.bonusround,
                current.questiontype
        )
    }


    inner class LevelsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val TVLEVEL: TextView = itemView.findViewById(R.id.TV_Level)
        private val rating: RatingBar = itemView.findViewById(R.id.ratingBar)
        private val layoutBackground: LinearLayout = itemView.findViewById(R.id.layout_background)
        private val myContext = itemView.context
        //private val myContext: Context = sumView.context
        fun bind(ID: Int, ML: Int, SL: Int, Stars: Float, Unlocked: Boolean,BonusRound:Boolean,QuestionType:Int) {
            TVLEVEL.text = ID.toString()
            rating.rating = Stars

            if (Unlocked){
                itemView.isEnabled=true;itemView.isClickable=true;layoutBackground.setBackgroundResource(R.drawable.level_background)
            }else{
                itemView.isEnabled=false;itemView.isClickable=false;layoutBackground.setBackgroundResource(R.drawable.standard_background_deactivated);TVLEVEL.setTextColor(myContext.getColor(R.color.ColorOnDeactivated))
            }
            itemView.setOnClickListener {
                //Set your codes about intent here
                onClick(ID,ML,SL,Stars,BonusRound,QuestionType)
            }
        }

        }
    }

    class LevelsComparator : DiffUtil.ItemCallback<Levels>() {
        override fun areItemsTheSame(oldItem: Levels, newItem: Levels): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: Levels, newItem: Levels): Boolean {
            return oldItem == newItem
        }
    }

If you set the RecyclerView width to match_parent , your ConstraintLayout , LinearLayout , TextView and RatingBar widths to match_parent , the items will stretch to fill the entire width of the screen (assuming you're using GridLayoutManager )

在此处输入图像描述

However, you'll notice that they don't fit the screen vertically, you have to scroll to them all. Setting height to 'match_parent' won't help here, you'll have to calculate the height in your adapter if you want them to fit exact.

This might make it look a bit strange on certain devices though (such as phones with longer screens).

在此处输入图像描述

To give a better looking layout, you might want to set the following properties on the ConstraintLayout :

android:layout_height="0dp"
app:layout_constraintDimensionRatio="3:1"

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM