版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】怎么在Android中自定义View实现球体进度球
这篇文章给大家介绍怎么在Android中自定义View实现球体进度球,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1、定义BallProgress,BallProgress继承View,重写onDraw()方法,用于实现进度球的view。public
class
BallProgress
extends
View
{
private
float
mProgress
=
0.0f;
//取值位
0
-
1.0
private
boolean
selected
=
true;
public
BallProgress(Context
context)
{
super(context);
}
public
BallProgress(Context
context,
@Nullable
AttributeSet
attrs)
{
super(context,
attrs);
}
public
BallProgress(Context
context,
@Nullable
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
init();
}
private
void
init()
{
mProgressPaint
=
new
Paint();//初始化,定义画笔。
mProgressPaint.setAntiAlias(true);//设置抗锯齿
}
public
float
getProgress()
{
return
mProgress;
}
public
void
setProgress(float
progress)
{//设置进度,通过进度的大小实现裁剪的大小
mProgress
=
progress;
invalidate();
}
private
Paint
mProgressPaint;
@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
Bitmap
dst
=
getRectangleBitmap();//获取bitmap
setLayerType(LAYER_TYPE_HARDWARE,
null);
//开启硬件离屏缓存
canvas.drawBitmap(dst,
0,
0,
mProgressPaint);
}
private
Bitmap
getRectangleBitmap()
{
int
width
=
getWidth();
int
height
=
getHeight();
Bitmap
dstBitmap
=
Bitmap.createBitmap(width,
height,
Bitmap.Config.ARGB_8888);
ClipDrawable
clipDrawable
=
null;
clipDrawable
=
(ClipDrawable)
getContext().getResources().getDrawable(R.drawable.bottom_top_clip_single_color);//获取球形的背景图片,用于裁剪,就是上面看到的进度球中的图片
clipDrawable.setBounds(new
Rect(0,
0,
width,
height));//设置边界
clipDrawable.setLevel((int)
(10000
*
mProgress));//设置进度,
Canvas
canvas
=
new
Canvas(dstBitmap);//设置画布
clipDrawable.draw(canvas);//绘制
return
dstBitmap;//将bitmap返回
}
}有了自定义的BallProgress,就可以在布局中使用了,定义的xml文件如下:<?xml
version="1.0"
encoding="utf-8"?>
<RelativeLayout
xmlns:android="/apk/res/android"
xmlns:tools="/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.admin.floatprogressbar.BallProgress
android:id="@+id/progress"
android:layout_width="@dimen/progress_size"
android:layout_height="@dimen/progress_size"
android:layout_centerInParent="true"
/>
<ImageView
android:layout_width="@dimen/progress_size"
android:layout_height="@dimen/progress_size"
android:layout_centerInParent="true"
android:background="@drawable/main_tab_un_select_bg"
/>
</RelativeLayout>上面布局中的ImageView是悬浮球的边界。在MainActivity中来定时的改变进度球的大小。代码如下:public
class
MainActivity
extends
AppCompatActivity
{
private
final
int
PROGRESS_MESSAGE
=
0;
private
float
progress
=
0.0f;
private
BallProgress
mBallProgress;
private
Handler
mHandler
=
new
Handler(new
Handler.Callback()
{
@Override
public
boolean
handleMessage(Message
msg)
{
switch
(msg.what)
{
case
PROGRESS_MESSAGE:
progress
=
(progress
>
0.9f)
?
0.9f
:
progress;
mBallProgress.setProgress(progress);//接收消息,改变进度球的进度
break;
}
return
true;
}
});
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initAction();
}
private
void
initView()
{
mBallProgress
=
findViewById(R.gress);
}
//发消息
private
void
initAction()
{
new
Thread(new
Runnable()
{
@Override
public
void
run()
{
while
(true)
{
progress
+=
0.02f;
try
{
Thread.sleep(100);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
mHandler.sendEmptyMessage(PROGRESS_MESSAGE);//每隔100毫秒发送一次消息,对进度球进度进行更新。
}
}
}).start();
}
}上面代码在inAction()中开一个线程,每隔100毫秒发送消息,在handler中处理更新,在handler使用中并没有直接重写hanldeMessage方法,而是传入Handler.Callback并在callback中实现handleMessage方法,这样可以防止内存泄漏。实际应用中,可以是跟业务相关的具体进度。总结自定义进度球,用的是继承view,并且通过自定义画笔,重写onDraw()方法来实现,一般自定义view都会重写onDraw()方法,一般进度条都是ClipDrawable来实现的。源码地址:进度球代码带波浪的进度球上面已经实现了简单的进度球,但是效果不是很好,根据评论区中的提议加上动画和贝塞尔曲线波纹实现了下面的效果,只取了进度处于某一固定进度的动画效果如图:准备知识二阶贝塞尔曲线贝塞尔曲线是用一系列点来控制曲线状态的,将这些点简单分为两类:二阶贝塞尔曲线的路径由给定点P0、P1、P2的函数B(t)函数方程如下:二阶曲线由两个数据点(P0和P2),一个控制点(P1)来描述曲线状态,大致如下:android中自带实现二阶贝塞尔曲线的api,在Path类中的函数quadTo。public
void
quadTo
(float
x1,
float
y1,
float
x2,
float
y2)其中(x1,y1)是上图中控制点p1的坐标,(x2,y2)是上图中数据点结束位置p2的坐标,数据点p0的默认坐标是(0,0),也可以用函数moveTo(x,y)来改变p0坐标。要实现上面进度球进度的波动效果,就要将两个贝塞尔曲线结合起来,并且动态的改变两个贝塞尔曲线的数据点和控制点,这样就会使用户感觉到波动的效果。实现/**
*
Created
time
17:24.
*
*
@author
huhanjun
*
@since
2019/1/2
*/
public
class
BezierFloatView
extends
View
{
private
double
rArc=0;
private
double
percent=0;
public
BezierFloatView(Context
context)
{
super(context);
}
public
BezierFloatView(Context
context,
@Nullable
AttributeSet
attrs)
{
super(context,
attrs);
initPaint();
initAnimator();
}
private
RectF
rectF;
private
int
mWidth,
mHeight;//画布的宽带和高度
private
float
cycleWidth,
cycleHeight
=
30f;//周期的宽度和高度
private
Path
pathRipple;//画的路径
private
Paint
paintRipple;//画笔
private
float
moveSet
=
0;//移动的值
private
ValueAnimator
animator;//动画
private
boolean
isStart
=
false;
/**
*
初始化动画
*/
private
void
initAnimator()
{
animator
=
ValueAnimator.ofFloat(0,
mWidth);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setDuration(800);
animator.setInterpolator(new
LinearInterpolator());
animator.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener()
{
@Override
public
void
onAnimationUpdate(ValueAnimator
valueAnimator)
{
percent=valueAnimator.getAnimatedFraction();
moveSet
=
valueAnimator.getAnimatedFraction()
*
mWidth;
invalidate();
}
});
}
/**
*
初始化画的路径
*/
private
void
initPath()
{
rArc
=
mWidth*(1-2*percent);
double
angle=
Math.acos(rArc/mWidth);
pathRipple
=
new
Path();
pathRipple.moveTo(-6
*
cycleWidth
+
moveSet,
0);
pathRipple.quadTo(-5
*
cycleWidth
+
moveSet,
cycleHeight,
-4
*
cycleWidth
+
moveSet,
0);
pathRipple.quadTo(-3
*
cycleWidth
+
moveSet,
-cycleHeight,
-2
*
cycleWidth
+
moveSet,
0);
pathRipple.quadTo(-cycleWidth
+
moveSet,
cycleHeight,
moveSet,
0);
pathRipple.quadTo(cycleWidth
+
moveSet,
-cycleHeight,
2
*
cycleWidth
+
moveSet,
0);
pathRipple.addArc(rectF,0,180);
pathRipple.close();
pathRipple.setFillType(Path.FillType.WINDING);
}
/**
*
初始化画笔
*/
private
void
initPaint()
{
paintRipple
=
new
Paint();
paintRipple.setStrokeWidth(2);
paintRipple.setStyle(Paint.Style.FILL);
paintRipple.setColor(Color.BLUE);
paintRipple.setAntiAlias(true);
}
/**
*
画波纹
*
*
@param
canvas
*/
private
void
drawRipple(Canvas
canvas)
{
initPath();
canvas.drawPath(pathRipple,
paintRipple);
}
@Override
protected
void
onSizeChanged(int
w,
int
h,
int
oldw,
int
oldh)
{
super.onSizeCha
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 农药试剂采购合同模板
- 冶炼项目epc合同范本
- 与 签订施工合同模板
- 文化的内涵与功能 学案 高中政治统编版必修四哲学与文化
- it服务类合同模板
- 中医馆施工合同协议书
- 外包服务合同模板模板
- 会议服务合同模板模板
- bot项目融资合同模板
- 主播劳动合同模板
- 七年级数学上丰富的图形世界单元测试题有答案
- 城镇土地使用税 房产税税源明细表
- 低碳经济路线图(课堂PPT)
- 宜宾大地坡地块投资分析报告
- 转化医学研究及发展分享
- 挡墙总结报告(共6页)
- 八年级生物下第1节 花的结构和类型 导学案济南版
- 海鼎_HDPOS4操作手册v1.0
- 中国人民解放军计算机信息系统安全保密规定
- 发动机盖铰链的设计开发
- 部编人教版小学二年级数学上学期看图列式计算家庭专项练习完美版
评论
0/150
提交评论