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

来源:互联网 发布:各种软件 编辑:程序博客网 时间:2024/05/16 03:28

http://www.cnblogs.com/whoislcj/p/5711001.html

前言:

      上篇介绍了自定义控件的基本要求以及绘制的基本原理,本篇文章主要介绍如何给自定义控件自定义一些属性。本篇文章将继续以上篇文章自定义圆形百分比为例进行讲解。有关原理知识请参考Android自定义控件之基本原理(一)这篇文章。

 自定义控件相关文章地址:

  • Android自定义控件之基本原理
  • Android自定义控件之自定义属性
  • Android自定义控件之自定义组合控件
  • Android自定义控件之自定义ViewGroup实现标签云

需求产生背景:

     为何要引入自定义属性?当Android提供的原生属性不能满足实际的需求的时候,比如我们需要自定义圆形百分比半径大小、圆形背景、圆形显示的位置、圆形进度的背景等等。这个时候就需要我们自定义属性了。

自定义属性步骤:

1.)在res/values文件下添加一个attrs.xml文件,如果项目比较大的话,会导致attrs.xml代码相当庞大,这时可以根据相应的功能模块起名字,方便查找,例如:登录模块相关attrs_login.xml

复制代码
<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="RoundImageView">        <attr name="borderRadius" />        <attr name="type" />    </declare-styleable></resources>
复制代码

2.)如何声明一组属性

使用<declare-styleable name="PercentView"></declare-styleable>来定义一个属性集合,name就是属性集合的名字,这个名字一定要起的见名知意。

  <declare-styleable name="PercentView">    <!--添加属性-->   </declare-styleable>

然后就是定义属性值了,通过<attr name="textColor" format="color" /> 方式定义属性值,属性名字同样也要起的见名知意,format表示这个属性的值的类型,类型有以下几种:

  • reference:引用资源

  • string:字符串

  • Color:颜色

  • boolean:布尔值

  • dimension:尺寸值

  • float:浮点型

  • integer:整型

  • fraction:百分数

  • enum:枚举类型

  • flag:位或运算

基于上面的要求,我们可以定义一下百分比控件属性
复制代码
    <declare-styleable name="PercentView">        <attr name="percent_circle_gravity"><!--圆形绘制的位置-->            <flag name="left" value="0" />            <flag name="top" value="1" />            <flag name="center" value="2" />            <flag name="right" value="3" />            <flag name="bottom" value="4" />        </attr>        <attr name="percent_circle_radius" format="dimension" /><!--圆形半径-->        <attr name="percent_circle_progress" format="integer" /><!--当前进度值-->        <attr name="percent_progress_color" format="color" /><!--进度显示颜色-->        <attr name="percent_background_color" format="color" /><!--圆形背景色-->    </declare-styleable>
复制代码

3.)布局中如何使用

复制代码
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:lee="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <com.whoislcj.views.PercentView        android:layout_width="200dp"        android:layout_height="200dp"        android:layout_margin="10dp"        android:background="@color/red"        android:padding="10dp"        lee:percent_background_color="@color/gray"        lee:percent_circle_gravity="left"        lee:percent_circle_progress="30"        lee:percent_circle_radius="50dp"        lee:percent_progress_color="@color/blue" /></LinearLayout>
复制代码

为属性集设置一个属性集名称,我这里用的lee,我这是因为实在想不起使用什么属性集名称了,建议在真正的项目中使用项目的缩写,比如微信可能就是使用wx。

4.)自定义控件中如何获取自定义属性

每一个属性集合编译之后都会对应一个styleable对象,通过styleable对象获取TypedArray typedArray,然后通过键值对获取属性值,这点有点类似SharedPreference的取法。

复制代码
  TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PercentView);    if (typedArray != null) {        backgroundColor = typedArray.getColor(R.styleable.PercentView_percent_background_color, Color.GRAY);        progressColor = typedArray.getColor(R.styleable.PercentView_percent_progress_color, Color.BLUE);        radius = typedArray.getDimension(R.styleable.PercentView_percent_circle_radius, 0);        progress = typedArray.getInt(R.styleable.PercentView_percent_circle_progress, 0);        gravity = typedArray.getInt(R.styleable.PercentView_percent_circle_gravity, CENTER);        typedArray.recycle();     }
复制代码

5.)完整示例

