Android自定义控件之自定义属性

Stella981
• 阅读 521

前言

自定义控件可以说是android里的一个门槛,对很多android开发者来说可能都会认为比较难,当然这也是成为一个高手的必经之路,因此我准备在定义控件上多下些功夫,多花点时间研究,多写博客,如果想一起学习自定义控件,欢迎大家关注,如有疑问欢迎留言,如有谬误欢迎批评指正。

目录

Android自定义控件之自定义属性

通过本篇博客你将学到以下内容

1.自定义控件的步骤

2.自定义view中自定义属性的方法

3.自定义属性中format 10中类型的详解

一、自定义控件步骤

1.自定义View属性
2.重写onMeasure
3.重写onLayout
4.重写onDraw
今天这篇博客主要介绍第一步自定义属性,通过一个案例来进行讲解
案例的效果如下
Android自定义控件之自定义属性
即我们通过自定义View画一个圆,其中可以控制圆的半径大小和颜色,具体怎么做的呢?

二、自定义属性方法

1.首先在res/values/目录下创建attrs文件,如下所示

<declare-styleable name="CircleView">

      <attr name="circleRadius" format="dimension"/>
      <attr name="circleColor" format="color"/>
</declare-styleable>

WheelRecyclerView是自己起的名字,不要与系统的冲突就行,
<attr name="circleRadius" format="dimension"/>其中name就是自定义属性的名字(类似于系统控件的android:layout_width) format 就是属性的类型,这里支持10种类型,如下图所示
Android自定义控件之自定义属性
我们先把这个小案例的流程走完,大家对流程熟悉之后再对细节进行讲解。

2.编写自定义View,并在构造方法中获取我们自定义的属性

   public CircleView(Context context) {
        this(context,null);
    }

    public CircleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    /**
     * 获取自定义属性
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public CircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

         TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.CircleView);
        /**
         * 获取圆的半径属性
         */
        circleRadius=ta.getDimension(R.styleable.CircleView_circleRadius,DEFAULT_RADIUS);
        /**
         * 获取圆的颜色属性
         */
        mColor=ta.getColor(R.styleable.CircleView_circleColor,DEFAULT_COLOR);
        ta.recycle();


        init();
    }

从上面可以看出,在一个参数的构造方法中,调用了两个参数的构造方法,然后在两个参数的构造方法中调用了三个参数的构造方法,然后通过context的obtainStyledAttributes方法可以得到一个TypedArray对象,这个对象里面封装了获取各个属性的方法,比如getDimension,getColor,getFloat等方法用来获取属性值。

3.重写onMeasure方法

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        /**
         * Extracts the mode from the supplied measure specification
         * 从提供的测量规范中获取模式
         */
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        /**
         * Extracts the size from the supplied measure specification
         * 从提供的测量规范中获取大小
         */
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);

        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        int heightSize=MeasureSpec.getSize(heightMeasureSpec);
        /**
         * 如果宽度的测量模式是AT_MOST
         * 则设置宽度
         */
        if(widthMode==MeasureSpec.AT_MOST){

            widthSize= (int) (circleRadius*2+getPaddingLeft()+getPaddingRight());
        }

        if(heightMode==MeasureSpec.AT_MOST){

            heightSize= (int) (circleRadius*2+getPaddingTop()+getPaddingBottom());
        }

        setMeasuredDimension(widthSize,heightSize);
    }

上面我们重写了onMeasure方法,获取测量模式、获取控价大小并且按照我们自己的要求制定规则调用setMeasuredDimension此方法设置最终的宽和高。

4.重写onDraw方法

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int paddingLeft=getPaddingLeft();
        int paddingTop=getPaddingTop();
        int paddingBottom=getPaddingBottom();
        int paddingRight=getPaddingRight();

        int width=getWidth()-paddingLeft-paddingRight;
        int height=getHeight()-paddingBottom-paddingTop;

        canvas.drawCircle(width/2+paddingLeft,height/2+paddingTop,circleRadius,mPaint);
    }

onDraw方法很简单就是调用canvas的drawCircle方法,设置好圆的位置、半径和画笔画一个圆

