Android可触摸圆形进度条,Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动...
Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动。package com.example.test;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MusicProgressBar extends View{
/**
* 画笔对象的引用
*/
private Paint paint;
/**
* 圆环的颜色
*/
private int roundColor;
/**
* 圆环进度的颜色
*/
private int roundProgressColor;
/**
* 圆环的宽度
*/
private float roundWidth;
/**
* 最大进度
*/
private int max;
/**
* 当前进度
*/
private int progress;
/**
* 中间进度百分比的字符串的颜色
*/
private int textColor;
/**
* 中间进度百分比的字符串的字体
*/
private float textSize;
/**
* 点的半径
*/
private float pointRadius;
/**
* 空心点的宽度
*/
private float pointWidth;
private Drawable mThumb, mThumbPress;
public MusicProgressBar(Context context) {
this(context, null);
}
public MusicProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MusicProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
paint = new Paint();
//TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar);
//获取自定义属性和默认值
roundColor =Color.RED;// mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.RED);
roundProgressColor =Color.GREEN;// mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.GREEN);
roundWidth =3;// mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 3);
textColor =Color.BLACK;// mTypedArray.getColor(R.styleable.RoundProgressBar_textColor, Color.GREEN);
textSize =8;// mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize, 15);
max =100;// mTypedArray.getInteger(R.styleable.RoundProgressBar_imageMax, 100);
pointRadius =3;// mTypedArray.getDimension(R.styleable.RoundProgressBar_pointRadius, 3);
pointWidth =2;// mTypedArray.getDimension(R.styleable.RoundProgressBar_pointWidth, 2);
// mTypedArray.recycle();
// 加载拖动图标
mThumb = getResources().getDrawable(R.drawable.ic_launcher);// 圆点图片
int thumbHalfheight = mThumb.getIntrinsicHeight() / 2;
int thumbHalfWidth = mThumb.getIntrinsicWidth() / 2;
mThumb.setBounds(-thumbHalfWidth, -thumbHalfheight, thumbHalfWidth, thumbHalfheight);
mThumbPress = getResources().getDrawable(R.drawable.ic_launcher);// 圆点图片
thumbHalfheight = mThumbPress.getIntrinsicHeight() / 2;
thumbHalfWidth = mThumbPress.getIntrinsicWidth() / 2;
mThumbPress.setBounds(-thumbHalfWidth, -thumbHalfheight, thumbHalfWidth, thumbHalfheight);
paddingOuterThumb = thumbHalfheight*2;
}
@Override
public void onDraw(Canvas canvas) {
/**
* 画最外层的大圆环
*/
paint.setColor(roundColor); //设置圆环的颜色
paint.setStyle(Paint.Style.STROKE); //设置空心
paint.setStrokeWidth(roundWidth); //设置圆环的宽度
paint.setAntiAlias(true); //消除锯齿
canvas.drawCircle(centerX, centerY, radius, paint); //画出圆环
/**
* 画文字
*/
paint.setStrokeWidth(0);
paint.setColor(textColor);
paint.setTextSize(textSize);
// paint.setTypeface(Typeface.DEFAULT); //设置字体
String textTime = getTimeText(progress);
float textWidth = paint.measureText(textTime); //测量字体宽度,我们需要根据字体的宽度设置在圆环中间
// canvas.drawText(textTime, centerX - textWidth / 2, centerY + textSize/2, paint);
/**
* 画圆弧 ,画圆环的进度
*/
paint.setStrokeWidth(roundWidth); //设置圆环的宽度
paint.setColor(roundProgressColor); //设置进度的颜色
RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius); //用于定义的圆弧的形状和大小的界限
paint.setStyle(Paint.Style.STROKE);
canvas.drawArc(oval, 270, 360 * progress / max, false, paint); //根据进度画圆弧
// 画圆上的两个点
paint.setStrokeWidth(pointWidth);
PointF startPoint = ChartUtil.calcArcEndPointXY(centerX, centerY, radius, 0, 270);
canvas.drawCircle(startPoint.x, startPoint.y, pointRadius, paint);
//paint.setStyle(Paint.Style.FILL_AND_STROKE);
PointF progressPoint = ChartUtil.calcArcEndPointXY(centerX, centerY, radius, 360 * progress / max, 270);
//canvas.drawCircle(progressPoint.x, progressPoint.y, pointRadius, paint);
// 画Thumb
canvas.save();
canvas.translate((float)(progressPoint.x+15*Math.sin(360 * progress / max*0.0174533f)), (float)(progressPoint.y-15*Math.cos(360 * progress / max*0.0174533f)));
canvas.rotate(360 * progress / max);
if (downOnArc) {
mThumbPress.draw(canvas);
} else {
mThumb.draw(canvas);
}
canvas.restore();
paint.setStrokeWidth(0);
paint.setColor(textColor);
paint.setTextSize(textSize);
// paint.setTypeface(Typeface.DEFAULT); //设置字体
// String textTime = getTimeText(progress);
// float textWidth = paint.measureText(textTime);
progress-=5;
canvas.rotate(360*(progress+5) / max, (float)(progressPoint.x+26f*Math.sin(360 * progress / max*0.0174533f)),(float)(progressPoint.y-26f*Math.cos(360 * progress / max*0.0174533f)));
canvas.drawText(textTime,(float)(progressPoint.x+26f*Math.sin(360 * progress / max*0.0174533f)),(float)(progressPoint.y-26f*Math.cos(360 * progress / max*0.0174533f)), paint);
canvas.rotate(-360*(progress+5) / max, progressPoint.x, progressPoint.y);
progress+=5;
}
private boolean downOnArc = false;
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (isTouchArc(x, y)) {
downOnArc = true;
updateArc(x, y);
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (downOnArc) {
updateArc(x, y);
return true;
}
break;
case MotionEvent.ACTION_UP:
downOnArc = false;
invalidate();
if (changeListener != null) {
changeListener.onProgressChangeEnd(max, progress);
}
break;
}
return super.onTouchEvent(event);
}
private int centerX, centerY;
private int radius;
private int paddingOuterThumb;
@Override
protected void onSizeChanged(int width, int height, int oldw, int oldh) {
centerX = width / 2;
centerY = height / 2;
int minCenter = Math.min(centerX, centerY);
radius = (int) (minCenter - roundWidth/2 - paddingOuterThumb); //圆环的半径
minValidateTouchArcRadius = (int) (radius - paddingOuterThumb*1.5f);
maxValidateTouchArcRadius = (int) (radius + paddingOuterThumb*1.5f);
super.onSizeChanged(width, height, oldw, oldh);
}
// 根据点的位置,更新进度
private void updateArc(int x, int y) {
int cx = x - getWidth() / 2;
int cy = y - getHeight() / 2;
// 计算角度,得出(-1->1)之间的数据,等同于(-180°->180°)
double angle = Math.atan2(cy, cx)/Math.PI;
// 将角度转换成(0->2)之间的值,然后加上90°的偏移量
angle = ((2 + angle)%2 + (90/180f))%2;
// 用(0->2)之间的角度值乘以总进度,等于当前进度
progress = (int) (angle * max/2);
if (changeListener != null) {
changeListener.onProgressChange(max, progress);
}
invalidate();
}
private int minValidateTouchArcRadius; // 最小有效点击半径
private int maxValidateTouchArcRadius; // 最大有效点击半径
// 判断是否按在圆边上
private boolean isTouchArc(int x, int y) {
double d = getTouchRadius(x, y);
if (d >= minValidateTouchArcRadius && d <= maxValidateTouchArcRadius) {
return true;
}
return false;
}
// 计算某点到圆点的距离
private double getTouchRadius(int x, int y) {
int cx = x - getWidth() / 2;
int cy = y - getHeight() / 2;
return Math.hypot(cx, cy);
}
private String getTimeText(int progress) {
int minute = progress / 60;
int second = progress % 60;
String result = (minute < 10 ? "0" : "") + minute + ":" + (second < 10 ? "0" : "") + second;
return result;
}
public synchronized int getMax() {
return max;
}
/**
* 设置进度的最大值
* @param max
*/
public synchronized void setMax(int max) {
if(max < 0){
throw new IllegalArgumentException("max not less than 0");
}
this.max = max;
}
/**
* 获取进度.需要同步
* @return
*/
public synchronized int getProgress() {
return progress;
}
/**
* 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步
* 刷新界面调用postInvalidate()能在非UI线程刷新
* @param progress
*/
public synchronized void setProgress(int progress) {
if(progress < 0){
throw new IllegalArgumentException("progress not less than 0");
}
if(progress > max){
progress = max;
}
if(progress <= max){
this.progress = progress;
postInvalidate();
}
}
public int getCricleColor() {
return roundColor;
}
public void setCricleColor(int cricleColor) {
this.roundColor = cricleColor;
}
public int getCricleProgressColor() {
return roundProgressColor;
}
public void setCricleProgressColor(int cricleProgressColor) {
this.roundProgressColor = cricleProgressColor;
}
public float getRoundWidth() {
return roundWidth;
}
public void setRoundWidth(float roundWidth) {
this.roundWidth = roundWidth;
}
public static class ChartUtil {
/**
* 依圆心坐标,半径,扇形角度,计算出扇形终射线与圆弧交叉点的xy坐标
* @param cirX
* @param cirY
* @param radius
* @param cirAngle
* @return
*/
public static PointF calcArcEndPointXY(float cirX, float cirY, float radius, float cirAngle){
float posX = 0.0f;
float posY = 0.0f;
//将角度转换为弧度
float arcAngle = (float) (Math.PI * cirAngle / 180.0);
if (cirAngle < 90)
{
posX = cirX + (float)(Math.cos(arcAngle)) * radius;
posY = cirY + (float)(Math.sin(arcAngle)) * radius;
}
else if (cirAngle == 90)
{
posX = cirX;
posY = cirY + radius;
}
else if (cirAngle > 90 && cirAngle < 180)
{
arcAngle = (float) (Math.PI * (180 - cirAngle) / 180.0);
posX = cirX - (float)(Math.cos(arcAngle)) * radius;
posY = cirY + (float)(Math.sin(arcAngle)) * radius;
}
else if (cirAngle == 180)
{
posX = cirX - radius;
posY = cirY;
}
else if (cirAngle > 180 && cirAngle < 270)
{
arcAngle = (float) (Math.PI * (cirAngle - 180) / 180.0);
posX = cirX - (float)(Math.cos(arcAngle)) * radius;
posY = cirY - (float)(Math.sin(arcAngle)) * radius;
}
else if (cirAngle == 270)
{
posX = cirX;
posY = cirY - radius;
}
else
{
arcAngle = (float) (Math.PI * (360 - cirAngle) / 180.0);
posX = cirX + (float)(Math.cos(arcAngle)) * radius;
posY = cirY - (float)(Math.sin(arcAngle)) * radius;
}
return new PointF(posX, posY);
}
public static PointF calcArcEndPointXY(float cirX, float cirY, float radius, float cirAngle, float orginAngle){
cirAngle = (orginAngle + cirAngle) % 360;
return calcArcEndPointXY(cirX, cirY, radius, cirAngle);
}
}
private OnProgressChangeListener changeListener;
public void setChangeListener(OnProgressChangeListener changeListener) {
this.changeListener = changeListener;
}
public interface OnProgressChangeListener {
void onProgressChange(int duration, int progress);
void onProgressChangeEnd(int duration, int progress);
}
}
Android可触摸圆形进度条,Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动...相关推荐
- android+无触摸操作,如何在Android中模拟触摸事件?
这是一个monkeyrunner脚本,用于将触摸和拖动操作发送到应用程序.我一直在使用它来测试我的应用程序可以处理快速重复的滑动手势. # This is a monkeyrunner jython ...
- android关闭触摸声音,如何在Android中关闭所有触摸声音 | MOS86
开箱即用,您的电话可能会为您所做的每件事发出令人讨厌的声音. 这些可能会使您发疯,这仅仅是因为您厌倦了噪音,或者可能是因为它打扰了周围的人. 值得庆幸的是,您可以禁用手机发出的哑音,仅在需要时才发出声 ...
- android关闭触摸声音,如何在Android中以编程方式禁用触摸时的振动和声音?
我正在使用ImageView的OnLongClickListener创建一个应用程序并打开alertdialog,并且还有ontouch缩放功能.但是当我长时间按压而不是振动时,可以在长按聆听器上关闭 ...
- Android 自定义View,自定义属性--自定义圆形进度条(整理)
很多的时候,系统自带的View满足不了我们的功能需求,那么我们就需要自定义View来满足我们的需求 自定义View时要先继承View,添加类的构造方法,重写父类View的一些方法,例如onDraw,为 ...
- Android自定义圆形下载进度条,Android自定义之圆形进度条
先来看看效果图,有图才有真相: Usage Android Studio 使用Gradle构建 dependencies { compile 'com.github.ws.circleprogress ...
- android触摸进度条,Android仿IOS ViewPager滑动进度条
最近做项目,碰到如下的需求:ViewPager分页,如果是6页(包括6页)就用圆点,如果是6页以上就用进度条来切换.前面一种交互方法最常见,用小圆点来表示当前选中的页面,这些小圆点称为导航点,很多Ap ...
- android 图片处理过程中添加进度条,『Android自定义View实战』给我一个图标,还你一个水波纹进度球...
前言 我们都知道,平时表现进度的方式有千千万万种(没有UI想不到的,只有你做不到的= =.),其中有一种就是水波纹进度球的形式,网上很多种实现都是直接采用纯色填充的方式,即水波纹都是纯颜色填充,效果看 ...
- android编程任务进度条,Android 进度条 ProgressBar - Android 入门教程
今天要学的是一个特定场合要用到的控件--进度条控件.进度条的作用不言而喻,而在实际使用中,通常会有两种类型的进度条:横向进度条和圆形进度条.当然,ProgressBar 也是支持这两种类型的,可以应对 ...
- android 签到 进度条,Android 七种进度条的样式
当一个应用在后台执行时,前台界面就不会有什么信息,这时用户根本不知道程序是否在执行.执行进度如何.应用程序是否遇到错误终止等,这时需要使用进度条来提示用户后台程序执行的进度.Android系统提供了两 ...
最新文章
- wordpress调用树形目录
- 听障人士的“有声桥梁”:百度智能云曦灵-AI手语平台发布
- [BZOJ4556][TJOI2016HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)
- 从C语言的角度重构数据结构系列(八)-数据结构堆知识超级丑数
- 京瓷2010复印a4内容不全_京瓷2010复印机,纸卡定影的故障
- excel导入mysql语句_求助:用SQL语句从Excel将数据导入到SQL数据库
- 如何在 SAP BTP 平台上重用另一个已经开发好的 service
- 取0-1中间任意数java_java – 找到一个整数n 0,其中包含以下三个条件
- DEV C++如何不需要通过建项目可以调试程序
- opencv不能读取MP4格式文件
- 二维数组按某个键值排序 FOR PHP
- python查看系统信息_Python脚本获取操作系统版本信息
- 软件dfmea_最全最专业解析!详解DFMEA新版六步法~fmea软件
- dos攻击工具如何使用?两款dos攻击工具介绍
- D4 数据分析实例:分析movielens电影数据+pandas核心数据结构
- 电商与ERP集成方案
- 连接局域网打印机用计算机名,如何连接局域网内共享的打印机
- java 415_@RequestBody接受参数报415错误
- uc通讯不成功php版本过高,UC通信失败怎么办
- CSAPP第四章家庭作业参考答案
热门文章
- AVOD:Aggregate View Object Detection跑通(官方README小补充)
- C#控制浏览器自动填充表单的代码
- 【JetPack+Retrofit+Rxjava】获取Bing每日一图并显示ViewModel+LiveData+DataBinding+MVVM 补充笔记
- RJ45电口引脚定义
- 论“取势、明道、优术”的趋势
- mcgscom口针脚定义_计算机串口(RS232)的针脚定义是什么?
- 对对碰-第11届蓝桥杯Scratch省赛真题第6题
- 23、Java——常见异常的原因和解决办法
- python 计算两个经纬度的距离_python 通过两个点的经纬度计算距离
- 易语言怎么写删除c盘文件夹,易语言删除文件目录的方法