复制代码
public class PercentView extends View {    private final static String TAG = PercentView.class.getSimpleName();    private Paint mPaint;    private int backgroundColor = Color.GRAY;    private int progressColor = Color.BLUE;    private float radius;    private int progress;    private float centerX = 0;    private float centerY = 0;    public static final int LEFT = 0;    public static final int TOP = 1;    public static final int CENTER = 2;    public static final int RIGHT = 3;    public static final int BOTTOM = 4;    private int gravity = CENTER;    private RectF rectF;  //用于定义的圆弧的形状和大小的界限    public PercentView(Context context) {        super(context);        init();    }    public PercentView(Context context, AttributeSet attrs) {        super(context, attrs);        initParams(context, attrs);        init();    }    public PercentView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initParams(context, attrs);        init();    }    private void init() {        mPaint = new Paint();        mPaint.setAntiAlias(true);        rectF = new RectF();    }    private void initParams(Context context, AttributeSet attrs) {        mPaint = new Paint();        mPaint.setAntiAlias(true);        rectF = new RectF();        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PercentView);        if (typedArray != null) {            backgroundColor = typedArray.getColor(R.styleable.PercentView_percent_background_color, Color.GRAY);            progressColor = typedArray.getColor(R.styleable.PercentView_percent_progress_color, Color.BLUE);            radius = typedArray.getDimension(R.styleable.PercentView_percent_circle_radius, 0);            progress = typedArray.getInt(R.styleable.PercentView_percent_circle_progress, 0);            gravity = typedArray.getInt(R.styleable.PercentView_percent_circle_gravity, CENTER);            typedArray.recycle();        }    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        Log.e(TAG, "onMeasure--widthMode-->" + widthMode);        switch (widthMode) {            case MeasureSpec.EXACTLY://                break;            case MeasureSpec.AT_MOST:                break;            case MeasureSpec.UNSPECIFIED:                break;        }        Log.e(TAG, "onMeasure--widthSize-->" + widthSize);        Log.e(TAG, "onMeasure--heightMode-->" + heightMode);        Log.e(TAG, "onMeasure--heightSize-->" + heightSize);        int with = getWidth();        int height = getHeight();        Log.e(TAG, "onDraw---->" + with + "*" + height);        centerX = with / 2;        centerY = with / 2;        switch (gravity) {            case LEFT:                centerX = radius + getPaddingLeft();                break;            case TOP:                centerY = radius + getPaddingTop();                break;            case CENTER:                break;            case RIGHT:                centerX = with - radius - getPaddingRight();                break;            case BOTTOM:                centerY = height - radius - getPaddingBottom();                break;        }        float left = centerX - radius;        float top = centerY - radius;        float right = centerX + radius;        float bottom = centerY + radius;        rectF.set(left, top, right, bottom);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        Log.e(TAG, "onLayout");    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        mPaint.setColor(backgroundColor);        // FILL填充, STROKE描边,FILL_AND_STROKE填充和描边        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        canvas.drawCircle(centerX, centerY, radius, mPaint);        mPaint.setColor(progressColor);        double percent = progress * 1.0 / 100;        int angle = (int) (percent * 360);        canvas.drawArc(rectF, 270, angle, true, mPaint);  //根据进度画圆弧    }}
复制代码

运行结果:

根据不同的配置显示的两种效果

小结:

通过自定义属性可以达到自定义的控件也能像原生的控件一样实现可配置。但是在实际的项目开发中,像本文介绍的这种自定义控件使用频率并不是最高的,使用频率较高的是通过自定义一个组合控件的方式,来达到布局文件的复用,以减少项目维护成本以及开发成本,下篇文章将重点介绍如何自定义控件组合。

 

干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天!
分类: Android自定义控件
标签: Android 自定义控件, Android 自定义属性
好文要顶 关注我 收藏该文  
总李写代码
关注 - 1
粉丝 - 128
+加关注
0
0
« 上一篇:Android自定义控件之基本原理
» 下一篇:Android自定义控件之自定义组合控件


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 档案丢了怎么办失业证 三岁宝宝不合群怎么办 阴唇手术半月了疤痕增生怎么办 宝宝小阴唇黏连怎么办 6个月宝宝阴唇粘连怎么办? 高一孩子不爱上学怎么办 3岁宝宝外阴发红怎么办 40爸妈离婚我该怎么办 小儿吃糖卡住了怎么办 额头撞墙上肿了怎么办 宝宝额头撞肿了怎么办 小孩额头撞肿了怎么办 宝宝撞到额头肿了怎么办 小孩子上一年级语文很差了怎么办? 楼下说小孩太吵怎么办 托班的小孩太吵怎么办 宝宝两岁只会简单的词怎么办 我儿子的视力低怎么办 小孩子课文看书都不会读怎么办 宝宝衣服买小了怎么办 拉拉裤腰围小了怎么办 一周九个月宝宝发烧怎么办 8个月的婴儿37.7怎么办 宝宝发烧37度3怎么办 2岁宝宝发烧37度怎么办 3个月新生儿发烧怎么办 生完孩子肚子松弛怎么办 6个月婴儿高烧怎么办 7个月婴儿高烧怎么办 11个月婴儿高烧怎么办 4个月婴儿高烧怎么办 新生宝宝混合喂养消化不良怎么办 四个月的宝宝不追听不追视怎么办 宝宝母乳换奶粉拉肚子怎么办 奶牛产奶脂肪低怎么办 新生儿混合喂养不喝水怎么办 小孩子咳嗽怎么办有什么偏方 混合喂养宝宝不喝奶粉怎么办 混合喂养宝宝不吃奶粉怎么办 混合喂养宝宝不吃奶瓶怎么办 混合喂养的宝宝不吃奶粉怎么办