1、使用ItemDecoration
class CarBrandStickItemDecoration(var context: Context) : RecyclerView.ItemDecoration() {
private var mItemHeaderHeight = 50
private var mItemHeaderPaint = Paint()
private var mTextPaint = Paint()
private var mLinePaint = Paint()
private var hotCityText = "热门品牌"
init {
mItemHeaderHeight = context.dp2px(30)
mItemHeaderPaint.color = context.resources.getColor(R.color.color_gray_f0)
mTextPaint.color = context.resources.getColor(R.color.color_gray_ae)
mTextPaint.textSize = context.sp2px(14).toFloat()
mLinePaint.color = context.resources.getColor(R.color.color_gray_eb)
}
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
if (parent.adapter is CarBrandAdapter) {
val adapter = parent.adapter as CarBrandAdapter
if (adapter.itemCount == 0) {
return
}
val position = parent.getChildAdapterPosition(view)
if (adapter.isHeaderItem(position)) {
outRect.top = mItemHeaderHeight
} else {
outRect.top = 1
}
}
}
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
if (parent.adapter is CarBrandAdapter) {
val adapter = parent.adapter as CarBrandAdapter
if (adapter.itemCount == 0) {
return
}
for (i in 0 until parent.childCount) {
val view = parent.getChildAt(i)
val position = parent.getChildAdapterPosition(view)
if (adapter.isHeaderItem(position)) {
c.drawRect(0f, (view.top - mItemHeaderHeight).toFloat(), parent.width.toFloat(), view.top.toFloat(), mItemHeaderPaint)
val textRect = Rect()
if (adapter.hasHotCity() && position == 0) {
mTextPaint.getTextBounds(hotCityText, 0, hotCityText.length, textRect)
c.drawText(hotCityText, context.dp2px(15).toFloat(),
((view.top - mItemHeaderHeight) + mItemHeaderHeight / 2 + textRect.height() / 2).toFloat(), mTextPaint)
} else {
mTextPaint.getTextBounds(adapter.getGroupName(position), 0, adapter.getGroupName(position).length, textRect)
c.drawText(adapter.getGroupName(position), context.dp2px(15).toFloat(),
((view.top - mItemHeaderHeight) + mItemHeaderHeight / 2 + textRect.height() / 2).toFloat(), mTextPaint)
}
} else {
c.drawRect(0f, view.top - 1f, parent.width.toFloat(), view.top.toFloat(), mLinePaint)
}
}
}
}
override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
if (parent.adapter is CarBrandAdapter) {
val adapter = parent.adapter as CarBrandAdapter
if (adapter.itemCount == 0) {
return
}
val position = (parent.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
val view = parent.findViewHolderForAdapterPosition(position)?.itemView!!
if (adapter.isHeaderItem(position + 1)) {
val bottom = Math.min(mItemHeaderHeight, view.bottom)
c.drawRect(0f, view.top - mItemHeaderHeight.toFloat(), parent.width.toFloat(), bottom.toFloat(), mItemHeaderPaint)
val textRect = Rect()
if (adapter.hasHotCity() && position == 0) {
mTextPaint.getTextBounds(hotCityText, 0, hotCityText.length, textRect)
c.drawText(hotCityText, context.dp2px(15).toFloat(), mItemHeaderHeight.toFloat() / 2 + textRect.height() / 2 - (mItemHeaderHeight - bottom), mTextPaint)
} else {
mTextPaint.getTextBounds(adapter.getGroupName(position), 0, adapter.getGroupName(position).length, textRect)
c.drawText(adapter.getGroupName(position), context.dp2px(15).toFloat(), mItemHeaderHeight.toFloat() / 2 + textRect.height() / 2 - (mItemHeaderHeight - bottom), mTextPaint)
}
} else {
c.drawRect(0f, 0f, parent.width.toFloat(), mItemHeaderHeight.toFloat(), mItemHeaderPaint)
val textRect = Rect()
if (adapter.hasHotCity() && position == 0) {
mTextPaint.getTextBounds(hotCityText, 0, hotCityText.length, textRect)
c.drawText(hotCityText, context.dp2px(15).toFloat(), mItemHeaderHeight.toFloat() / 2 + textRect.height() / 2, mTextPaint)
} else {
mTextPaint.getTextBounds(adapter.getGroupName(position), 0, adapter.getGroupName(position).length, textRect)
c.drawText(adapter.getGroupName(position), context.dp2px(15).toFloat(), mItemHeaderHeight.toFloat() / 2 + textRect.height() / 2, mTextPaint)
}
}
}
}
}
2、adapter
class CarBrandAdapter(var context: Context, var mList: MutableList<CarBrand>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var hotList = mutableListOf<CarBrand>()
var layoutManager: LinearLayoutManager? = null
private var onCarBrandSelectedListener: OnCarBrandSelectedListener?= null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
if (viewType == 0)
return BrandViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_item_car_brand, parent, false))
return HotBrandViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_hot_brand, parent, false))
}
override fun getItemCount(): Int {
if (hotList.isEmpty()) {
return mList.size
}
return mList.size + 1
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is BrandViewHolder) {
val realPosition = getRealPosition(position)
if (mList[realPosition].carIcon.isNotNil()) {
holder.ivLogo.display(mList[realPosition].carIcon)
} else {
holder.ivLogo.setImageResource(R.mipmap.default_product)
}
holder.tvBrand.text = mList[realPosition].brandName
holder.clContent.onClick {
onCarBrandSelectedListener?.apply {
this.onCarBrandSelected(mList[realPosition])
}
}
} else if (holder is HotBrandViewHolder) {
holder.rvHotBrand.layoutManager = GridLayoutManager(context, 5)
val adapter = BaseRecyclerViewAdapter(context, hotList, R.layout.layout_tab_item_5_1) { view, carBrand, position1 ->
if (carBrand.carIcon.isNotNil()) {
view.findViewById<ImageView>(R.id.iv_icon).display(carBrand.carIcon)
} else {
view.findViewById<ImageView>(R.id.iv_icon).setImageResource(R.mipmap.default_product)
}
view.findViewById<TextView>(R.id.tv_text).text = carBrand.brandName
}
adapter.setOnItemClickListener(object : BaseRecyclerViewAdapter.OnItemClickListener {
override fun onItemClick(v: View, position: Int) {
onCarBrandSelectedListener?.apply {
this.onCarBrandSelected(hotList[position])
}
}
})
holder.rvHotBrand.adapter = adapter
}
}
override fun getItemViewType(position: Int): Int {
if (position == 0 && hotList.isNotEmpty()) {
return 1
}
return 0
}
fun scrollToSection(index: String) {
if (index == "#" && hotList.isNotEmpty() && layoutManager != null) {
layoutManager?.scrollToPositionWithOffset(0, 0)
return
}
if (mList.isEmpty()) return
if (index.isEmpty()) return
for (i in 0 until mList.size) {
if (index == mList[i].headChar.substring(0, 1)) {
if (layoutManager != null) {
layoutManager?.scrollToPositionWithOffset(i, 0)
return
}
}
}
}
fun isHeaderItem(position: Int): Boolean {
if (position == 0) {
return true
} else {
val realPosition = getRealPosition(position)
val lastGroupName = if (realPosition == 0) "#" else mList[realPosition - 1].headChar.substring(0, 1)
val currGroupName = mList[realPosition].headChar.substring(0, 1)
return lastGroupName != currGroupName
}
}
fun getGroupName(position: Int): String {
if (position == 0 && hotList.isNotEmpty()) {
return hotList[0].headChar.substring(0, 1)
}
return mList[getRealPosition(position)].headChar.substring(0, 1)
}
fun getRealPosition(position: Int): Int {
return if (itemCount == mList.size) position else position - 1
}
fun hasHotCity(): Boolean {
return hotList.isNotEmpty()
}
fun setData(data: List<CarBrand>, hotList: List<CarBrand>) {
mList.clear()
mList.addAll(data)
this.hotList.clear()
this.hotList.addAll(hotList)
notifyDataSetChanged()
}
fun setOnCarBrandSelectedLsitener(onCarBrandSelectedListener: OnCarBrandSelectedListener) {
this.onCarBrandSelectedListener = onCarBrandSelectedListener
}
class BrandViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var clContent = itemView.findViewById<ConstraintLayout>(R.id.cl_content)
var ivLogo = itemView.findViewById<ImageView>(R.id.iv_logo)
var tvBrand = itemView.findViewById<TextView>(R.id.tv_brand)
}
class HotBrandViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var rvHotBrand = itemView.findViewById<RecyclerView>(R.id.rv_hot)
}
interface OnCarBrandSelectedListener {
fun onCarBrandSelected(brand: CarBrand)
}
}
3、数据结构
data class CarBrand(
var brandName: String = "",
var id: String,
var carIcon: String = "",
var headChar: String = "",
var pinYin: String = ""
)
网友评论