自定义View理解

一、 为什么要学习自定义View

      主要是Android系统内置的View无法实现我们的需求,我们需要针对我们的业务需求定制我们想要的View

自定义View的方式:

 

自定义View我们大部分时候只需重写两个函数:onMeasure()、onDraw()。onMeasure负责对当前View的尺寸进行测量,onDraw负责把当前这个View绘制出来。

自定义View的绘制流程


集成View:View流程

onMeasure() (在这个方法里指定自己的宽高) -> onDraw() (绘制自己的内容)

集成ViewGroup:ViewGroup流程 

onMeasure() (指定自己的宽高, 所有子View的宽高)-> onLayout() (摆放所有子View) -> onDraw() (绘制内容)


二、 常用的方法:

获取父View提供的参考大小

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

设置自定义View的尺寸大小(在OnMeasure的最后调用)

setMeasuredDimension(width, height);

刷新View(invalidate() postInvalidate())

invalidate()与postInvalidate()这两个都是刷新View的API,它们主要的区别是invalidate()可以在主线程(UI线程)中调用,而不能在子线程中调用,若在子线程中进行刷新view的操作需要配合handler来使用。而postInvalidate()可以在子线程中直接调用。

三、自定义布局属性(通我们自定属性,让用户用我们定义的属性)

①第一步: 首先我们需要在 res/values/styles.xml 文件(如果没有请自己新建)里面声明一个我们自定义的属性:
<resources>

     <!--name为声明的"属性集合"名,可以随便取,但是最好是设置为跟我们的View一样的名称-->
    <declare-styleable name="MyView">
         <!--声明我们的属性,名称为default_size,取值类型为尺寸类型(dp,px等)-->
        <attr name="default_size" format="dimension" />
    </declare-styleable>

</resources>

②第二步:在布局文件用上我们的自定义的属性啦

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:hc="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"

    android:layout_height="match_parent">


    <com.hc.studyview.MyView
        android:layout_width="match_parent"
        android:layout_height="100dp"
         hc:default_size="100dp"  />

</LinearLayout>

注意:需要在根标签(LinearLayout)里面设定命名空间,命名空间名称可以随便取,比如hc,命名空间后面取得值是固定的:"http://schemas.android.com/apk/res-auto"。

③第三步:我们的自定义的View里面把我们自定义的属性的值取出来,在构造函数中,还记得有个AttributeSet属性吗?就是靠它帮我们把布局里面的属性取出来。

  public MyView(Context context, AttributeSet attrs) {
      super(context, attrs);
      //第二个参数就是我们在styles.xml文件中的<declare-styleable>标签
        //即属性集合的标签,在R文件中名称为R.styleable+name
        TypedArray a = 
context.obtainStyledAttributes(attrs, R.styleable.MyView);


        //第一个参数为属性集合里面的属性,R文件名称:
R.styleable+属性集合名称+下划线+属性名称
        //第二个参数为,如果没有设置这个属性,则设置的默认的值
        defalutSize = a.getDimensionPixelSize(R.styleable.MyView_default_size, 100);


        //最后记得将TypedArray对象回收
        a.recycle();

   }

四、注意的问题

1. 支持wrap_content 

如果不在onMeasure()中对wrap_content作特殊处理,那么wrap_content属性将失效

2. 支持padding & margin 

如果不支持,那么paddingmargin(ViewGroup情况)的属性将失效

                 对于继承View的控件,padding是在draw()中处理

                   对于继承ViewGroup的控件,padding和margin会直接影响measure和layout过程

3. 启动或停止线程/ 动画的方式: 
1. 启动线程/ 动画:使用view.onAttachedToWindow(),因为该方法调用的时机是当包含View的Activity启动的时刻 
2. 停止线程/ 动画:使用view.onDetachedFromWindow(),因为该方法调用的时机是当包含View的Activity退出或当前View被remove的时刻

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值