700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > android 曲线进度条 Android自定义View——使用贝塞尔曲线实现流量进度条

android 曲线进度条 Android自定义View——使用贝塞尔曲线实现流量进度条

时间:2023-09-03 21:59:58

相关推荐

android 曲线进度条 Android自定义View——使用贝塞尔曲线实现流量进度条

第一次写带图片的博客,多少还是有点紧张,效果不好,请将就着看,前面的图是今天要写的控件的效果图,元素不多,分别是一个按钮和一个自定义的控件。

在此以前,我看过许多的书,比如《Android群英传》、《第一行代码》等,也看了很多大神的博客,但是即便是这样,当我看到这么多代码的时候,一直都没有真正的动手去敲过这些代码,以至于我总是觉得自定义View是一个多么高深莫测的技术,我们这些小白是难以触及的,但是当昨晚看了一篇鸡汤之后,觉得人还是要学会专注,要耐得住寂寞,要沉得住气。所以在未来的几天,我也会持续的更新自己的博客,希望能够得到大家的监督,也希望能够一起成长。

一般来说,不到迫不得已,还是不要去自定义自己的控件,毕竟现在Android API已经给我提供了功能这么强大的控件了,而且你也能够发现,就算是这么强大的谷歌,很多控件也还是有自己的bug,更何况我们自己写的控件,当然了,通过自定义控件,来加深我们对Android系统的控件的了解,这也是进阶的一个好方法。好了,废话我先说到这里,下面开始今天的主题。

新建一个Class文件,命名为MyLineView,让它继承View,实现它的三个构造函数,紧接着初始化一些画笔、Path,圆等数据。代码如下:

1.定义变量

private Paint mPaint, mPaint2;

private Path mPath = new Path();

protected int mViewWidth, mViewHeight;

protected int mWidth, mHeight;

private float r, rArc, x;

private float percent = 0.5f;

private RectF rectF;

private PointF mPointF = new PointF(0, 0);

在构造函数里面初始化数据

public MyLineView(Context context, AttributeSet attrs) {

super(context, attrs);

mPaint = new Paint();

mPaint.setColor(Color.BLACK);

mPaint.setStrokeWidth(3);

mPaint.setStyle(Paint.Style.STROKE);

mPaint.setTextSize(100);

mPaint2 = new Paint();

mPaint2.setColor(Color.CYAN);

mPaint2.setStrokeWidth(8);

mPaint2.setStyle(Paint.Style.FILL);

}

准备工作已经做好了,紧接着我们复写View的一个onSizeChanged()方法,故名思议,就是当控件的大小发生改变的时候调用。我们在这里对变量进行赋值,代码如下:

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

/**控件的高宽*/

mViewWidth = w;

mViewHeight = h;

/**与屏幕左边的距离和距离右边的距离*/

mWidth = mViewWidth - getPaddingLeft() - getPaddingRight();

mHeight = mViewHeight - getPaddingTop() - getPaddingBottom();

/**定义半径*/

r = Math.min(mWidth, mHeight) * 0.4f;

rectF = new RectF(-r, -r, r, r);

}

好了,这个时候的变量已经拥有值了,那可以开始写最重要的操作了,开始写onDraw();

@Override

protected void onDraw(Canvas canvas) {

// super.onDraw(canvas);

/** * 画曲线和外围的圆 */

canvas.translate(mViewWidth / 2, mViewHeight / 2);

canvas.drawCircle(0, 0, r, mPaint);

rArc = r * (1 - 2 * percent);

double angle = Math.acos((double) rArc / r);

x = r * (float) Math.sin(angle);

mPath.addArc(rectF, 90 - (float) Math.toDegrees(angle),

(float) Math.toDegrees(angle) * 2);

mPath.moveTo(-x, rArc);

mPath.rQuadTo(x / 2, -r / 8, x, 0);

mPath.rQuadTo(x / 2, r / 8, x, 0);

canvas.drawPath(mPath, mPaint2);

mPath.rewind();

/** * 画文字 */

NumberFormat numberFormat = NumberFormat.getPercentInstance();

numberFormat.setMinimumFractionDigits(1);

textCenter(new String[] { numberFormat.format(percent) }, mPaint,

canvas, mPointF, Paint.Align.CENTER);

}

文字的处理:

/** * 多行文本居中、居右、居左 * *@param strings * 文本字符串列表 *@param paint * 画笔 *@param canvas * 画布 *@param point * 点的坐标 *@param align * 居中、居右、居左 */

