这篇文章来学习基本的自定义组件,画图,自定义标签属性.这个学习例子我们模仿Swift中自定义组件的界面效果(http://www.wutongwei.com/front/infor_showone.tweb?id=109)
好的我们马上着手代码编写.
我们先来看下布局的界面效果
代码如下
<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); } }
运行代码效果如下