到这里一个简单的自定义控件以及完成了,在布局中声明我们自定义的View如下:

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

    <com.example.video.CircleView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:padding="5dp"
        app:circleRadius="50dp"
        app:circleColor="#FF0000"/>

</LinearLayout>

运行即可看到文章开头的效果。

三、自定义属性format类型详解

接下来咱们对自定义属性时的format的类型做一下说明,format的类型一共10中分别为:
string、boolean、color、dimension、enum、flags、float、fraction、integer、reference。

1.string

即字符串这个很好理解,类似于系统的textview设置text内容,在attrs中声明如下

<declare-styleable name="名称">
    <attr name="text" format="string"/>
</declare-styleable>

在布局中设置如下

app:text="Hello World!"

系统textview的text设置如下

android:text="hello world!!!"

2.boolean

布尔类型,有两个值true和false,类似于系统Button的clickable属性,在attrs中声明如下

<declare-styleable name="名称">
    <attr name="clickable" format="boolean"/>
</declare-styleable>

在布局中设置如下

app:clickable="true"

系统button的clickable设置如下

android:clickable="false"

3.color

设置颜色即设置16进制的颜色,在attrs中声明如下

<declare-styleable name="名称">
    <attr name="color" format="color"/>
</declare-styleable>

在布局中有如下两种设置方式

app:color="#FFFFFF"
app:color="@color/id"

系统中给TextView设置字体颜色

android:textColor="@color/colorPrimary"

4.dimension

设置尺寸值,一般用来设置dp值,在attrs中声明如下

<declare-styleable name="名称">
    <attr name="circleRadius" format="dimension" />
</declare-styleable>

在布局中可以进行如下设置

 app:circleRadius="50dp"

系统textview设置宽度的方法

 android:layout_width="50dp"

5.enum

设置枚举,一般有几个选项,用来选择,可以参考LinearLayout的orientation属性,在attrs中声明如下

<attr name="orientation">
    <enum name="horizontal" value="0"/>
    <enum name="vertical" value="1"/>
</attr>

在布局中可以进行如下的属性设置

Android自定义控件之自定义属性

可以看到当我们输入orientation的时候会有两个选项就是我们上述xml中所声明的horizontal和vertical

系统中的LinearLayout与之同理。

6.flags

位或运算即可以进行多个选择,在atts中声明如下

<declare-styleable name="CircleView">
     <attr name="gravity" format="flags">
         <flag name="top" value="0"/>
         <flag name="center" value="1"/>
         <flag name="right" value="2"/>
         <flag name="left" value="3"/>
     </attr>
</declare-styleable>

在布局中可以进行如下的属性设置

app:gravity="right|left|top"

7.float

浮点类型,在attr中声明如下

<declare-styleable name="CircleView"> 
   <attr name = "alpha" format="float" />
</declare-styleable>

在布局中可以对属性进行如下设置

app:alpha="0.8"

8.fraction

百分数,一般有两种

  • 100% 表示相对于对象自身的百分比

  • 100%p 表示相对于父容器的百分比,percent of parent

在布局中可以属性进行如下设置

app:progress="50%"

9.integer

整形,这个很简单,就不说了

10.reference

某一资源ID,在attr中声明如下

<declare-styleable name="CircleView">
    <attr name="pic" format="reference"/>
</declare-styleable>

在布局中可以对属性进行如下设置

app:pic="@mipmap/ic_launcher"

好了以上就是对自定义属性内容的学习比较简单,但是也必须要从简单的学起,后续会逐步更新自定义View相关的内容,如有谬误欢迎批评指正,如果觉得本篇博客对你有帮助,就点个赞呗。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Android 自定义控件
用到的图片文件:!(http://static.oschina.net/uploads/space/2013/1218/202753_DiGI_584457.png)平时都是用简单的控件通过布局来组合一大堆控件,界面复杂起来的话,布局文件就很大,维护起来也很烦。就想把常用的控件组合写成自定义控件,这样维护起来也方便,代码也清爽,下面就以带消除按钮的E
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这