Android-Kotlin Recycleview 점성 헤드 그룹 효과 실현

선행 효과 도:
그림 에서 볼 수 있 듯 이 점성 머리 를 추가 하 는 것 도 직관 적 인 조별 효과 에 해당 하고 비교적 많은 실현 방식 이 있다.예 를 들 어:
  • RecyclerView 의 ItemDecoration 을 통 해 실현
  • BaseSection QuickAdapter 어댑터 를 통 해 실현
  • 본 고 는 RecyclerView 의 ItemDecoration 재 작성 을 통 해 이 루어 집 니 다.BaseSection QuickAdapter 를 사용 하려 면 BRVAH 를 참고 하 십시오.
    https://github.com/CymChad/BaseRecyclerViewAdapterHelper
    코드 를 붙 이기 전에 아 이 템 데 코 레이 션 부터 알 아 보 겠 습 니 다.
    소개:
    공식 소개
    An ItemDecoration allows the application to add a special drawing and layout offset to specific item views from the adapter's data set. This can be useful for drawing dividers between items, highlights, visual grouping boundaries and more.
    All ItemDecorations are drawn in the order they were added, before the item views (in onDraw() and after the items (in onDrawOver(Canvas, RecyclerView, RecyclerView.State).
    정부의 설명 정 의 는 여전히 명확 하고 정확 하 다.
    ItemDecoration 은 구체 적 인 View 에 구체 적 인 그림 이나 layot 의 오프셋 을 추가 할 수 있 습 니 다.View 간 의 분할 선,시각 적 그룹 경계 등 을 그 리 는 데 매우 유용 합 니 다.모든 ItemDecorations 는 추 가 된 순서에 따라 itemview 전에('onDraw()'를 다시 쓰 거나 itemview 를 다시 쓰 면('onDrawOver(Canvas,RecyclerView,RecyclerView.State)'을 다시 쓰 면 그립 니 다.
    따라서 전체적인 실현 방향 은 ItemDecoration 을 다시 쓰 는 것 입 니 다.인터페이스 리 셋 을 통 해 데이터 data 배열 에서 해당 하 는 item 의 날 짜 를 가 져 오고 날 짜 를 통 해 그룹 을 나 누 어 item 의 오프셋 을 설정 한 다음 onDrawOver 를 통 해 그룹 디 스 플레이 를 그립 니 다.
    ItemDecoration 은 유행 이 지난 것 을 제외 하고 다음 세 가지 방법 만 남 았 습 니 다.
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)

    그 중 세 가지 방법의 용도
  • getItemOffests 는 outRect.set(l,t,r,b)를 통 해 지정 한 itemview 의 paddingLeft,paddingTop,paddingRight,paddingBottom
  • 을 설정 할 수 있 습 니 다.
  • onDraw 는 일련의 c.drawXXX()방법 으로 itemView 를 그리 기 전에 우리 가 필요 로 하 는 내용 을 그 릴 수 있 습 니 다.
  • onDrawOver 는 onDraw 와 유사 합 니 다.itemView 를 그린 후에 그립 니 다.구체 적 인 표현 형식 은 바로 그 려 진 내용 이 itemview 상층 부 에 있 습 니 다.

  • RecyclerView 의 addItemDecoration() ItemDecoration 을 호출 하면 ItemDecoration 은 집합 에 추가 되 고 RecyclerView 는 add 의 순서에 따라 순서대로 호출(getItemOffsets->onDraw->onDrawOver하 는 방법 입 니 다.
    실 현 된 코드 붙 이기:
    어댑터,필요 에 따라 다른 adapter 를 계승 하여 사용 할 수 있 습 니 다:
    class UndoneTodoListAdapter (val context: Context, datas: MutableList) :
            BaseQuickAdapter(R.layout.undone_todo_item, datas) {
    
        private var d : MutableList = datas
    
        override fun getItemCount(): Int {
            return d.size
        }
    
        override fun convert(helper: BaseViewHolder?, item: TodoListResponse.Data.Datas?) {
            item ?: return
            var p : String = "  "
            when {
                item.priority == 1 -> p = "  "
                item.priority == 2 -> p = "  "
            }
            if (helper != null) {
                @Suppress("DEPRECATION")
                helper.setText(R.id.item_title, item.title)
                        .setText(R.id.item_content, item.content)
                        .setText(R.id.todo_p, "   :$p")
                        .addOnClickListener(R.id.delete_todo)
                        .addOnClickListener(R.id.update_status_todo)
                when {
                    item.type == 1 -> helper.setImageResource(R.id.item_type, R.drawable.work)
                    item.type == 2 -> helper.setImageResource(R.id.item_type, R.drawable.sport)
                    item.type == 3 -> helper.setImageResource(R.id.item_type, R.drawable.play)
                }
    
            }
        }
    
    }

    item 레이아웃 코드:
    
    
    
        
    
            
    
            
    
            
    
        
        
        
    
            
    
        
    
        
    
            
    
            
    
        
    
    
            StickyDecoration
    class StickyDecoration(context: Context, decorationCallback: DecorationCallback) : RecyclerView.ItemDecoration() {
    
        private var callback: DecorationCallback? = decorationCallback
        private var textPaint: TextPaint? = null
        private var paint: Paint? = null
        private var topHead: Int = 0
        private var topHeadD: Int = 0
    
        init {
            paint = Paint()
            paint!!.color = ContextCompat.getColor(context, R.color.bg_header)
            textPaint = TextPaint()
            textPaint!!.typeface = Typeface.DEFAULT
            textPaint!!.isFakeBoldText = false
            textPaint!!.isAntiAlias = true
            textPaint!!.textSize = 35f
            textPaint!!.color = ContextCompat.getColor(context, R.color.colorPrimary)
            textPaint!!.textAlign = Paint.Align.LEFT
            topHead = context.resources.getDimensionPixelSize(R.dimen.head_top)
            topHeadD = context.resources.getDimensionPixelSize(R.dimen.head_top_d)
        }
    
        override fun getItemOffsets(outRect: Rect?, view: View?, parent: RecyclerView?, state: RecyclerView.State?) {
            super.getItemOffsets(outRect, view, parent, state)
            val position = parent!!.getChildAdapterPosition(view)
            val data : String = callback!!.getData(position)
            if (TextUtils.isEmpty(data) || TextUtils.equals(data,"")) {
                return
            }
            //          padding
            if (position == 0 || isHeader(position)) {
                outRect!!.top = topHead
            } else {
                outRect!!.top = topHeadD
            }
        }
    
        override fun onDrawOver(c: Canvas?, parent: RecyclerView?, state: RecyclerView.State?) {
            super.onDrawOver(c, parent, state)
            //       item   
            val childCount = parent!!.childCount
            //      item  
    //        val itemCount = state!!.itemCount
            val itemCount = parent.adapter.itemCount
            val left : Int = parent.left + parent.paddingLeft
            val right : Int = parent.right + parent.paddingRight
            var preData : String?
            var currentDate : String? = null
            for (i in 0 until childCount) {
                val view = parent.getChildAt(i)
                val position = parent.getChildAdapterPosition(view)
                val textLine = callback!!.getData(position)
                preData = currentDate
                currentDate = callback!!.getData(position)
                if (TextUtils.isEmpty(currentDate) || TextUtils.equals(currentDate, preData)) {
                    continue
                }
                if (TextUtils.isEmpty(textLine)) {
                    continue
                }
                val viewBottom = view.bottom
                var textY = max(topHead, view.top).toFloat()
                //             
                if (position + 1 < itemCount) {
                    val nextData = callback!!.getData(position + 1)
                    if (currentDate != nextData && viewBottom < textY) {
                        //      view   header
                        textY = viewBottom.toFloat()
                    }
                }
                val rect = Rect(left, textY.toInt() - topHead, right, textY.toInt())
                c!!.drawRect(rect, paint!!)
                //      ,                  
                val fontMetrics = textPaint!!.fontMetrics
                val baseline = ((rect.bottom + rect.top).toFloat() - fontMetrics.bottom - fontMetrics.top) / 2
                textPaint!!.textAlign = Paint.Align.CENTER//    
                //    
                c.drawText(textLine, 100F, baseline, textPaint!!)
            }
        }
    
        //       
        private fun isHeader(pos: Int): Boolean {
            return if (pos == 0) {
                true
            } else {
                val preData = callback!!.getData(pos - 1)
                val data = callback!!.getData(pos)
                preData != data
            }
        }
    
        interface DecorationCallback {
            fun getData(position: Int): String
        }
    }

    사용 추가
    todo_rv.run {
                layoutManager = LinearLayoutManager(context)
                adapter = todoListAdapter
                addItemDecoration(StickyDecoration(context, object : StickyDecoration.DecorationCallback {
                    override fun getData(position: Int): String {
                        return datas[position].dateStr
                    }
                }))
            }

    좋은 웹페이지 즐겨찾기