【移動應用開發(fā)技術】怎么在Android中自定義View實現(xiàn)球體進度球_第1頁
【移動應用開發(fā)技術】怎么在Android中自定義View實現(xiàn)球體進度球_第2頁
【移動應用開發(fā)技術】怎么在Android中自定義View實現(xiàn)球體進度球_第3頁
【移動應用開發(fā)技術】怎么在Android中自定義View實現(xiàn)球體進度球_第4頁
【移動應用開發(fā)技術】怎么在Android中自定義View實現(xiàn)球體進度球_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

【移動應用開發(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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論