700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > android 环形时间显示_Android自定义波浪加载圆形进度条——(自定义控件 一)...

android 环形时间显示_Android自定义波浪加载圆形进度条——(自定义控件 一)...

时间:2019-04-01 21:46:54

相关推荐

android 环形时间显示_Android自定义波浪加载圆形进度条——(自定义控件 一)...

自定义控件—— 波浪形状圆形进度加载

时间管理的基础是精力管理,精力的高低、正负分影响到我们的效率

而时间是无法管理的,能够管理的只有自己,透过管理自己的习惯,管理自己的事件来达成对时间的管理。

而在每一天中,人生不丰于做多少事,而在于把重要的事情专注做、用心做,把它做到极致。

1、效果简阅

2、实现思路设计

3、初始化操作

private void init(Context context) {

//绘制圆形的 Paint

mCicrlPaint = new Paint();

mCicrlPaint.setAntiAlias(true);

mCicrlPaint.setColor(Color.BLUE);

//绘制进度的 Paint

mProgressPaint = new Paint();

mProgressPaint.setAntiAlias(true);

mProgressPaint.setColor(Color.RED);

//设置只绘制重叠的部分

mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

//绘制文字的 Paint

mTextPaint = new Paint();

mTextPaint.setAntiAlias(true);

mTextPaint.setColor(Color.WHITE);

mTextPaint.setTextSize(20);

//绘制进度的Path

mPath = new Path();

/**

* 手势识别监听

*/

final GestureDetector gestureDetector = new GestureDetector(listener);

/**

* 将触摸识别事件传递给 GestureDetector

*/

this.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

return gestureDetector.onTouchEvent(event);

}

});

this.setClickable(true);

//设置布局加载监听

this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

@Override

public void onGlobalLayout() {

//更新控件的大小

viewHeight = ProgressView.this.getHeight();

viewWidth = ProgressView.this.getWidth();

//创建 bitmap 与 canvas

bitmap = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);

mCanvas = new Canvas(bitmap);

/**

* 更新默认设置

*/

updateDefaulBuildValue();

}

});

}

GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {

/**

* 单击点击监听

* @param e

* @return

*/

@Override

public boolean onSingleTapConfirmed(MotionEvent e) {

System.out.println("sing click ");

if (clickListener != null) {

clickListener.onSingleClick(e);

return true;

}

return super.onSingleTapConfirmed(e);

}

/**

* 双击点击监听

* @param e

* @return

*/

@Override

public boolean onDoubleTap(MotionEvent e) {

if (clickListener != null) {

clickListener.onDoubleClick(e);

}

return super.onDoubleTap(e);

}

/**

* 常按事件监听

* @param e

*/

@Override

public void onLongPress(MotionEvent e) {

if (clickListener != null) {

clickListener.onLongPressClick(e);

}

super.onLongPress(e);

}

};

同时设置了点击事件的监听接口回调

/**

* 控件 点击事件监听 回调

*/

public interface OnWaveProgressClickListener {

/**

* 单击回调接口

* @param e

*/

public void onSingleClick(MotionEvent e);

/**

* 双击回调接口

* @param e

*/

public void onDoubleClick(MotionEvent e);

/**

* 找按回调接口

* @param e

*/

public void onLongPressClick(MotionEvent e);

}

private OnWaveProgressClickListener clickListener;

/**

* 设置控件的点击事件

*

* @param listener

*/

public void setWaveOnClickListener(OnWaveProgressClickListener listener) {

this.clickListener = listener;

}

4、测量

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

/**

* 绘制的为正方形进度条,测量比较较小的长度为圆形的直径长度

*/

int width;

int height;

width = Math.min(widthSize, heightSize);

height = Math.min(widthSize, heightSize);

setMeasuredDimension(width, height);

}

5、绘制

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//绘制整体圆形

mCanvas.drawCircle(viewWidth / 2, viewWidth / 2, viewWidth / 2, mCicrlPaint);

//绘制进度图形

mPath.reset();

//进度图形的高度 随着加载进度的改变

float y = (1 - (float) currentProgress / maxProgress) * viewHeight;

mPath.moveTo(viewWidth, y);

mPath.lineTo(viewWidth, viewHeight);

