自定义view实战(3):带header和footer的Layout

前言

上两篇文章对安卓自定义view的事件分发做了一些应用,但是对于自定义view来讲,并不仅仅是事件分发这么简单,还有一个很重要的内容就是view的绘制流程。接下来我这通过带header和footer的Layout,来学习一下ViewGroup的自定义流程,并对其中的MeasureSpec、onMeasure以及onLayout加深理解。

需求

这里就是一个有header和footer的滚动控件,可以在XML中当Layout使用,核心思想如下:

  • 1、由header、XML内容、footer三部分组成
  • 2、滚动中间控件时,上面有内容时header不显示,下面有内容时footer不显示
  • 3、滑动到header和footer最大值时不能滑动,释放的时候需要回弹
  • 4、完全显示时隐藏footer

编写代码

编写代码这部分还真让我头疼了一会,主要就是MeasureSpec的运用,如何让控件能够超出给定的高度,如何获得实际高度和控件高度,真是纸上得来终觉浅,绝知此事要躬行,看书那么多遍,实际叫自己写起来真的费劲,不过最终写完,才真的敢说自己对measure和layout有一定了解了。

老习惯,先看代码,再讲问题吧!

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.Scroller
import android.widget.TextView
import androidx.core.view.forEach
import kotlin.math.min

/**
 * 有header和footer的滚动控件
 * 核心思想:
 * 1、由header、container、footer三部分组成
 * 2、滚动中间控件时,上面有内容时header不显示,下面有内容时footer不显示
 * 3、滑动到header和footer最大值时不能滑动,释放的时候需要回弹
 * 4、完全显示时隐藏footer
 */
@SuppressLint("SetTextI18n", "ViewConstructor")
class HeaderFooterView @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
    defStyleAttr: Int = 0,
    var header: View? = null,
    var footer: View? = null
): ViewGroup(context, attributeSet, defStyleAttr){
   
   

    var onReachHeadListener: OnReachHeadListener? = null
    var onReachFootListener: OnReachFootListener? = null

    //上次事件的横坐标
    private var mLastY = 0f

    //总高度
    private var totalHeight = 0

    //是否全部显示
    private var isAllDisplay = false

    //流畅滑动
    private var mScroller = Scroller(context)

    init {
   
   
        //设置默认的Header、Footer,这里是从构造来的,如果外部设置需要另外处理
        header = header ?: makeTextView(context, "Header")
        footer = footer ?: makeTextView(context, "Footer")

        //添加对应控件
        addView(header, 0)

        //这里还没有加入XML中的控件
        //Log.e("TAG", "init: childCount=$childCount", )
        addView(footer, 1)
    }

    //创建默认的Header\Footer
    private fun makeTextView(context: Context, textStr: String): TextView {
   
   
        return TextView(context).apply {
   
   
            layoutParams = LayoutParams(LayoutParams.MATCH_PARENT
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值