周记(1)-2019-10-27-Android

  1. Bug 汇总

    1. merge 标签在 ConstraintLayout 中约束失效。
      1. 参考链接
  2. 知识点

    1. RecyclerView 自定义 ItemDecoration
      1. 参考链接1
      2. 参考链接2
      3. RecyclerView animation 的库
    2. LayoutInflater 填充界面
      1. 郭神的文章

1. Bugs:

  1. 在 ConstraintLayout 布局中使用 include 添加根布局标签为 merge 的 xml 页面时,约束失效。

解决方案:

  • 在被添加的页面中,移除 merge 标签。

当使用 include 标签时,系统会把 include 标签的属性运用到被添加页面到根视图上。但是 merge 标签是一个特殊的标签,它允许你在布局中有多个视图,但没有根视图。所以使用 merge 标签时,所有约束会被丢弃。

2. 知识点

1. ItemDecoration

实现自定义的 ItemDecoration,主要重写三个方法,getOffSetsonDraw、和 onDrawOver

1.1 getItemOffSets

  • 作用:

设置 ItemView 的内嵌偏移长度,每个 ItemView 外部都有一个 Rect 矩形(OutRect),默认 ItemView 在 OutRect 中的偏移为 0(重叠),通过调用 outRect 方法可以设置内部 View 的偏移量。

  • 代码:
    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        outRect.set(50, 50, 50, 50)
    }
  • 效果:

原图和实现对比图

1.2 onDraw

onDraw 用于在 ItemView 上进行绘制,onDraw优先进行绘制,并被

  • 作用:

为每个 ItemView 绘制,绘制图层在 ItemView 以下,如果绘制区域相重叠,会被 ItemView 遮挡。

  • 代码:
    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
        val childCount = parent.childCount
        paint.color = Color.YELLOW
        for (i in 0 until childCount) {
            val child = parent.getChildAt(i)
            val divider = 10
            val left = child.left
            val top = child.top - divider
            val right = child.right
            val bottom = child.bottom + divider
            c.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), paint)
        }
    }
  • 效果:

绘制的黄色矩形被 ItemView 遮挡

1.3 onDrawOver

  • 作用:

绘制图像,并显示在 itemView 的上层。

  • 代码:
    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDrawOver(c, parent, state)
        val childCount = parent.childCount
        paint.color = Color.RED
        for (i in 0 until childCount) {
            val child = parent.getChildAt(i)
            val top = child.top
            val left = child.right - bitmap.width
            c.drawBitmap(bitmap,left.toFloat(),top.toFloat(),paint)
        }
    }
  • 效果:

1.4 实现自定义头部并将头部保持在顶部

  • 代码
package com.learnandroid.androidlibraryapp.fragments

import android.content.Context
import android.graphics.*
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.learnandroid.androidlibraryapp.R

/**
 * com.learnandroid.androidlibraryapp.fragments
 * Author: binguner
 * Date: 2019-10-23 20:24
 */
class MyRecyclerViewDecoration(val context: Context) : RecyclerView.ItemDecoration() {

    private val paint: Paint = Paint()
    private val textPaint: Paint = Paint()
    private var bitmap:Bitmap = BitmapFactory.decodeResource(context.resources,R.drawable.ic_account_circle_black_24dp)
    private val TAG = MyRecyclerViewDecoration::class.java.simpleName
    private var mIndex: Int = 0

    // 设置 ItemView 的内嵌偏移长度,每个 ItemView 外部都有一个 Rect 矩形(OutRect),默认 ItemView 在 OutRect 中的偏移为 0(重叠)
    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        val position = parent.getChildAdapterPosition(view)
        if (position % 5 == 0) {
            outRect.set(0, 50, 0, 0)
        }
    }

    // 在子视图上设置绘制范围,并绘制内容,绘制图层在 ItemView 以下,如果绘制区域相重叠,会被遮挡
    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
    }

    // 绘制内容:绘制在图层的最上面
    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDrawOver(c, parent, state)
        paint.color = Color.YELLOW
        textPaint.color = Color.BLACK
        textPaint.textSize = 35f
        val childCount = parent.childCount
        for (i in 0 until childCount) {
            val child = parent.getChildAt(i)
            val index = parent.getChildAdapterPosition(child)
            if (index % 5 == 0) {
                if (i < 5) {
                    if (i == 1 && child.top < 100 ) {
                        val divider = 50
                        val top = child.top - divider
                        val left = child.left
                        val bottom = child.top
                        val right = child.right
                        c.drawRect(left.toFloat(),top.toFloat(),right.toFloat(),bottom.toFloat(),paint)
                        c.drawText("Index is $index", left.toFloat(), child.top.toFloat() - 10, textPaint)
                    }else{
                        val divider = 50
                        val top = 0
                        val left = 0
                        val bottom = divider
                        val right = child.right
                        c.drawRect(left.toFloat(),top.toFloat(),right.toFloat(),bottom.toFloat(),paint)
                        if (i == 0) {
                            c.drawText("Index is ${index}", left.toFloat(), 35f, textPaint)
                        } else {
                            c.drawText("Index is ${index - 5}", left.toFloat(), 35f, textPaint)
                        }
                    }
                }
                if (i != 0) {
                    val divider = 50
                    val top = child.top - divider
                    val left = child.left
                    val bottom = child.top
                    val right = child.right
                    c.drawRect(left.toFloat(),top.toFloat(),right.toFloat(),bottom.toFloat(),paint)
                    c.drawText("Index is $index", left.toFloat(), child.top.toFloat() - 10, textPaint)
                }
            }
            val top = child.top
            val left = child.right - bitmap.width
            c.drawBitmap(bitmap,left.toFloat(),top.toFloat(),paint)
            if (i < 5) {
                val divider = 50
                val top = child.top - divider
                val left = child.left
                val right = child.right
                val bottom = child.top
            }
    }

}
  • 效果

2. LayoutInflater

LayoutInflater 的 infalte 方法有以下几个重载:

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) 
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)

第一个方法里调用第二个方法,attachToRoot 默认为 true。

  • 如果 root 为 null,attachToRoot 没有意义
  • 如果 root 不为 null,attachToRoot 为 true,会给当前 View 添加一个父布局(root)
  • 如果 root 部位 null,arrachToRoot 为 false,会将布局文件最外层的所有 layout 属性进行设置,当该 View 被添加到父布局中,layout 属性自动生效。
发布了27 篇原创文章 · 获赞 9 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/nenguou04/article/details/102779571