实现头部多样式的布局方案网上有很多,这里简单记录下实现的方案:
-
方案一:参考鸿洋大神的方案:blog.csdn.net/lmj62356579…
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
/**
* 支持添加header的Adapter
*/
open class HeaderAndFooterWrapperAdapter<H : HeaderAndFooterWrapperViewHolder, D : Any> :RecyclerView.Adapter<HeaderAndFooterWrapperViewHolder>() {
private var headerViewMap: HashMap<Int,View> = hashMapOf()
private var headerKey = 100000
private var footerViewMap: HashMap<Int,View> = hashMapOf()
private var footerKey = 200000
private var contentAdapter: ContentAdapter<H, D>? = null
fun addHeader(headerView: View): HeaderAndFooterWrapperAdapter<H,D> {
headerViewMap.put(headerViewMap.size + headerKey,headerView)
return this
}
fun addFooter(footerView: View): HeaderAndFooterWrapperAdapter<H,D> {
footerViewMap.put(footerViewMap.size + footerKey,footerView)
return this
}
fun setContentAdapter(contentAdapter: ContentAdapter<H,D>?): HeaderAndFooterWrapperAdapter<H,D> {
this.contentAdapter = contentAdapter
return this
}
fun getHeaderViews(): List<View> {
return headerViewMap.values.toList()
}
fun getFooterViews(): List<View> {
return footerViewMap.values.toList()
}
private fun getHeaderCount(): Int {
return headerViewMap.size
}
private fun getFooterCount(): Int {
return footerViewMap.size
}
private fun getContentCount(): Int{
return contentAdapter?.itemCount?: 0
}
fun getContentAdapter(): ContentAdapter<H,D>? {
return contentAdapter
}
open fun isHeaderViewPos(position: Int): Boolean {
return position < getHeaderCount()
}
open fun isFooterViewPos(position: Int): Boolean {
return position >= getHeaderCount() + getContentCount()
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): HeaderAndFooterWrapperViewHolder {
if (headerViewMap.containsKey(viewType)) {
return HeaderAndFooterWrapperViewHolder(headerViewMap[viewType]!!)
}else if(footerViewMap.containsKey(viewType)){
return HeaderAndFooterWrapperViewHolder(footerViewMap[viewType]!!)
}
return contentAdapter!!.createViewHolder(parent,viewType)
}
override fun onBindViewHolder(holder: HeaderAndFooterWrapperViewHolder, position: Int) {
if (isHeaderViewPos(position)){
return
}else if (isFooterViewPos(position)){
return
}
contentAdapter?.onBindViewHolder(holder as H,position - getHeaderCount())
}
override fun getItemCount(): Int {
return getHeaderCount() + getContentCount() + getFooterCount()
}
override fun getItemViewType(position: Int): Int {
if (isHeaderViewPos(position)) {
return headerViewMap.keys.toList()[position]
}
if (isFooterViewPos(position)) {
return footerViewMap.keys.toList()[position - getHeaderCount() - getContentCount()]
}
return 0
}
}
open class HeaderAndFooterWrapperViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {}
open abstract class ContentAdapter<H: HeaderAndFooterWrapperViewHolder,D> : RecyclerView.Adapter<H>() {
//数据
protected var dataList: MutableList<D> = mutableListOf()
fun setDatas(data: MutableList<D>) {
this.dataList.addAll(data)
}
fun getDatas(): MutableList<D> {
return dataList
}
override fun getItemCount(): Int {
return dataList.size
}
}
使用方式:
headerAndFooterWrapperAdapter = HeaderAndFooterWrapperAdapter<ContentViewHolder, String>().apply {
//添加header
addHeader(Form4(context, null).buildApply {
leftText = "测试"
rightText = "文案"
})
addHeader(Form4(context, null).buildApply {
leftText = "测试2"
rightText = "文案2"
})
addHeader(Form4(context, null).buildApply {
leftText = "测试3"
rightText = "文案3"
})
//添加footer
addFooter(Form4(context, null).buildApply {
leftText = "测试4"
rightText = "文案4"
})
//设置内容区域的Adapter
setContentAdapter(object : ContentAdapter<ContentViewHolder, String>() {
private var items = mutableListOf<String>()
init {
for (i in 0..100) {
items.add("== " + i.toString())
}
setDatas(items)
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ContentViewHolder {
return ContentViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.item_ware_test, parent, false)
)
}
override fun onBindViewHolder(
holder: ContentViewHolder,
position: Int
) {
holder.tv_name.text = "商品名:${dataList.get(position)}"
holder.tv_delete.setOnClickListener {
dataList.removeAt(position)
headerAndFooterWrapperAdapter?.notifyDataSetChanged()
}
holder.tv_add.setOnClickListener {
dataList.add("new Data $position")
headerAndFooterWrapperAdapter?.notifyDataSetChanged()
}
}
})
}
//外部刷新头部
bt_change_header.setOnClickListener {
(ware_rv.adapter as HeaderAndFooterWrapperAdapter<ContentViewHolder,String>).apply {
getHeaderViews().forEach { view ->
view as Form4
view.refreshFormApply {
leftText += "new"+System.currentTimeMillis()
rightText += "new"+System.currentTimeMillis()
rightBottomText += "底部文案" +System.currentTimeMillis()
}
}
}
}
//外部数据修改
bt_change_rv.setOnClickListener {
(ware_rv.adapter as HeaderAndFooterWrapperAdapter<ContentViewHolder,String>).apply {
getContentAdapter()?.apply {
getDatas().removeAt(0)
}
notifyDataSetChanged()
}
}
//和RecyclerView绑定
ware_rv.apply {
layoutManager = LinearLayoutManager(context)
adapter = headerAndFooterWrapperAdapter
}
}
//外部内容部分的ViewHolder
class ContentViewHolder(itemView: View) : HeaderAndFooterWrapperViewHolder(itemView){
var tv_name = itemView.findViewById<TextView>(R.id.tv_name)
var tv_delete = itemView.findViewById<TextView>(R.id.tv_delete)
var tv_add = itemView.findViewById<TextView>(R.id.tv_add)
}
好处:不用关心header和footer的位置
-
方案2:使用ContactAdapter
//组合Adapter,可用于多布局
// setIsolateViewTypes 是否隔离子Adapter的ViewType true:表示隔离 false:表示不隔离
//当子AAdapter和BAdapter的ViewType返回一样时候
//true:表示隔离,AAdapter返回的是AAdapter绑定的ViewHolder,BAdapter返回的是BAdapter绑定的ViewHolder
//false:表示不隔离,有可能,BAdapter返回的可能是AAdapter绑定的ViewHolder
ware_rv.apply {
layoutManager = LinearLayoutManager(context)
adapter = ConcatAdapter(ConcatAdapter.Config.Builder().setIsolateViewTypes(true).build()).apply {
addAdapter(ContentAdapter1())
addAdapter(ContentAdapter2())
addAdapter(ContentAdapter3())
addAdapter(ContentAdapter1())
addAdapter(ContentAdapter2())
addAdapter(ContentAdapter3())
}
}
class ContentAdapter1() : RecyclerView.Adapter<ContentViewHolder>() {
private var items = mutableListOf<String>()
//
init {
for (i in 0..10) {
items.add("ContentAdapter1 == " + i.toString())
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContentViewHolder {
return ContentViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_ware_test, parent, false)
)
}
override fun onBindViewHolder(holder: ContentViewHolder, position: Int) {
holder.tv_name.text = "商品名:${items.get(position)}"
holder.tv_delete.setOnClickListener {
items.removeAt(position)
notifyDataSetChanged()
}
holder.tv_add.setOnClickListener {
items.add("ContentAdapter1 new Data $position")
notifyDataSetChanged()
}
}
override fun getItemCount(): Int {
return items.size
}
}
class ContentAdapter2() : RecyclerView.Adapter<ContentViewHolder>() {
private var items = mutableListOf<String>()
//
init {
for (i in 0..10) {
items.add("ContentAdapter2 == " + i.toString())
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContentViewHolder {
return ContentViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.item_ware_test_2, parent, false)
)
}
override fun onBindViewHolder(holder: ContentViewHolder, position: Int) {
holder.tv_name.text = "商品名:${items.get(position)}"
holder.tv_delete.setOnClickListener {
items.removeAt(position)
notifyDataSetChanged()
}
holder.tv_add.setOnClickListener {
items.add("ContentAdapter2 new Data $position")
notifyDataSetChanged()
}
}
override fun getItemCount(): Int {
return items.size
}
}
class ContentAdapter3() : RecyclerView.Adapter<ContentViewHolder>() {
private var items = mutableListOf<String>()
//
init {
for (i in 0..10) {
items.add("ContentAdapter3 == " + i.toString())
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContentViewHolder {
return ContentViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_ware_test_3, parent, false)
)
}
override fun onBindViewHolder(holder: ContentViewHolder, position: Int) {
holder.tv_name.text = "商品名:${items.get(position)}"
holder.tv_delete.setOnClickListener {
items.removeAt(position)
notifyDataSetChanged()
}
holder.tv_add.setOnClickListener {
items.add("ContentAdapter3 new Data $position")
notifyDataSetChanged()
}
}
override fun getItemCount(): Int {
return items.size
}
}
//
class ContentViewHolder(itemView: View) : HeaderAndFooterWrapperViewHolder(itemView) {
var tv_name = itemView.findViewById<TextView>(R.id.tv_name)
var tv_delete = itemView.findViewById<TextView>(R.id.tv_delete)
var tv_add = itemView.findViewById<TextView>(R.id.tv_add)
}
好处:可以很方便的实现多布局,还有许多细节,读者自行研究
-
方案3,自定义View控制滑动事件和Header\Footer的布局
待续----