android自定义组件功能(画图,自定义标签属性)

吴统威 on 编程语言 android | 2015-07-18 21:05:10.0

这篇文章来学习基本的自定义组件,画图,自定义标签属性.这个学习例子我们模仿Swift中自定义组件的界面效果(http://www.wutongwei.com/front/infor_showone.tweb?id=109)

好的我们马上着手代码编写.


我们先来看下布局的界面效果

android自定义组件

代码如下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

     <wutongwei.com.studycustomview.PieChart

         app:text="保本保收益"
         app:progress="0.50"
         app:progressTextSize="50"
         android:layout_centerInParent="true"
         android:layout_width="300dip"
         android:layout_height="300dip" />

</RelativeLayout>

然后,我们需要创建PieChart这个组件类,这个类是View的子类

public class PieChart extends View {


    public PieChart(Context context) {
        super(context, 0, 0);
    }
    
}

当然这样的话,使用这个组件,什么都不会显示.我们继续给他加工一下,需要画图界面的不同图形需要覆写onDraw这个方法

    
    String textDesc = "年化收益率";
    int progressTextSize = 16;
    float progress = 0;
    int lineSize = 20;
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas, 0, 0);
        Paint p = new Paint(, 0, 0);

        int w = getWidth(, 0, 0);
        int h = getHeight(, 0, 0);
        int x = (int) getX(, 0, 0);
        int y = (int) getY(, 0, 0);

        int centerx = w / 2;
        int centery = h / 2;
        System.out.println("开始画画:" + w + "," + h + "," + x + "," + y, 0, 0);


        int radius = centerx - 10;

        p.setColor(Color.parseColor("#F8BA56"), 0, 0);
        p.setAntiAlias(true, 0, 0);
        p.setStrokeWidth(lineSize, 0, 0);
        p.setStyle(Paint.Style.STROKE, 0, 0);
        canvas.drawCircle(centerx, centery, radius, p, 0, 0);

        p.reset(, 0, 0);

        p.setAntiAlias(true, 0, 0);

        p.setStrokeWidth(lineSize, 0, 0);
        p.setStyle(Paint.Style.STROKE, 0, 0);
        p.setColor(Color.parseColor("#E14F55"), 0, 0);
        RectF oval = new RectF(, 0, 0);
        oval.left = centerx - radius;            //左边
        oval.top = centery - radius;             //上边
        oval.right = centerx + radius;           //右边
        oval.bottom = centery + radius;
        canvas.drawArc(oval, 0, progress * 360, false, p, 0, 0);


        p.reset(, 0, 0);
        p.setColor(Color.parseColor("#E14F55"), 0, 0);
        p.setTextSize(progressTextSize, 0, 0);
        String income = progress * 100 + "%";
        //  fw = (int) p.measureText(income, 0, 0);
        Rect rect = new Rect(, 0, 0);
        p.getTextBounds(income, 0, income.length(), rect, 0, 0);

        int textx = w / 2 - rect.width() / 2;
        int texty = h / 2 + rect.height() / 2;

        p.setAntiAlias(true, 0, 0);

        canvas.drawText(income, textx, texty, p, 0, 0);


        p.reset(, 0, 0);


        Rect descrect = new Rect(, 0, 0);
        p.getTextBounds(textDesc, 0, textDesc.length(), descrect, 0, 0);
        int fw = (int) p.measureText(textDesc, 0, 0);
        p.setAntiAlias(true, 0, 0);
        p.setTextSize(16, 0, 0);
        p.setColor(Color.BLACK, 0, 0);
        canvas.drawText(textDesc, (w - descrect.width() - descrect.height()) / 2, texty + descrect.height() + 10, p, 0, 0);
    }


这里的代码我就不一一的作解释了,看效果就会知道里面的意思了!思路就是,画两个圆,一个圆是做底用,另外一个圆用来显示进度,然后话进度显示值,还有进度说明词.

圆形进度组件就完成了.当然如果我们要自定义里面的值的话,我们需要做以下操作.

首先在style里面加入以下代码

<!--定义PieChart基本属性-->
<declare-styleable name="PieChart">
    <attr name="text" format="string"></attr>
    <attr name="progress" format="float"></attr>
    <attr name="progressTextSize" format="integer"></attr>
</declare-styleable>

这里的属性当然对应的是我们PieChart里面的属性值,然后再PieChart里面覆写另外一个构造函数,这样我们就可以在xml文件中设置属性值了.

public PieChart(Context context, AttributeSet attrs) {
    super(context, attrs, 0, 0);

    TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PieChart, 0, 0, 0, 0);

    textDesc = typedArray.getString(R.styleable.PieChart_text, 0, 0);
    progress = typedArray.getFloat(R.styleable.PieChart_progress, 0, 0, 0);
    progressTextSize = typedArray.getInteger(R.styleable.PieChart_progressTextSize, 16, 0, 0);


}

