Recycler View с GridLayoutManager без прокрутки

Приложение содержит две кнопки, одну для ListView, а другую для GridView, поэтому я создал для ItemViews и один адаптер. Я создал метод переключения между ListView и GridView. Все работает нормально, кроме GridView, который, кажется, забит. Просмотр списка прокручивается по вертикали, но только до 6 элементов, список содержит 9. Я хочу, чтобы GridView прокручивался так же, как прокручивается до конца в представлении списка. Я потратил 2 часа одновременно на поиск решения, но ни один из них не сработал. Я пробовал ScrollView, NestedScrollView, но все еще не могу решить.

Вид сетки = RecyclerView с GridLayoutManager

Вот скриншот:

Этот отлично работает до 6 элементов и скрывает 3 из 9

Рис.1: ListView (работает нормально)

Этот не прокручивается (только GridView)

Рис. 2: вид сетки (без прокрутки)

Вот код:

activity_main.xml

<?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="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/frameLayout_imageContainer"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/iv_house"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            app:srcCompat="@drawable/house" />

    </FrameLayout>

    <LinearLayout
        android:id="@+id/linearLayout_btnContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginBottom="8dp"
        android:gravity="end"
        android:orientation="horizontal"
        app:layout_constraintTop_toBottomOf="@id/frameLayout_imageContainer">

        <ImageButton
            android:id="@+id/btnListView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/btn_gradient_purple"
            android:padding="8dp"
            android:tint="@color/colorWhite"
            app:srcCompat="@drawable/ic_list" />

        <ImageButton
            android:id="@+id/btnGridView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:background="@drawable/btn_gradient_purple"
            android:padding="8dp"
            android:tint="@color/colorWhite"
            app:srcCompat="@drawable/ic_grid" />

    </LinearLayout>


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_room"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        app:layout_constraintTop_toBottomOf="@+id/linearLayout_btnContainer">

    </androidx.recyclerview.widget.RecyclerView>


</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private lateinit var mRoomList: ArrayList<Room>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val roomTypeBedroom = RoomType("Bedroom", R.drawable.ic_bedroom)
        val roomTypeKitchen = RoomType("Kitchen", R.drawable.ic_kitchen)
        val roomTypeBathroom = RoomType("Bathroom", R.drawable.ic_bathroom)
        val roomTypeLiving = RoomType("Living", R.drawable.ic_living)
        val roomTypeDining = RoomType("Dining", R.drawable.ic_dinning)
        val roomTypeEmpty = RoomType("Empty", R.drawable.ic_empty)

        mRoomList = arrayListOf(
                Room("Bedroom 1", R.drawable.bedroom_1, 1, roomTypeBedroom),
                Room("Bedroom 2", R.drawable.bedroom_2, 2, roomTypeBedroom),
                Room("Bedroom 3", R.drawable.bedroom_3, 3, roomTypeBedroom),
                Room("Kitchen", R.drawable.kitchen, 4, roomTypeKitchen),
                Room("Bathroom", R.drawable.bathroom, 5, roomTypeBathroom),
                Room("Living Room", R.drawable.living, 6, roomTypeLiving),
                Room("Dining Room", R.drawable.sitting_area, 7, roomTypeDining),
                Room("Empty Room 1", R.drawable.empty_1, 8, roomTypeEmpty),
                Room("Empty Room 2", R.drawable.empty_2, 9, roomTypeEmpty)

        )

        showRoomsAs(ViewType.GRID)


        btnGridView.setOnClickListener {
            showRoomsAs(ViewType.GRID)
        }

        btnListView.setOnClickListener {
            showRoomsAs(ViewType.LIST)
        }

    }

    private fun showRoomsAs(viewType: ViewType) {

        val roomAdapter = RoomAdapter(
                this,
                mRoomList,
                viewType,
                frameLayout_imageContainer
        )


        if (viewType == ViewType.GRID) {
            rv_room.layoutManager = GridLayoutManager(this, 3)
            btnGridView.visibility = View.GONE
            btnListView.visibility = View.VISIBLE
        } else {
            rv_room.layoutManager = LinearLayoutManager(this)
            btnGridView.visibility = View.VISIBLE
            btnListView.visibility = View.GONE
        }

        rv_room.adapter = roomAdapter
    }


}

