美文网首页
Android学习笔记-自定义View-基础知识

Android学习笔记-自定义View-基础知识

作者: 予久i | 来源:发表于2019-02-20 23:32 被阅读0次

    关于自定义View,说简单有些效果很方便实现,说困难有些效果需要对View的整个原理有深入的研究,而且有时对自定义View这个概念就不是很理解。经过一些网上资料的查找以及对《Android开发艺术探索》《Android进阶之光》等书籍的阅读,整理出部分知识点 简单总结一下自定义View相关知识。

    什么是自定义View

    我们平常需要一些比较炫酷、特殊的效果是系统中自带的控件无法实现的,这个时候就需要我们去继承View或者ViewGroup重写其中的某些相关方法,自己实现相关效果,也可以直接继承相关控件或者布局扩展其功能来实现我们想要的效果。

    自定义View分类

    自定义View分类标准不唯一,但是大致上可以分为四类:

    • 直接继承View
      这种的通常用于实现一些不规则的或者通过布局不易实现的效果再或者静态或者动态的显示一些不规则的图形。这个时候就可以直接继承自View并重写onDrow()方法来进行绘制。此时通常需要自己处理wrap_contentpadding。如:绘制一个圆形,绘制雷达图等。
    • 直接继承ViewGroup
      这种主要用来实现某些除系统布局之外的特殊的布局方式。比如想将几个View组合在一起的时候,便可以通过这种方式自定义相关布局。这种方式比继承View实现起来稍复杂了一些。需要对相关元素进行测量和布局。
    • 继承自某些控件
      这种方式直接继承自某些已有控件如Button、TextView等通常用来扩展已有的控件的功能,相比较于继承自View的实现更加简单不需要自己处理wrap_content、padding
    • 继承自某些布局
      这种方式和直接继承ViewGroup相比也是简便了一些,不需要自己再进行相关元素的测量和布局。当然离底层也稍微远一些。

    自定义View中的重要方法

    继承自View

    • 构造函数
      一共有四个构造函数,参数最多的构造函数是:public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes),最常用的只有前两个,相关含义:
      context:当前的上下文环境。
      attrs :可以通过该属性值得到自定义的declare-styleable属性值。
      declare-styleable:当我们在布局文件中使用自定义View并且想在该自定义View中使用新的属性时可以在value文件夹下新建attrs.xml文件为该自定义View设置自定义的属性值。
      相关代码
      综上所述:我们可以在构造函数中初始化相关数据或者通过自定义attrs.xml文件来为自定义View设置相关属性然后在构造函数中得到该自定义属性值
    • onMeasure(int widthMeasureSpec, int heightMeasureSpec)
      该方法用来测量View大小。其中的参数widthMeasureSpec是由宽度大小以及宽度的测量模式组合而成的值。可以使用MeasureSpec类的相关方法得到宽度的大小和测量模式,代码如下:
            //得到宽度大小和其测量模式
            widthSize=MeasureSpec.getSize(widthMeasureSpec);
            widthMode=MeasureSpec.getMode(widthMeasureSpec);
            //对View宽高进行修改
            //setMeasuredDimension(widthSize,heightSize);
    

    heightMeasureSpec的含义同上。
    在该方法中的到View宽高数据的同时也可以使用setMeasuredDimension(widthSize,heightSize);方法来为View设置宽度和高度大小
    关于测量模式:
    1.UNSPECIFIED
    默认的测量模式,父控件没有给子View任何限制,子View可以设置为任意大小
    2.EXACTLY
    精确模式,表示父控件已经确切的指定了子View的大小,对应于:直接指定宽高属性值或者match_parent
    3.AT_MOST
    最大模式,子View大小没有具体限制,子View最大为父View大小,对应于:wrap_content

    • onSizeChanged(int w, int h, int oldw, int oldh)
      该方法在View大小发生改变时调用。可以用来得到当前View的大小,该方法的四个参数含义:
      1.w 当前View的宽度
      2.h 当前View的高度
      3.oldw 上一次View的宽度
      4.oldh 上一次View的高度
    • onDraw(Canvas canvas)
      该方法就是我们自定义View中最常用也是最重要的方法,我们可以在该方法中绘制我们想要的View图形。首先说明参数canvas:画布,具有一系列与图形绘制相关的方法。
      完成一个View会依次经过以下绘制过程:
      1.背景
      使用drawBackground()方法进行绘制,该方法不能重写
      2.主体
      使用onDraw()方法进行绘制,该方法可重写
      3.子View
      使用dispatchDraw()方法进行绘制,该方法可重写
      4.滑动边缘渐变和滑动条
      使用onDrawForeground()方法进行绘制,该方法可重写
      5.前景
      使用onDrawForeground()方法进行绘制,该方法可重写

    所以我们可以通过重写相应的方法来控制View绘制的顺序和绘制内容
    相关代码

    继承自ViewGroup

    • onLayout(boolean changed, int left, int top, int right, int bottom)
      该方法主要用来确定子View的布局位置,在自定义ViewGroup时使用,调用子Viewlayout函数,用于确定子View的位置。可以在该方法中调用相关方法实现对子View的控制,如:
            //子View个数
            int count=getChildCount();
            //子View对象
            View child=getChildAt(0);
    

    相关参数含义:
    changedView是否有新的位置和尺寸即是否改变
    left:子View左侧距离父View左侧的距离
    top:子View顶部距离父View顶部的距离
    right:子View右侧距离父View右侧的距离
    bottom:子View底部距离父View底部的距离

    • 构造函数
      同继承自View
    • onMeasure(int widthMeasureSpec, int heightMeasureSpec)
      同继承自View
    • onSizeChanged(int w, int h, int oldw, int oldh)
      同继承自View
    • onDraw(Canvas canvas)
      同继承自View

    绘制自定义View所使用的工具

    Paint

    画笔,顾名思义 该工具类主要是在图形绘制的过程中像一支笔一样与Canvas以及Path相配合用来辅助图形的绘制。只不过我们可以通过相关的方法来设置这支的颜色,粗细等属性。
    示例:

            mPaint=new Paint();
            mPaint.setColor(Color.BLUE);    //画笔颜色
            mPaint.setStyle(Paint.Style.FILL);  //设置画笔模式为填充
            mPaint.setStrokeWidth(10f);     //设置画笔宽度为10px
    

    Canvas

    画布,和画笔一样由名字便可得知它的作用,我们绘制图形便是在Canvas上实现,可以与Paint和Path相互配合绘制出各种效果。该工具类为我们提供了:
    基本图形
    如:圆形、矩形、椭圆、点、线、圆弧等的绘制方法。
    画布的相关操作
    缩放、位移、旋转、设置显示区域等相关方法的实现。
    基本图形绘制-部分相关代码
    画布相关操作-部分相关代码

    Path

    路径,主要用来实现一些比点、线、圆、圆弧等更加复杂的操作。如:心形、正多边形、贝塞尔曲线等。
    部分相关代码

    如何为自定义View设置自定义属性

    • 设置自定义属性attrs.xml
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="CustomView">
            <attr name="custom_view_color" format="color"/>
        </declare-styleable>
    </resources>
    
    • 在自定义View得到自定义属性的值:
    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            //获取自定义属性值
            TypedArray customViewAttrs=context.obtainStyledAttributes(attrs, R.styleable.CustomView);
            int mColor=customViewAttrs.getColor(R.styleable.CustomView_custom_view_color, Color.RED);
        }
    
    • 使用自定义属性在布局文件中:
    <com.example.androidprimarycodedemo.custom_view.CustomView
        android:id="@+id/custom_view"
        app:custom_view_color="@color/colorAccent"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

    实现自定义View步骤

    通过上述一些知识的了解,我们大致可以得到自定义View的大体步骤。
    1、选定要继承的View类
    分析要实现的效果确定要实现的自定义View类需要继承自ViewViewGroup、特定控件还是特定的布局。
    2、确定自定义View大小、位置等所需数据
    根据实际情况确实是否需要处理wrap_contentpadding以及通过相关函数的到实际需要的参数等。
    3、根据具体情况进行绘制
    根据要实现的效果选择相应的PaintPath以及Canvas的一些效果进行自定义View的绘制。

    自定义View注意事项

    • 让View支持wrap_content
      直接继承自ViewViewGrop的自定义View如果不在onMeasure中对wrap_content进行特殊处理,当外界布局使用wrap_content属性时将无法达到预期效果。
    • 如果有必要,让你的View支持padding
      直接继承自View的控件如果不在draw中处理padding,则padding属性无法起作用,继承自ViewGroup的控件需要在onMeasureonLayout中考虑padding和子元素的margin对其造成的影响,否则将导致padding和子元素的margin失效。
    • 尽量不要再View中使用Handler,没必要
      View内部提供了post系列方法可以替代Handler的作用。
    • View中如果有线程和动画,需要及时停止
      View中带有线程或者动画时最好在onAttachedToWindow方法调用时是启动,在onDetachedFromWindow方法调用时停止,防止造成内存泄漏。
    • View带有滑动嵌套冲突情形时,需要处理好滑动冲突
      滑动冲突如果不能处理好则会影响View的效果。

    上述 自定义View分类和自定义View注意事项 内容摘抄自《Android开发艺术探索》

    相关文章

      网友评论

          本文标题:Android学习笔记-自定义View-基础知识

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