mPath.lineTo(0, viewHeight);

mPath.lineTo(0, y);

//

/**

* 计算振幅的比例

* 振幅 的大小 是随着进度的大小动态改变的

*/

int amplitude = (int) ((1 - (float) currentProgress / maxProgress) * mDefaulAmplitude);

if (currentProgress % 2 == 0) {

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

mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);

mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);

}

} else {

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

mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);

mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);

}

}

mPath.close();

mCanvas.drawPath(mPath, mProgressPaint);

//

//绘制 中间显示的百分比文字

String text = "" + (int) (((float) currentProgress / maxProgress) * 100);

//获取绘制文字的宽度

float textWidth = mTextPaint.measureText(text);

//获取绘制文字的高度

Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();

//Descent是baseline之下至字符最低处的距离

//Ascent是baseline之上至字符最高处的距离

//ascent + descent 就是测量文字的高度

float textHeight = fontMetrics.ascent + fontMetrics.descent;

//计算绘制中间显示进度文字的坐标

float textY = viewHeight / 2 - textHeight / 2;

float textX = viewWidth / 2 - textWidth / 2;

//绘制显示进度的文字

mCanvas.drawText(text, textX, textY, mTextPaint);

canvas.drawBitmap(bitmap, 0, 0, null);

}

绘制分析

5.1绘制圆形背景

5.2绘制进度

5.3绘制波浪曲线

曲线分析 一

曲线分析 二

曲线分析三

绘制:

/**

* 计算振幅的比例

* 振幅 的大小 是随着进度的大小动态改变的

*/

int amplitude = (int) ((1 - (float) currentProgress / maxProgress) * mDefaulAmplitude);

if (currentProgress % 2 == 0) {

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

mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);

mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);

}

} else {

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

mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);

mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);

}

}

效果

上面的图形中绘制了四组正反曲线,也就是说分别绘制了四个开口向上的曲线,四个开口向下的曲线,

这里采用的绘制思想是每一次都 绘制一个开口向上的曲线 和一个开口向下的曲线,然后形成一个完整的类似正弦曲线的线形,这里绘制了四次,也就是在FOR循环中循环了四次,具体的循环次数是不定的,依据控件的大小来动态设置

5.4绘制显示文本

//获取绘制文字的宽度

float textWidth = mTextPaint.measureText(text);

//获取绘制文字的高度

Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();

//Descent是baseline之下至字符最低处的距离

//Ascent是baseline之上至字符最高处的距离

//ascent + descent 就是测量文字的高度

float textHeight = fontMetrics.ascent + fontMetrics.descent;

//计算绘制中间显示进度文字的坐标

float textY = viewHeight / 2 - textHeight / 2;

float textX = viewWidth / 2 - textWidth / 2;

//绘制显示进度的文字

mCanvas.drawText(text, textX, textY, mTextPaint);

其中涉及到一些文本测量

6、完整源码

package com.animation.androidlongs.a360animationapplication.view;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.PorterDuff;

import android.graphics.PorterDuffXfermode;

import android.util.AttributeSet;

import android.view.GestureDetector;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewTreeObserver;

/**

* Created by androidlongs on 16/8/9.

*/

public class WaveProgressView extends View {

private Paint mCicrlPaint;

private Paint mProgressPaint;

private Paint mTextPaint;

private Canvas mCanvas;

private Path mPath;

private Bitmap bitmap;

public WaveProgressView(Context context) {

super(context);

init(context);

}

public WaveProgressView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

public WaveProgressView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(context);

}

private void init(Context context) {

//绘制圆形的 Paint

mCicrlPaint = new Paint();

mCicrlPaint.setAntiAlias(true);

mCicrlPaint.setColor(Color.BLUE);

//绘制进度的 Paint

mProgressPaint = new Paint();

mProgressPaint.setAntiAlias(true);

mProgressPaint.setColor(Color.RED);

//设置只绘制重叠的部分

mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

//绘制文字的 Paint

mTextPaint = new Paint();

mTextPaint.setAntiAlias(true);

mTextPaint.setColor(Color.WHITE);

mTextPaint.setTextSize(20);

//绘制进度的Path

mPath = new Path();

/**

* 手势识别监听

*/

final GestureDetector gestureDetector = new GestureDetector(listener);

/**

* 将触摸识别事件传递给 GestureDetector

*/

this.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

return gestureDetector.onTouchEvent(event);

}

});