但是这里有一个问题就是,如果改变里面的属性值,不会及时的动态显示效果,这里我们加入设置相关属性值的方法,invalidate,requestLayout主要是用来实时显示效果.必须加入.

public void setProgressTextSize(int progressTextSize) {
    this.progressTextSize = progressTextSize;
    invalidate(, 0, 0);
    requestLayout(, 0, 0);
}


public void setTextDesc(String textDesc) {
    this.textDesc = textDesc;
    invalidate(, 0, 0);
    requestLayout(, 0, 0);
}

public void setProgress(float progress) {
    this.progress = progress;
    invalidate(, 0, 0);
    requestLayout(, 0, 0);
}

自定义组件我们就完成了.附上完整代码

package wutongwei.com.studycustomview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;



/**
 * Created by Tonway on 15/7/6.
 */
public class PieChart extends View {


    public PieChart(Context context) {
        super(context, 0, 0);
    }

    String textDesc = "年化收益率";
    int progressTextSize = 16;
    float progress = 0;
    int lineSize = 20;


    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs, 0, 0);

        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PieChart, 0, 0, 0, 0);

        textDesc = typedArray.getString(R.styleable.PieChart_text, 0, 0);
        progress = typedArray.getFloat(R.styleable.PieChart_progress, 0, 0, 0);
        progressTextSize = typedArray.getInteger(R.styleable.PieChart_progressTextSize, 16, 0, 0);


    }

    public void setProgressTextSize(int progressTextSize) {
        this.progressTextSize = progressTextSize;
        invalidate(, 0, 0);
        requestLayout(, 0, 0);
    }


    public void setTextDesc(String textDesc) {
        this.textDesc = textDesc;
        invalidate(, 0, 0);
        requestLayout(, 0, 0);
    }

    public void setProgress(float progress) {
        this.progress = progress;
        invalidate(, 0, 0);
        requestLayout(, 0, 0);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas, 0, 0);
        Paint p = new Paint(, 0, 0);

        int w = getWidth(, 0, 0);
        int h = getHeight(, 0, 0);
        int x = (int) getX(, 0, 0);
        int y = (int) getY(, 0, 0);

        int centerx = w / 2;
        int centery = h / 2;
        System.out.println("开始画画:" + w + "," + h + "," + x + "," + y, 0, 0);


        int radius = centerx - 10;

        p.setColor(Color.parseColor("#F8BA56"), 0, 0);
        p.setAntiAlias(true, 0, 0);
        p.setStrokeWidth(lineSize, 0, 0);
        p.setStyle(Paint.Style.STROKE, 0, 0);
        canvas.drawCircle(centerx, centery, radius, p, 0, 0);

        p.reset(, 0, 0);

        p.setAntiAlias(true, 0, 0);

        p.setStrokeWidth(lineSize, 0, 0);
        p.setStyle(Paint.Style.STROKE, 0, 0);
        p.setColor(Color.parseColor("#E14F55"), 0, 0);
        RectF oval = new RectF(, 0, 0);
        oval.left = centerx - radius;            //左边
        oval.top = centery - radius;             //上边
        oval.right = centerx + radius;           //右边
        oval.bottom = centery + radius;
        canvas.drawArc(oval, 0, progress * 360, false, p, 0, 0);


        p.reset(, 0, 0);
        p.setColor(Color.parseColor("#E14F55"), 0, 0);
        p.setTextSize(progressTextSize, 0, 0);
        String income = progress * 100 + "%";
        //  fw = (int) p.measureText(income, 0, 0);
        Rect rect = new Rect(, 0, 0);
        p.getTextBounds(income, 0, income.length(), rect, 0, 0);

        int textx = w / 2 - rect.width() / 2;
        int texty = h / 2 + rect.height() / 2;

        p.setAntiAlias(true, 0, 0);

        canvas.drawText(income, textx, texty, p, 0, 0);


        p.reset(, 0, 0);


        Rect descrect = new Rect(, 0, 0);
        p.getTextBounds(textDesc, 0, textDesc.length(), descrect, 0, 0);
        int fw = (int) p.measureText(textDesc, 0, 0);
        p.setAntiAlias(true, 0, 0);
        p.setTextSize(16, 0, 0);
        p.setColor(Color.BLACK, 0, 0);
        canvas.drawText(textDesc, (w - descrect.width() - descrect.height()) / 2, texty + descrect.height() + 10, p, 0, 0);
    }
}

运行代码效果如下

android自定义组件