Android自定义View以及ViewGroup初探

来源:互联网 发布:泉州五中网络应用平台 编辑:程序博客网 时间:2024/06/06 18:08

在Android中,控件大致被分为两类:ViewGroup和View。ViewGroup控件作为父控件管理其包含的View控件。例如LinearLayout下包含着一些TextView,ImageView等View控件。

自定义View

适当的使用自定义View可以丰富程序的体验效果,但是滥用View则会带来适得其反的效果。

  • 在View中通常有以下一些比较重要的 回调方法

    • onFinishInflate():从XML加载组件后回调
    • onSizeChanged():组件大小改变时回调
    • onMeasure():回调该方法用于测量
    • onLayout():回调该方法用来确定显示的位置
    • onTouchEvent():监听到触摸事件时回调
  • 通常情况下有一下3种方法来实现自定义的控件

    • 对现有控件进行扩展
    • 通过组合来实现新的控件
    • 重写View来实现全新的控件

原本想先看个效果图,但是图片太大,上传不了。想要查看动图可以去我的GitHub查看:自定义View

由于项目尝试使用freeline编译(freeline是一个秒级编译,可以提高编译速。,不了解的可以去搜索看看,这里就不做解释了),上传到GitHub的时候忘记忽略文件上传了。大家可以忽略这部分文件。

对现有控件进行扩展

下面就拿TextView进行扩展

  • 实现带闪烁的效果
    这里写图片描述

  • 实现步骤

    • 创建一个类继承自TextView
    • 利用Paint对象的Shader渲染器,通过一个不断变化的LinearGradient
    • 使用带有该属性的Paint对象来绘制要显示的文本
    • 最后通过矩阵方式来不断平移渐变效果
  • 主要重写了onSizeChanged()方法 ,对组件大小的改变进行监听。

    @Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {    super.onSizeChanged(w, h, oldw, oldh);    if (mMeasuredWidth == 0){        mMeasuredWidth = getMeasuredWidth();        if (mMeasuredWidth > 0){            mPaint = getPaint();    //获取当前绘制的TextView的Paint对象            mLinearGradient = new LinearGradient(0, 0, mMeasuredWidth, 0,                    new int[]{Color.BLUE, 0xffffffff, Color.BLUE},                    null, Shader.TileMode.CLAMP);            mPaint.setShader(mLinearGradient);  //设置原生TextView没有的LinearGradent属性            mMatrix = new Matrix();        }    }}
  • 还重写了onDraw()方法,用于绘制渐变矩形。

    @Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    if (mMatrix != null){        mTranslate += mMeasuredWidth / 5;        if (mTranslate >2*mMeasuredWidth){            mTranslate = -mMeasuredWidth ;        }        mMatrix.setTranslate( mTranslate, 0 );        mLinearGradient.setLocalMatrix(mMatrix);        postInvalidateDelayed(100); //无效后延时100毫秒后出现    }}
  • 源码

创建组合控件

组合控件可以很好的创建出具有重用功能的控件,这种方式通常需要继承一个合适的ViewGroup,再给它添加指定功能的控件,从而形成新的控件。

下面以TopBar举例

  • 先看一下效果
    这里写图片描述

  • 大部分的程序都会有一个头布局,因此将其封装成一个组合控件,可以大大减少代码的书写。 一般的头布局会有标题,返回按钮,以及更多按钮。因此我们将其进行封装。

  • 实现步骤
    • 首先在res/values目录下,创建一个attrs.xml文件,在里面定义你需要的属性。
<resources>    <declare-styleable name="TopBar">        <attr name="title" format="string"/>        <attr name="titleTextSize" format="dimension"/>        <attr name="titleTextColor" format="color"/>        <attr name="leftTextColor" format="color"/>        <attr name="leftBackground" format="reference|color"/>        <attr name="leftText" format="string"/>        <attr name="rightTextColor" format="color"/>        <attr name="rightBackground" format="reference|color"/>        <attr name="rightText" format="string"/>    </declare-styleable></resources>
  • 创建一个类继自一个ViewGroup,这里我选择 RelativeLayout。

  • 将你在atts.xml中定义的declare-styleable的所有属性的值存储到TypedArray中,获取完TypedArray的值后,一般要调用recyle方法来避免重新创建的时候的错误。

  • 动态创建3个控件

  • 为创建的控件元素赋值,值就来源于我们在引用的xml文件中给对应属性的赋值

  • 为组件元素设置相应的布局元素。也就是控件的摆放位置,是包裹内容还是铺满父布局。

  • 为了满足更多的需求,我们一般还会给控件添加点击事件,以及控件的显示和隐藏方法。

  • 最后在xml布局中引用,记得添加自定义的命名空间名称。

<com.dongxi.customerview.view.TopBar        android:id="@+id/topBar"        android:layout_width="match_parent"        android:layout_height="40dp"        custom:leftText="Back"        custom:leftBackground="@mipmap/ic_launcher"        custom:leftTextColor="@color/colorAccent"        custom:rightBackground="@mipmap/ic_launcher"        custom:rightTextColor="@color/colorAccent"        custom:rightText="MORE"        custom:title="自定义标题"        custom:titleTextColor="@color/colorAccent"        custom:titleTextSize="10sp"        />
  • 源码

重写View来实现新的控件

实现的是音频效果图

  • 效果
    这里写图片描述

  • 分析

    • 绘制一个个随机产生高度的矩形
    • 每个举行之间稍微便宜一点距离即可
    • 给绘制的Paint对象添加一个LinearGradient渐变效果
  • 源码

自定义ViewGroup

这里实现的是具有黏性的ScrollerView

  • 效果
    这里写图片描述

  • 分析

    • 首先定义一个类继承自ViewGroup,然后获取到Activity的实际屏幕信息
    • 在onMeasure方法中使用遍历对子view进行测量
    • 设置子view的摆放位置,本例中是显示在手机完整的一屏。
    • 在onLayout中将具体的参数传递进去即可完成静态的添加子view到viewgroup中
    • 重写onTouchEvent方法,对各个操作进行控制,即可实现滑动效果。
  • 话不多说,直接看源码。

0 0
原创粉丝点击