RoomAdapter.k

import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class RoomAdapter(
        private val context: Context,
        private val rooms: ArrayList<Room>,
        private val type: ViewType,
        private val imageContainer: FrameLayout)
    : RecyclerView.Adapter<RoomAdapter.RoomViewHolder>() {


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RoomViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        var view: View? = null
        if (type == ViewType.GRID)
            view = inflater.inflate(R.layout.rv_item_grid, parent, false)
        else if (type == ViewType.LIST)
            view = inflater.inflate(R.layout.rv_item_list, parent, false)

        return RoomViewHolder(view!!)
    }

    override fun getItemCount(): Int {
        return rooms.size
    }

    override fun onBindViewHolder(holder: RoomViewHolder, position: Int) {
        val room = rooms[position]
        holder.icon.setBackgroundResource(room.type.icon)
        holder.name.text = room.name
        holder.type.text = room.type.type
        holder.status.text = room.isRoomOnOrOff()
    }

    inner class RoomViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
        override fun onClick(p0: View?) {
            val room = rooms[adapterPosition]
            if (room.associatedImageView == null) {
                val imageView = ImageView(context)

                imageView.layoutParams = ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                )

                imageView.setImageResource(room.image)

                room.associatedImageView = imageView
                imageContainer.addView(imageView)

            }

            if (room.isOn) {

                room.associatedImageView?.visibility = View.GONE
                room.isOn = false
            } else {
                room.associatedImageView?.visibility = View.VISIBLE
                room.isOn = true
            }

            notifyDataSetChanged()

        }

        val icon: ImageView
        val name: TextView
        val type: TextView
        val status: TextView

        init {
            itemView.setOnClickListener(this)

            icon = itemView.findViewById(R.id.rv_item_icon) as ImageView
            name = itemView.findViewById(R.id.rv_room_name) as TextView
            type = itemView.findViewById(R.id.rv_room_type) as TextView
            status = itemView.findViewById(R.id.rv_status) as TextView
        }

    }
}

мы будем благодарны за любую быструю помощь


person thezeeshantariq    schedule 08.08.2019    source источник
comment
Цель ConstraintLayout - избежать вложенных макетов. Вы должны создать весь свой макет без FrameLayout и LinearLayout.   -  person charles-allen    schedule 09.08.2019


Ответы (1)


ConstraintLayout иногда бывает непросто. Ваш recyclerView может находиться в нескольких дюймах от порта просмотра приложения. Вы можете попробовать указанные ниже атрибуты на своем recyclerView

Вариант 1: использование большого отступа

<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_room"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="250dp"
        android:paddingLeft="8dp"
        android:paddingRight="8dp"
        android:paddingBottom ="20dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="parent">

</androidx.recyclerview.widget.RecyclerView>

Вариант 2: использование app:layout_constraintBottom_toBottomOf

<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_room"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="250dp"
        android:paddingLeft="8dp"
        android:paddingRight="8dp"
        android:paddingBottom ="20dp"
        app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/linearLayout_btnContainer">

</androidx.recyclerview.widget.RecyclerView>

Добавление app:layout_constraintBottom_toBottomOf="parent" во второй вариант заставляет нижнюю часть recyclerView придерживаться нижней части constraintLayout и не переполняться

person Giddy Naya    schedule 09.08.2019
comment
Я пробовал constraintBottom раньше, но это тоже не сработало. Это предотвратило переполнение recyclerview, но начало перекрываться с видами над ним. И paddingTop может помочь, но проблема в том, что изображение выше может измениться в любое время (пользователем), что может вызвать перекрытие. - person thezeeshantariq; 09.08.2019
comment
Затем установите фиксированную высоту для imageView выше - person Giddy Naya; 09.08.2019