美文网首页
Android——自定义控件View详解

Android——自定义控件View详解

作者: 多仔百事宅 | 来源:发表于2020-10-14 17:01 被阅读0次

    为什么要自定义控件?

    1.特定的显示风格
    2.处理特有的用户交互

    例:比如原本TextView不能滑动里面的文字,通过自定义控件实现

    3.优化我们的布局

    例:通过嵌套实现复杂的布局,但是绘制和测量的效率慢,通过自定义控件实现,提升效率

    4.封装等

    例:app内很多控件可以复用,比如首页底部的tab按钮,封装成自定义控件,方便后续使用

    如何自定义控件?

    1.自定义属性的声明与获取

    提取自定义控件的属性,去声明,然后在构造方法里去获取。

    • 分析需要的自定义属性:颜色,文字大小,文字,图标等
    • 在res/values/attrs.xml定义声明
    • 在layout.xml文件中进行使用
    • 在View的构造方法中进行获取
      通过TypedArray a=context.obtainStyledAttributes()进行获取,返回来一个TypedArray对象,通过这个对象可以获取到对应的自定义属性的值,获取完成要记得recycle();
      中间获取的过程可以使用for循环,直接获取也可以
    2.测量onMeasure

    测量自身需要多大的范围,
    两个数字决定,一个测量的模式,一个测量的值
    测量的模式分三种:

    • EXACTLY:设置了明确的值,那result就等于我们设置的值
    • AT_MOST:最多不能超过某个值,这个模式一般出现在设置了wrap_content的情况下,尺寸是根据自身内容决定的,但是不能超过父控件高度和宽度
    • UNSPECIFIED:没有限制高度和宽度,适用于Listview,ScrollView等
      使用MeasureSpec对象获取自定义控件的测试模式和数值设置了大小,然后来设置自定义控件的高宽,最后要记得用setMeasuredDimension方法来把得到的result值传进去
      需要重新测量的话要调用requestLayout(),用来提供给外部进行重新测量,不包括绘制
    3.布局onLayout(ViewGroup)

    单纯的View不需要考虑这个,
    ViewGroup需要复写这个方法

    • 决定子View的位置
    • 尽可能将onMeasure中一些操作移动到此方法中(耗时操作移动到这里,onLayout只触发一次)
    • 计算好位置,通过requestLayout()这个方法进行布局
    4.绘制onDrow
    • 绘制内容区域:使用Canvas相关的API绘制你想要的效果
    • invalidate(在UI线城中调用),postInvalidate(在子线程中调用)
    • Cancas.drawXXX 熟练使用这里面的一些方法
    • translate,rotate,scale,skew 巧妙使用这些变换的方法
    • save(),restore() 结束要注意这个状态
      一般情况下,与用户没有交互的情况下,理论下只考虑onMeasure和onDrow就可以了,如果是自定义的ViewGroup还需要额外考虑onLayout
    5.onTouchEvent

    如果有交互的地方,需要在这里进行处理

    • ACTION_DOWN :
      放下手指
    • ACTION_MOVE :
      移动手指
    • ACTION_UP :
      抬起手指,如果有加入到速度检测等,在这里判断
    • ACTION_POINTER_DOWN:
      考虑多点触控时,需要考虑的类型
    • ACTION_POINTER_UP:
      考虑多点触控时,需要考虑的类型
    • getParent().requestDisallowInterceptTouchEvent(true)
      如果子view已经拿到事件了,可以调用这个方法,可以告诉父控件,不要拦截我的事件
    • VelocityTracker
    6.onInterceptTouchEvent(ViewGroup)

    事件转发过程中,事件是由交给子控件处理的,但是转发的过程中,父控件有权去拦截子控件的事件,就是通过这个方法,如果返回时true了,那就表明事件被拦截了,事件要交给ViewGroup自己去处理

    • ACTION_DOWN :
      放下手指
    • ACTION_MOVE :
      移动手指,进行一些移动距离的计算
    • ACTION_UP :
      抬起手指,如果有加入到速度检测等,在这里判断
    • ACTION_POINTER_DOWN:
      考虑多点触控时,需要考虑的类型
    • ACTION_POINTER_UP:
      考虑多点触控时,需要考虑的类型
    • getParent().requestDisallowInterceptTouchEvent(true)
      如果子view已经拿到事件了,可以调用这个方法,可以告诉父控件,不要拦截我的事件
      决定是否拦截该手势
      如果自定义的是ViewGroup,想拦截子View里面的方法,还需要写这个方法。

    相关文章

      网友评论

          本文标题:Android——自定义控件View详解

          本文链接:https://www.haomeiwen.com/subject/oluwpktx.html