【移动应用开发技术】怎么在Android中自定义View实现球体进度球_第1页
【移动应用开发技术】怎么在Android中自定义View实现球体进度球_第2页
【移动应用开发技术】怎么在Android中自定义View实现球体进度球_第3页
【移动应用开发技术】怎么在Android中自定义View实现球体进度球_第4页
【移动应用开发技术】怎么在Android中自定义View实现球体进度球_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】怎么在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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论