this.setClickable(true);

//设置布局加载监听

this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

@Override

public void onGlobalLayout() {

//更新控件的大小

viewHeight = WaveProgressView.this.getHeight();

viewWidth = WaveProgressView.this.getWidth();

//创建 bitmap 与 canvas

bitmap = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);

mCanvas = new Canvas(bitmap);

/**

* 更新默认设置

*/

updateDefaulBuildValue();

}

});

}

GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {

/**

* 单击点击监听

* @param e

* @return

*/

@Override

public boolean onSingleTapConfirmed(MotionEvent e) {

System.out.println("sing click ");

if (clickListener != null) {

clickListener.onSingleClick(e);

return true;

}

return super.onSingleTapConfirmed(e);

}

/**

* 双击点击监听

* @param e

* @return

*/

@Override

public boolean onDoubleTap(MotionEvent e) {

if (clickListener != null) {

clickListener.onDoubleClick(e);

}

return super.onDoubleTap(e);

}

/**

* 常按事件监听

* @param e

*/

@Override

public void onLongPress(MotionEvent e) {

if (clickListener != null) {

clickListener.onLongPressClick(e);

}

super.onLongPress(e);

}

};

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

/**

* 绘制的为正方形进度条,测量比较较小的长度为圆形的直径长度

*/

int width;

int height;

width = Math.min(widthSize, heightSize);

height = Math.min(widthSize, heightSize);

setMeasuredDimension(width, height);

}

/**

* 默认控件的 宽 高

* 默认的 当前的进度 总的进度

*/

public int viewWidth = 150;

public int viewHeight = 150;

public int currentProgress = 0;

public int maxProgress = 100;

/**

* 计算振幅大小 所用的比例数 默认为10

*/

private int mAplitudeCunt = 10;

/**

* 默认振幅的大小 为控件高度的 1/10

*/

private int mDefaulAmplitude = viewHeight / mAplitudeCunt;

/**

* 计算周期长度使用的比例数 默认为8

*/

private int mPriodicCount = 8;

/**

* 曲线默认的周期长度

*/

private int mDefaulPriodic = viewHeight / mPriodicCount;

/**

* 曲线的绘制次数

*/

private int mquadLineDrawCount = (int) ((float) viewWidth / mDefaulPriodic);

/**

* 更新默认的设置

*/

private void updateDefaulBuildValue() {

if (viewHeight < 400) {

mPriodicCount = 8;

mAplitudeCunt = 10;

} else if (viewHeight < 600 && viewHeight >= 400) {

mPriodicCount = 14;

mAplitudeCunt = 16;

} else if (viewHeight < 1000 && viewHeight >= 600) {

mPriodicCount = 20;

mAplitudeCunt = 20;

} else if (viewHeight < 1400 && viewHeight >= 100) {

mAplitudeCunt = 24;

mPriodicCount = 26;

} else {

mPriodicCount = 30;

mAplitudeCunt = 30;

}

/**

* 默认振幅的大小 为控件高度的 1/10

*/

mDefaulAmplitude = viewHeight / mAplitudeCunt;

/**

* 曲线默认的周期长度

*/

mDefaulPriodic = viewHeight / 8;

/**

* 曲线的绘制次数

*/

mquadLineDrawCount = (int) ((float) viewWidth / mDefaulPriodic);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//绘制整体圆形

mCanvas.drawCircle(viewWidth / 2, viewWidth / 2, viewWidth / 2, mCicrlPaint);

//绘制进度图形

mPath.reset();

//进度图形的高度 随着加载进度的改变

float y = (1 - (float) currentProgress / maxProgress) * viewHeight;

mPath.moveTo(viewWidth, y);

mPath.lineTo(viewWidth, viewHeight);

mPath.lineTo(0, viewHeight);

mPath.lineTo(0, y);

//

/**

* 计算振幅的比例

* 振幅 的大小 是随着进度的大小动态改变的

*/

int amplitude = (int) ((1 - (float) currentProgress / maxProgress) * mDefaulAmplitude);

if (currentProgress % 2 == 0) {

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

mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);

mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);

}

} else {

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

mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);

mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);

}

}

mPath.close();

mCanvas.drawPath(mPath, mProgressPaint);

//

//绘制 中间显示的百分比文字

String text = "" + (int) (((float) currentProgress / maxProgress) * 100);

//获取绘制文字的宽度

float textWidth = mTextPaint.measureText(text);

//获取绘制文字的高度

Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();

//Descent是baseline之下至字符最低处的距离

//Ascent是baseline之上至字符最高处的距离

//ascent + descent 就是测量文字的高度

float textHeight = fontMetrics.ascent + fontMetrics.descent;

//计算绘制中间显示进度文字的坐标

float textY = viewHeight / 2 - textHeight / 2;

float textX = viewWidth / 2 - textWidth / 2;

//绘制显示进度的文字

mCanvas.drawText(text, textX, textY, mTextPaint);

canvas.drawBitmap(bitmap, 0, 0, null);

}

/**

* 控件 点击事件监听 回调

*/

public interface OnWaveProgressClickListener {

/**

* 单击回调接口

*

* @param e

*/

public void onSingleClick(MotionEvent e);

/**

* 双击回调接口

*

* @param e

*/

public void onDoubleClick(MotionEvent e);

/**

* 找按回调接口

*

* @param e

*/

public void onLongPressClick(MotionEvent e);

}

private OnWaveProgressClickListener clickListener;

/**

* 控件 加载进度回调接口

*/

public interface OnWaveProgressListener {

public void onProgresUpdate(int progress);

public void onFinish();

}

private OnWaveProgressListener progressListener;

/**

* 设置更新当前进度

*

* @param progress

*/

public void updateProgress(int progress) {

if (progress <= 0) {

progress = 0;

} else if (progress > this.maxProgress) {

progress = maxProgress;

}

this.currentProgress = progress;

//进度更新接口回调

if (progressListener != null) {

progressListener.onProgresUpdate(currentProgress);

}

if (progress == maxProgress) {

if (progressListener != null) {

progressListener.onFinish();

}

}

//重绘

invalidate();

}

/**

* 设置最大进度

*

* @param max

*/

public void setMaxProgress(int max) {

if (max <= 0) {

max = 100;

}

this.setMaxProgress(max);

}

/**

* 设置控件的点击事件

*

* @param listener

*/

public void setWaveOnClickListener(OnWaveProgressClickListener listener) {

this.clickListener = listener;

}

/**

* 加载进度监听设置

*

* @param listener

*/

public void setWaveOnProgressListener(OnWaveProgressListener listener) {

this.progressListener = listener;

}

}

7、Activity中的使用

package com.animation.androidlongs.a360animationapplication;

import android.content.Intent;

import android.os.Handler;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.MotionEvent;

import com.animation.androidlongs.a360animationapplication.view.WaveProgressView;

public class MainActivity extends AppCompatActivity {

private WaveProgressView customWaveProgressView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Intent intent = new Intent(MainActivity.this, FloatViewService.class);

//startService(intent);

customWaveProgressView = (WaveProgressView) findViewById(R.id.progress);

handler.postDelayed(runnable,2000);

//设置点击事件监听

customWaveProgressView.setWaveOnClickListener(new WaveProgressView.OnWaveProgressClickListener() {

@Override

public void onSingleClick(MotionEvent e) {

System.out.println("onSingleClick");

}

@Override

public void onDoubleClick(MotionEvent e) {

System.out.println("onDoubleClick");

}

@Override

public void onLongPressClick(MotionEvent e) {

System.out.println("onLongPressClick");

}

});

//设置进度更新监听

customWaveProgressView.setWaveOnProgressListener(new WaveProgressView.OnWaveProgressListener() {

@Override

public void onProgresUpdate(int progress) {

}

@Override

public void onFinish() {

}

});

}

private Handler handler = new Handler();

private Runnable runnable = new Runnable() {

@Override

public void run() {

currentNum++;

customWaveProgressView.updateProgress(currentNum);

if (currentNum

handler.postDelayed(runnable,200);

}else {

handler.removeCallbacks(runnable);

currentNum = 0;

}

}

};

private int maxNum = 100;

private int currentNum =0;

}

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