版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
【移動應用開發(fā)技術】怎么在Android中自定義View實現(xiàn)球體進度球
這篇文章給大家介紹怎么在Android中自定義View實現(xiàn)球體進度球,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。1、定義BallProgress,BallProgress繼承View,重寫onDraw()方法,用于實現(xiàn)進度球的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)
{//設置進度,通過進度的大小實現(xiàn)裁剪的大小
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);
}
//發(fā)消息
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毫秒發(fā)送一次消息,對進度球進度進行更新。
}
}
}).start();
}
}上面代碼在inAction()中開一個線程,每隔100毫秒發(fā)送消息,在handler中處理更新,在handler使用中并沒有直接重寫hanldeMessage方法,而是傳入Handler.Callback并在callback中實現(xiàn)handleMessage方法,這樣可以防止內存泄漏。實際應用中,可以是跟業(yè)務相關的具體進度??偨Y自定義進度球,用的是繼承view,并且通過自定義畫筆,重寫onDraw()方法來實現(xiàn),一般自定義view都會重寫onDraw()方法,一般進度條都是ClipDrawable來實現(xiàn)的。源碼地址:進度球代碼帶波浪的進度球上面已經(jīng)實現(xiàn)了簡單的進度球,但是效果不是很好,根據(jù)評論區(qū)中的提議加上動畫和貝塞爾曲線波紋實現(xiàn)了下面的效果,只取了進度處于某一固定進度的動畫效果如圖:準備知識二階貝塞爾曲線貝塞爾曲線是用一系列點來控制曲線狀態(tài)的,將這些點簡單分為兩類:二階貝塞爾曲線的路徑由給定點P0、P1、P2的函數(shù)B(t)函數(shù)方程如下:二階曲線由兩個數(shù)據(jù)點(P0和P2),一個控制點(P1)來描述曲線狀態(tài),大致如下:android中自帶實現(xiàn)二階貝塞爾曲線的api,在Path類中的函數(shù)quadTo。public
void
quadTo
(float
x1,
float
y1,
float
x2,
float
y2)其中(x1,y1)是上圖中控制點p1的坐標,(x2,y2)是上圖中數(shù)據(jù)點結束位置p2的坐標,數(shù)據(jù)點p0的默認坐標是(0,0),也可以用函數(shù)moveTo(x,y)來改變p0坐標。要實現(xiàn)上面進度球進度的波動效果,就要將兩個貝塞爾曲線結合起來,并且動態(tài)的改變兩個貝塞爾曲線的數(shù)據(jù)點和控制點,這樣就會使用戶感覺到波動的效果。實現(xiàn)/**
*
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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 合理利用網(wǎng)絡說課稿分鐘
- 碧桂園物業(yè)管家述職報告
- 教育器材租賃合同模板
- 胸腰椎骨折的診斷與治療
- 溫室大棚灌溉系統(tǒng)安裝協(xié)議
- 新能源項目密封條模板
- 外賣公司墻布施工合同協(xié)議
- 城市住宅樓隔音改造合同
- 科研機構辦公設備招投標書
- 城市有軌電車塔吊租賃合同
- GB/T 6451-2023油浸式電力變壓器技術參數(shù)和要求
- 六年級英語學困生幫扶記錄
- LED屏施工方案(技術方案)
- 統(tǒng)計學專業(yè)大學生職業(yè)生涯規(guī)劃書
- 邊坡防護作用與防護類型全解課件
- 項目收費站機電工程(三大系統(tǒng))設備基本培訓資料
- 非飽和土力學03-吸力與SWCC課件
- 難治性高血壓-課件
- 混凝土攪拌站租賃合同范本(4篇)
- 成人無脈性心跳呼吸驟停搶救流程演示文稿
- 煙花爆竹經(jīng)營單位主要負責人安全培訓
評論
0/150
提交評論