Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
192 views
in Technique[技术] by (71.8m points)

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

screenshot on large screen

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
        }
    }
question from:https://stackoverflow.com/questions/65903559/how-to-implement-horizontal-vertical-chain-type-concept-in-recyclerview-gridla

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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)

enter image description here

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).

enter image description here

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"

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...