带有 GridLayoutManager 的 Recycler View 不滚动
Recycler View with GridLayoutManager not scrolling
该应用程序包含两个按钮,一个用于 ListView,另一个用于 GridView,因此我创建了 ItemViews 和一个适配器。我已经创建了在 ListView 和 GridView 之间切换的方法。除了 GridView 之外,一切都运行良好,它似乎被卡住了。列表视图垂直滚动但最多只有 6 个项目,列表包含 9 个。我希望 GridView 以与列表视图滚动相同的方式滚动直到结束。我同时花了 2 个小时来搜索解决方案,但 none 有效。我试过了,ScrollView,NestedScrollView,还是无法解决
网格视图 = 带有 GridLayoutManager 的 RecyclerView
截图如下:
这个最多可以隐藏 6 个项目并隐藏 9 个项目中的 3 个
这个不滚动(仅 GridView)
代码如下:
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
}
}
}
我们将不胜感激任何形式的快速帮助
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
的底部而不溢出
该应用程序包含两个按钮,一个用于 ListView,另一个用于 GridView,因此我创建了 ItemViews 和一个适配器。我已经创建了在 ListView 和 GridView 之间切换的方法。除了 GridView 之外,一切都运行良好,它似乎被卡住了。列表视图垂直滚动但最多只有 6 个项目,列表包含 9 个。我希望 GridView 以与列表视图滚动相同的方式滚动直到结束。我同时花了 2 个小时来搜索解决方案,但 none 有效。我试过了,ScrollView,NestedScrollView,还是无法解决
网格视图 = 带有 GridLayoutManager 的 RecyclerView
截图如下:
这个最多可以隐藏 6 个项目并隐藏 9 个项目中的 3 个
这个不滚动(仅 GridView)
代码如下:
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
}
}
}
我们将不胜感激任何形式的快速帮助
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
的底部而不溢出