GridLayoutManager 实现 复杂列布局
最近做直播页面有个需求 直接上页面
WechatIMG24.jpeg竖直往下依次有四个ItemView 。
Item2 Item4数目依次不定 。
其中item2 数据和item4 相同 也就是整个页面同一个接口
第一次我用 2个recyclerview LinearLayoutManager Vertical .显示。
当然 大家知道 会存在item2 数据多而 item4 不能显示的情况。
用scrollview 括起来 发现无用。果然还和listview 一样。
解决办法:
- 在每个RecyclerView外层嵌套一个RelativeLayout,并设置descendantFocusability属性。代码如下
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
果然数据正常显示了 但是发现滑动卡顿。 本人都体验差 肯定不行
- 换瀑布流解决方案 StaggeredGridLayoutManager
假如 StaggeredGridLayoutManager 瀑布流 这样的图片水平显示不就是我要的效果吗。 然后经过尝试发现不行 。它控制列的变化不太灵活。
回过头再去google 查资料发现 gridlayoutmanager 可以很灵活的修改列数 。哎呀 这就对了 以前产生误解 还是理解的不太透彻 一直以为gridlayoutmanager 就是 九宫格之类的职能 有时间一定要好好再研究源码。
果然效果立马实现。
class LiveFollowAdapter(private val context: Context) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
//todo 重构:1命名 2数据list 管理 3泛型 4 基类提取 5viewhold 分装
private var openRoomList: List<NAnchor> = ArrayList()
private var closeRoomList: List<NAnchor> = ArrayList()
private var dataList: MutableList<NAnchor> = mutableListOf()
private val TAG = "LiveFollowAdapter"
fun setDataList(data: NLiveFollow) {
if (data?.closeRooms != null) {
// openRoomList = data?.openRooms
openRoomList = data?.closeRooms
}
if (data?.closeRooms != null) {
closeRoomList = data?.closeRooms
}
dataList.clear()
dataList.add(NAnchor("live_header"))
dataList.addAll(openRoomList)
dataList.add(NAnchor("unlive_header"))
dataList.addAll(closeRoomList)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
ViewType.ViewType1.ordinal -> ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_living_follow_header, parent, false))
ViewType.ViewType2.ordinal -> ViewHolder2(LayoutInflater.from(context).inflate(R.layout.item_live_follow_grid, parent, false))
ViewType.ViewType3.ordinal -> ViewHolder3(LayoutInflater.from(context).inflate(R.layout.item_unlive_follow_header, parent, false))
ViewType.ViewType4.ordinal -> ViewHolder4(LayoutInflater.from(context).inflate(R.layout.item_live_follow_content, parent, false))
else -> throw IllegalArgumentException(" holder error")
}
}
override fun getItemViewType(position: Int): Int {
if (position == 0) {
return ViewType.ViewType1.ordinal
} else if (position > 0 && openRoomList!!.size > 0 && position <= openRoomList.size) {
return ViewType.ViewType2.ordinal
} else if (position == openRoomList?.size + 1) {
return ViewType.ViewType3.ordinal
} else {
return ViewType.ViewType4.ordinal
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder.itemViewType) {
ViewType.ViewType1.ordinal -> {
var viewHolder1 = holder as ViewHolder
viewHolder1.bind(openRoomList.size)
}
ViewType.ViewType2.ordinal -> {
var viewHolder2 = holder as ViewHolder2
if (openRoomList.size > 0 && openRoomList.size == position && openRoomList.size % 2 != 0) {
viewHolder2.bind(dataList.get(position), true)
} else {
viewHolder2.bind(dataList.get(position), false)
}
}
ViewType.ViewType3.ordinal -> {
var viewHolder3 = holder as ViewHolder3
viewHolder3.bind(closeRoomList.size)
}
ViewType.ViewType4.ordinal -> {
var viewHolder4 = holder as ViewHolder4
viewHolder4.bind(dataList.get(position))
}
}
}
override fun getItemCount(): Int {
return dataList.size
}
fun remove(position: Int) {
// dataList.removeAt(position)
notifyItemRemoved(position)
}
fun add(text: String, position: Int) {
// dataList.add(position, text)
notifyItemInserted(position)
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var num = itemView.findViewById<TextView>(R.id.tv_living_num)
fun bind(size: Int) {
num.text = "$size"
}
}
class ViewHolder2(itemView: View) : RecyclerView.ViewHolder(itemView) {
var title = itemView.findViewById<TextView>(R.id.tv_live_anchor_title)
var ivAvatar = itemView.findViewById<ImageView>(R.id.iv_avatar)
var constraintLayout = itemView.findViewById<ConstraintLayout>(R.id.cl_layout)
fun bind(anchor: NAnchor, flag: Boolean) {
title.text = anchor?.user?.nickname
// view.tv_anchor_motto.text = anchor.description
GlideApp.with(itemView.context).load(anchor?.user?.avatar)
.placeholder(R.mipmap.iv_default_head)
.error(R.mipmap.iv_default_head)
.into(ivAvatar)
//奇数时候 改动最后一个view
if (flag) {
var param: RecyclerView.LayoutParams = itemView.layoutParams as RecyclerView.LayoutParams
val height = param.height
val width = param.width
param.width = height
param.height = param.height
itemView.visibility = View.VISIBLE
itemView.setLayoutParams(param)
}
}
}
class ViewHolder3(itemView: View) : RecyclerView.ViewHolder(itemView) {
var num = itemView.findViewById<TextView>(R.id.tv_un_live_num)
fun bind(size: Int) {
num.text = "$size"
}
}
class ViewHolder4(itemView: View) : RecyclerView.ViewHolder(itemView) {
var name = itemView.findViewById<TextView>(R.id.tv_un_live_name)
var num = itemView.findViewById<TextView>(R.id.tv_un_live_follow_num)
var civHead = itemView.findViewById<ImageView>(R.id.civ_head)
// var header = itemView.findViewById<ImageView>(R.id.civ_head)
fun bind(anchor: NAnchor) {
name.text = anchor.user.nickname
num.text = anchor.likeCount.toString()
GlideApp.with(itemView.context).load(anchor?.user?.avatar)
.placeholder(R.mipmap.iv_default_head)
.error(R.mipmap.iv_default_head)
.into(civHead)
}
}
enum class ViewType {
ViewType1, ViewType2, ViewType3, ViewType4
}
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
val layoutManager = recyclerView.layoutManager
if (layoutManager is GridLayoutManager) {
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
//取多个item的每行占用个数的最小公倍数,
//这里最小公倍数为2 只有item2 显示2行所以返回1 其余为2
//他们对应的return 3,return 2,return 6
/*2122*/
var viewType = getItemViewType(position)
return when (viewType) {
ViewType.ViewType1.ordinal -> 2
ViewType.ViewType2.ordinal -> 1
ViewType.ViewType3.ordinal -> 2
else -> 2
}
}
}
}
}
}
上面onAttachedToRecyclerView 方法 是在recyclerview 与 adapter 适配数据时候 调用的 这才是关键方法 再一次见识了 recyclerview 的无比强大!
Fragment 中代码 就比较简单了。
val layoutManager = GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false);
rv_live_follow.layoutManager = layoutManager
liveFollowAdapter = LiveFollowAdapter(context!!)
rv_live_follow.addItemDecoration(GridSpacingItemDecoration(DensityUtil.dip2px(context!!, 9f)))
rv_live_follow.adapter = liveFollowAdapter
功能催的比较紧张 代码感觉还需要重构...
大功告成 搞定收工 又是一周结束了......
网友评论