RecyclerView跨行自适应调整
程序员文章站
2022-06-21 19:40:40
一、先看效果二、实现原理重写RecyclerView.LayoutManager,在onLayoutChildren时,重新测量计算布局,当多个item的宽度之和大于屏幕宽度时就换行,直接看以下代码,注释很详细:重写的LayoutManager:AutoFixLayoutManager.ktimport android.view.Viewimport android.view.ViewGroupimport androidx.core.view.getimport androi...
一、先看效果
二、实现原理
重写RecyclerView.LayoutManager,在onLayoutChildren时,重新测量计算布局,当多个item的宽度之和大于屏幕宽度时就换行,直接看以下代码,注释很详细:
重写的LayoutManager AutoFixLayoutManager.kt
import android.view.View
import android.view.ViewGroup
import androidx.core.view.get
import androidx.recyclerview.widget.RecyclerView
class AutoFixLayoutManager : RecyclerView.LayoutManager() {
private var parentScale = 1f
private var childScale = 1f
override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
return RecyclerView.LayoutParams(
RecyclerView.LayoutParams.WRAP_CONTENT,
RecyclerView.LayoutParams.WRAP_CONTENT
)
}
override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State?) {
detachAndScrapAttachedViews(recycler)
//屏幕总宽度
val sumWidth = width
var curLineWidth = 0
var curLineTop = 0
var lastLineMaxHeight = 0
for (i in 0 until itemCount) {
//循环获取item的宽高
val view: View = recycler.getViewForPosition(i)
measureChildWithMargins(view, 0, 0)
val width = getDecoratedMeasuredWidth(view)
val height = getDecoratedMeasuredHeight(view)
if (parentScale != 1f && state?.isMeasuring == true) {
//缩放ViewGroup
val params: ViewGroup.LayoutParams = view.layoutParams
params.width = (width * parentScale).toInt()
params.height = (height * parentScale).toInt()
view.layoutParams = params
}
addView(view)
if (childScale != 1f && state?.isMeasuring == true) {
//缩放childView
scaleItemChildView(view as ViewGroup)
}
curLineWidth += width
if (curLineWidth <= sumWidth) {
//不需要换行
layoutDecorated(
view,
curLineWidth - width,
curLineTop,
curLineWidth,
curLineTop + height
)
//比较当前行多有item的最大高度
lastLineMaxHeight = Math.max(lastLineMaxHeight, height)
} else {
//换行
curLineWidth = width
if (lastLineMaxHeight == 0) {
lastLineMaxHeight = height
}
//记录当前行top
curLineTop += lastLineMaxHeight
layoutDecorated(view, 0, curLineTop, width, curLineTop + height)
lastLineMaxHeight = height
}
}
}
/**
* 缩放item内子布局
*/
private fun scaleItemChildView(viewGroup: ViewGroup) {
for (index in 0 until viewGroup.childCount) {
val view = viewGroup[index]
val width = view.layoutParams.width
val height = view.layoutParams.height
if (width < 0 || height < 0) {
continue
}
val params: ViewGroup.LayoutParams = view.layoutParams
params.width = (width * childScale).toInt()
params.height = (height * childScale).toInt()
view.layoutParams = params
//设置childView在parentView内居中
val left = viewGroup.layoutParams.width / 2 - view.layoutParams.width / 2
val top = viewGroup.layoutParams.height / 2 - view.layoutParams.height / 2
val right = left + view.layoutParams.width
val bottom = top + view.layoutParams.height
view.layout(left, top, right, bottom)
}
}
/**
* 设置item进行缩放
*/
fun setScale(parentScale: Float, childScale: Float) {
this.parentScale = parentScale
this.childScale = childScale
}
}
adapter:AutoFixListAdapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class AutoFixListAdapter constructor(list: ArrayList<String>, context: Context) :
RecyclerView.Adapter<AutoFixListAdapter.AutoFixViewHolder>() {
private var context = context
private var list = list
private var isShowAll = true
class AutoFixViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) {
var tvName: TextView = view.findViewById(R.id.name)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AutoFixViewHolder {
return AutoFixViewHolder(
LayoutInflater.from(context).inflate(R.layout.app_item, parent, false)
)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: AutoFixViewHolder, position: Int) {
if (holder != null) {
//不重用item,我的测量方式是以不重用item为前提设计的,如果重用要重新设计测量方式
holder.setIsRecyclable(false)
holder.tvName.text = list[position]
if (isShowAll) {
holder.tvName.visibility = View.VISIBLE
} else {
holder.tvName.visibility = View.GONE
}
}
}
fun changeShowType() {
isShowAll = !isShowAll
notifyDataSetChanged()
}
fun isShowAll(): Boolean {
return isShowAll
}
}
MainAcitivy
import android.os.Bundle
import android.widget.ImageButton
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var imageButton: ImageButton
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
}
private fun initView() {
imageButton = findViewById(R.id.imageButton)
recyclerView = findViewById(R.id.recycler)
var manager = AutoFixLayoutManager()
manager.isAutoMeasureEnabled = true
recyclerView.layoutManager = manager
var adapter = AutoFixListAdapter(initData(), this)
recyclerView.adapter = adapter
imageButton.setOnClickListener {
adapter.changeShowType()
if (adapter.isShowAll()) {
imageButton.setBackgroundResource(R.mipmap.down)
manager.setScale(1f, 1f)
} else {
imageButton.setBackgroundResource(R.mipmap.right)
manager.setScale(0.6f, 0.5f)
}
}
}
private fun initData(): ArrayList<String> {
var list = ArrayList<String>()
for (index in 1..14) {
list.add("应用" + index)
}
return list
}
}
app_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="4dp">
<ImageView
android:id="@+id/icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="4dp"
android:src="@mipmap/ic_launcher_round" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="范德萨发" />
</LinearLayout>
activity_main.xml
<?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:orientation="vertical">
<ImageButton
android:id="@+id/imageButton"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_margin="16dp"
android:background="@mipmap/down" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageButton" />
</LinearLayout>
本文地址:https://blog.csdn.net/qq_24125575/article/details/110144592
推荐阅读
-
自适应-窗口调整时,可记录调整(变大变小)次数
-
vue 使用css根据屏幕大小宽度自适应调整
-
RecyclerView加载瀑布流,图片自适应问题
-
android recyclerview宽度随item的宽度自适应
-
RecyclerView跨行自适应调整
-
使用RecyclerView实现瀑布流高度自适应
-
百度地图标记,自动调整缩放等级,自适应缩放
-
紧急求助:如何实现背景图片自适应分辨率和IE窗口的调整_html/css_WEB-ITnose
-
紧急求助:如何实现背景图片自适应分辨率和IE窗口的调整_html/css_WEB-ITnose
-
紧急:如何实现背景图片自适应分辨率和IE窗口的调整_html/css_WEB-ITnose