protected void textCenter(String[] strings, Paint paint, Canvas canvas,

PointF point, Paint.Align align) {

paint.setTextAlign(align);

Paint.FontMetrics fontMetrics = paint.getFontMetrics();

float top = fontMetrics.top;

float bottom = fontMetrics.bottom;

int length = strings.length;

float total = (length - 1) * (-top + bottom)

+ (-fontMetrics.ascent + fontMetrics.descent);

float offset = total / 2 - bottom;

for (int i = 0; i < length; i++) {

float yAxis = -(length - i - 1) * (-top + bottom) + offset;

canvas.drawText(strings[i], point.x, point.y + yAxis, paint);

}

}

好了,截止目前已经把控件写好了,但是作为一个控件,数据不可能固定不变,所以向外暴露一个方法,用于改变进度的大小;

public void setProgress(float percent) {

if (percent != 0) {

this.percent = percent;

} else {

this.percent = 0;

}

/**重绘*/

invalidate();

}

好了全部流程都在这里了,最后再贴上全部的代码;

package com.example.view.weight;

import java.text.NumberFormat;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.PointF;

import android.graphics.RectF;

import android.util.AttributeSet;

import android.view.View;

/** * 贝塞尔曲线 * *@author cheng * */

public class MyLineView extends View {

private Paint mPaint, mPaint2;

private Path mPath = new Path();

protected int mViewWidth, mViewHeight;

protected int mWidth, mHeight;

private float r, rArc, x;

private float percent = 0.5f;

private RectF rectF;

private PointF mPointF = new PointF(0, 0);

public MyLineView(Context context) {

this(context, null);

}

public MyLineView(Context context, AttributeSet attrs) {

super(context, attrs);

mPaint = new Paint();

mPaint.setColor(Color.BLACK);

mPaint.setStrokeWidth(3);

mPaint.setStyle(Paint.Style.STROKE);

mPaint.setTextSize(100);

mPaint2 = new Paint();

mPaint2.setColor(Color.CYAN);

mPaint2.setStrokeWidth(8);

mPaint2.setStyle(Paint.Style.FILL);

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

mViewWidth = w;

mViewHeight = h;

mWidth = mViewWidth - getPaddingLeft() - getPaddingRight();

mHeight = mViewHeight - getPaddingTop() - getPaddingBottom();

r = Math.min(mWidth, mHeight) * 0.4f;

rectF = new RectF(-r, -r, r, r);

}

@Override

protected void onDraw(Canvas canvas) {

// super.onDraw(canvas);

/** * 画曲线和外围的圆 */

canvas.translate(mViewWidth / 2, mViewHeight / 2);

canvas.drawCircle(0, 0, r, mPaint);

rArc = r * (1 - 2 * percent);

double angle = Math.acos((double) rArc / r);

x = r * (float) Math.sin(angle);

mPath.addArc(rectF, 90 - (float) Math.toDegrees(angle),

(float) Math.toDegrees(angle) * 2);

mPath.moveTo(-x, rArc);

mPath.rQuadTo(x / 2, -r / 8, x, 0);

mPath.rQuadTo(x / 2, r / 8, x, 0);

canvas.drawPath(mPath, mPaint2);

mPath.rewind();

/** * 画文字 */

NumberFormat numberFormat = NumberFormat.getPercentInstance();

numberFormat.setMinimumFractionDigits(1);

textCenter(new String[] { numberFormat.format(percent) }, mPaint,

canvas, mPointF, Paint.Align.CENTER);

}

/** * 多行文本居中、居右、居左 * *@param strings * 文本字符串列表 *@param paint * 画笔 *@param canvas * 画布 *@param point * 点的坐标 *@param align * 居中、居右、居左 */

protected void textCenter(String[] strings, Paint paint, Canvas canvas,

PointF point, Paint.Align align) {

paint.setTextAlign(align);

Paint.FontMetrics fontMetrics = paint.getFontMetrics();

float top = fontMetrics.top;

float bottom = fontMetrics.bottom;

int length = strings.length;

float total = (length - 1) * (-top + bottom)

+ (-fontMetrics.ascent + fontMetrics.descent);

float offset = total / 2 - bottom;

for (int i = 0; i < length; i++) {

float yAxis = -(length - i - 1) * (-top + bottom) + offset;

canvas.drawText(strings[i], point.x, point.y + yAxis, paint);

}

}

public void setProgress(float percent) {

if (percent != 0) {

this.percent = percent;

} else {

this.percent = 0;

}

invalidate();

}

}

布局里面的代码:

android:id="@+id/view_line"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:gravity="center" />

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。