版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么自定義雙向進(jìn)度條
本篇文章給大家分享的是有關(guān)Android中怎么自定義雙向進(jìn)度條,在下覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著在下一起來看看吧。注釋基本上就把原理說明了一下。package
util;
import
android.content.Context;
import
android.graphics.Canvas;
import
android.graphics.Color;
import
android.graphics.Paint;
import
android.graphics.drawable.Drawable;
import
android.support.v4.content.ContextCompat;
import
android.util.AttributeSet;
import
android.util.Log;
import
android.view.MotionEvent;
import
android.view.View;
import
com.example.qzd.utildemo.R;
import
java.math.BigDecimal;
/**
*
雙向滑塊的進(jìn)度條(區(qū)域選擇)
*/
public
class
SeekRangeBar
extends
View
{
private
Context
_context;
private
static
final
int
CLICK_ON_LOW
=
1;
//手指在前滑塊上滑動
private
static
final
int
CLICK_ON_HIGH
=
2;
//手指在后滑塊上滑動
private
static
final
int
CLICK_IN_LOW_AREA
=
3;
//手指點(diǎn)擊離前滑塊近
private
static
final
int
CLICK_IN_HIGH_AREA
=
4;
//手指點(diǎn)擊離后滑塊近
private
static
final
int
CLICK_OUT_AREA
=
5;
//手指點(diǎn)擊在view外
private
static
final
int
CLICK_INVAILD
=
0;
private
static
final
int[]
STATE_NORMAL
=
{};
private
static
final
int[]
STATE_PRESSED
=
{android.R.attr.state_pressed,android.R.attr.state_window_focused,};
private
static
int
mThumbMarginTop
=
0;
//滑動塊頂部離view頂部的距離
private
static
int
mTextViewMarginTop
=
0;
//當(dāng)前滑塊文字距離view頂部距離
private
Drawable
hasScrollBarBg;
//滑動條滑動后背景圖
private
Drawable
notScrollBarBg;
//滑動條未滑動背景圖
private
Drawable
mThumbLow;
//前滑塊
private
Drawable
mThumbHigh;
//后滑塊
private
int
mScollBarWidth;
//控件寬度
=
滑動條寬度
+
滑動塊寬度
private
int
mScollBarHeight;
//控件高度
private
int
mThumbWidth;
//滑動塊直徑
private
double
mOffsetLow
=
0;
//前滑塊中心坐標(biāo)
private
double
mOffsetHigh
=
0;
//后滑塊中心坐標(biāo)
private
int
mDistance=0;
//總刻度是固定距離
兩邊各去掉半個(gè)滑塊距離
private
int
mFlag
=
CLICK_INVAILD;
//手指按下的類型
private
double
defaultScreenLow
=
0;
//默認(rèn)前滑塊位置百分比
private
double
defaultScreenHigh
=
100;
//默認(rèn)后滑塊位置百分比
private
OnSeekBarChangeListener
mBarChangeListener;
private
boolean
editable=false;//是否處于可編輯狀態(tài)
private
int
miniGap=5;//AB的最小間隔
private
double
progressLow;//起點(diǎn)(百分比)
private
double
progressHigh;//終點(diǎn)
public
SeekRangeBar(Context
context)
{
this(context,
null);
}
public
SeekRangeBar(Context
context,
AttributeSet
attrs)
{
this(context,
attrs,
0);
}
public
SeekRangeBar(Context
context,
AttributeSet
attrs,
int
defStyle)
{
super(context,
attrs,
defStyle);
_context=context;
//這里設(shè)置背景圖及滑塊圖,自定義過進(jìn)度條的同學(xué)應(yīng)該很熟悉了
notScrollBarBg
=
ContextCompat.getDrawable(_context,R.mipmap.hp_wbf);
hasScrollBarBg
=
ContextCompat.getDrawable(_context,
R.mipmap.hp_ybf);
mThumbLow
=
ContextCompat.getDrawable(_context,R.mipmap.hp_a);
mThumbHigh
=
ContextCompat.getDrawable(_context,R.mipmap.hp_b);
mThumbLow.setState(STATE_NORMAL);
mThumbHigh.setState(STATE_NORMAL);
//設(shè)置滑動條高度
mScollBarHeight
=
notScrollBarBg.getIntrinsicHeight();
//設(shè)置滑動塊直徑
mThumbWidth
=
mThumbLow.getIntrinsicWidth();
}
/**
*
測量view尺寸(在onDraw()之前)
*
@param
widthMeasureSpec
*
@param
heightMeasureSpec
*/
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
int
width
=
MeasureSpec.getSize(widthMeasureSpec);
mScollBarWidth
=
width;
if(mDistance==0)
{//這里滑塊中心坐標(biāo)初始化的時(shí)候測量一下(根據(jù)mDistance是否賦值判斷),并不需要不停地去測量。后面會根據(jù)進(jìn)度計(jì)算滑塊位置。
mOffsetLow
=
mThumbWidth
/
2;
mOffsetHigh
=
width
-
mThumbWidth
/
2;
}
mDistance
=
width
-
mThumbWidth;
if(defaultScreenLow
!=
0)
{
mOffsetLow
=
formatInt(defaultScreenLow
/
100
*
(mDistance))
+
mThumbWidth
/
2;
}
if(defaultScreenHigh
!=
100)
{
mOffsetHigh
=
formatInt(defaultScreenHigh
/
100
*
(mDistance))
+
mThumbWidth
/
2;
}
setMeasuredDimension(width,
mThumbWidth
+
mThumbMarginTop
+
2);
}
protected
void
onLayout(boolean
changed,
int
l,
int
t,
int
r,
int
b)
{
super.onLayout(changed,
l,
t,
r,
b);
}
/**
*
繪制進(jìn)度條
*/
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
//設(shè)置繪制樣式
Paint
text_Paint
=
new
Paint();
text_Paint.setTextAlign(Paint.Align.CENTER);
text_Paint.setColor(Color.RED);
text_Paint.setTextSize(20);
int
top
=
mThumbMarginTop
+
mThumbWidth
/
2
-
mScollBarHeight
/
2;
int
bottom
=
top
+
mScollBarHeight;
//繪制是否可操作狀態(tài)的下的不同樣式,僅可編輯狀態(tài)下顯示進(jìn)度條
if(editable)
{
//白色滑動條,兩個(gè)滑塊各兩邊部分
notScrollBarBg.setBounds(mThumbWidth
/
2,
top,
mScollBarWidth
-
mThumbWidth
/
2,
bottom);
notScrollBarBg.draw(canvas);
//紅色滑動條,兩個(gè)滑塊中間部分
hasScrollBarBg.setBounds((int)
mOffsetLow,
top,
(int)
mOffsetHigh,
bottom);
hasScrollBarBg.draw(canvas);
}
//前滑塊
mThumbLow.setBounds((int)
(mOffsetLow
-
mThumbWidth
/
2),
mThumbMarginTop,
(int)
(mOffsetLow
+
mThumbWidth
/
2),
mThumbWidth
+
mThumbMarginTop);
mThumbLow.draw(canvas);
//后滑塊
mThumbHigh.setBounds((int)
(mOffsetHigh
-
mThumbWidth
/
2),
mThumbMarginTop,
(int)
(mOffsetHigh
+
mThumbWidth
/
2),
mThumbWidth
+
mThumbMarginTop);
mThumbHigh.draw(canvas);
//當(dāng)前滑塊刻度
progressLow
=
formatInt((mOffsetLow
-
mThumbWidth
/
2)
*
100
/
mDistance);
progressHigh
=
formatInt((mOffsetHigh
-
mThumbWidth
/
2)
*
100
/
mDistance);
canvas.drawText((int)
progressLow
+
"",
(int)
mOffsetLow
-
2
-
2,
mTextViewMarginTop,
text_Paint);
canvas.drawText((int)
progressHigh
+
"",
(int)
mOffsetHigh
-
2,
mTextViewMarginTop,
text_Paint);
if
(mBarChangeListener
!=
null)
{
mBarChangeListener.onProgressChanged(this,
progressLow,
progressHigh);
}
}
//手勢監(jiān)聽
@Override
public
boolean
onTouchEvent(MotionEvent
e)
{
if(!editable)
{
return
false;
}
if
(e.getAction()
==
MotionEvent.ACTION_DOWN)
{
mFlag
=
getAreaFlag(e);
if
(mFlag
==
CLICK_ON_LOW)
{
mThumbLow.setState(STATE_PRESSED);
}
else
if
(mFlag
==
CLICK_ON_HIGH)
{
mThumbHigh.setState(STATE_PRESSED);
}
else
if
(mFlag
==
CLICK_IN_LOW_AREA)
{
mThumbLow.setState(STATE_PRESSED);
mThumbHigh.setState(STATE_NORMAL);
//如果點(diǎn)擊0-mThumbWidth/2坐標(biāo)
if
(e.getX()
<
0
||
e.getX()
<=
mThumbWidth
/
2)
{
mOffsetLow
=
mThumbWidth
/
2;
}
else
if
(e.getX()
>
mScollBarWidth
-
mThumbWidth
/
2)
{
mOffsetLow
=
mThumbWidth
/
2
+
mDistance;
}
else
{
mOffsetLow
=
formatInt(e.getX());
}
}
else
if
(mFlag
==
CLICK_IN_HIGH_AREA)
{
mThumbHigh.setState(STATE_PRESSED);
mThumbLow.setState(STATE_NORMAL);
if
(e.getX()
>=
mScollBarWidth
-
mThumbWidth
/
2)
{
mOffsetHigh
=
mDistance
+
mThumbWidth
/
2;
}
else
{
mOffsetHigh
=
formatInt(e.getX());
}
}
//更新滑塊
invalidate();
}
else
if
(e.getAction()
==
MotionEvent.ACTION_MOVE)
{
if
(mFlag
==
CLICK_ON_LOW)
{
if
(e.getX()
<
0
||
e.getX()
<=
mThumbWidth
/
2)
{
mOffsetLow
=
mThumbWidth
/
2;
}
else
if
(e.getX()
>=
mScollBarWidth
-
mThumbWidth
/
2)
{
mOffsetLow
=
mThumbWidth
/
2
+
mDistance;
mOffsetHigh
=
mOffsetLow;
}
else
{
mOffsetLow
=
formatInt(e.getX());
if
(mOffsetHigh
-
mOffsetLow
<=
0)
{
mOffsetHigh
=
(mOffsetLow
<=
mDistance
+
mThumbWidth
/
2)
?
(mOffsetLow)
:
(mDistance
+
mThumbWidth
/
2);
}
}
}
else
if
(mFlag
==
CLICK_ON_HIGH)
{
if
(e.getX()
<
mThumbWidth
/
2)
{
mOffsetHigh
=
mThumbWidth
/
2;
mOffsetLow
=
mThumbWidth
/
2;
}
else
if
(e.getX()
>
mScollBarWidth
-
mThumbWidth
/
2)
{
mOffsetHigh
=
mThumbWidth
/
2
+
mDistance;
}
else
{
mOffsetHigh
=
formatInt(e.getX());
if
(mOffsetHigh
-
mOffsetLow
<=
0)
{
mOffsetLow
=
(mOffsetHigh
>=
mThumbWidth
/
2)
?
(mOffsetHigh)
:
mThumbWidth
/
2;
}
}
}
//更新滑塊,每次滑塊有動作都要執(zhí)行此函數(shù)觸發(fā)onDraw方法繪制新圖片
invalidate();
}
else
if
(e.getAction()
==
MotionEvent.ACTION_UP)
{
Log.d("LOGCAT","ACTION
UP:"+progressHigh+"-"+progressLow);
mThumbLow.setState(STATE_NORMAL);
mThumbHigh.setState(STATE_NORMAL);
if(miniGap>0
&&
progressHigh<progressLow+miniGap){
progressHigh=progressLow+miniGap;
this.defaultScreenHigh
=
progressHigh;
mOffsetHigh
=
formatInt(progressHigh
/
100
*
(mDistance))
+
mThumbWidth
/
2;
invalidate();
}
}
return
true;
}
/**
*
設(shè)置是否可編輯狀態(tài),非可編輯狀態(tài)將不能對AB點(diǎn)進(jìn)行操作
*
@param
_b
*/
public
void
setEditable(boolean
_b){
editable=_b;
invalidate();
}
/**
*
獲取當(dāng)前手指位置
*/
public
int
getAreaFlag(MotionEvent
e)
{
int
top
=
mThumbMarginTop;
int
bottom
=
mThumbWidth
+
mThumbMarginTop;
if
(e.getY()
>=
top
&&
e.getY()
<=
bottom
&&
e.getX()
>=
(mOffsetLow
-
mThumbWidth
/
2)
&&
e.getX()
<=
mOffsetLow
+
mThumbWidth
/
2)
{
return
CLICK_ON_LOW;
}
else
if
(e.getY()
>=
top
&&
e.getY()
<=
bottom
&&
e.getX()
>=
(mOffsetHigh
-
mThumbWidth
/
2)
&&
e.getX()
<=
(mOffsetHigh
+
mThumbWidth
/
2))
{
return
CLICK_ON_HIGH;
}
else
if
(e.getY()
>=
top
&&
e.getY()
<=
bottom
&&
((e.getX()
>=
0
&&
e.getX()
<
(mOffsetLow
-
mThumbWidth
/
2))
||
((e.getX()
>
(mOffsetLow
+
mThumbWidth
/
2))
&&
e.getX()
<=
((double)
mOffsetHigh
+
mOffsetLow)
/
2)))
{
return
CLICK_IN_LOW_AREA;
}
else
if
(e.getY()
>=
top
&&
e.getY()
<=
bottom
&&
(((e.getX()
>
((double)
mOffsetHigh
+
mOffsetLow)
/
2)
&&
e.getX()
<
(mOffsetHigh
-
mThumbWidth
/
2))
||
(e.getX()
>
(mOffsetHigh
+
mThumbWidth
/
2)
&&
e.getX()
<=
mScollBarWidth)))
{
return
CLICK_IN_HIGH_AREA;
}
else
if
(!(e.getX()
>=
0
&&
e.getX()
<=
mScollBarWidth
&&
e.getY()
>=
top
&&
e.getY()
<=
bottom))
{
return
CLICK_OUT_AREA;
}
else
{
return
CLICK_INVAILD;
}
}
/**
*
設(shè)置前滑塊位置
*
@param
progressLow
*/
public
void
setProgressLow(double
progressLow)
{
this.defaultScreenLow
=
progressLow;
mOffsetLow
=
formatInt(progressLow
/
100
*
(mDistance))
+
mThumbWidth
/
2;
invalidate();
}
/**
*
設(shè)置后滑塊位置
*
@param
progressHigh
*/
public
void
setProgressHigh(double
progressHigh)
{
this.defaultScreenHigh
=
progressHigh;
mOffsetHigh
=
formatInt(progressHigh
/
100
*
(mDistance))
+
mThumbWidth
/
2;
invalidate();
}
/*
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年山西老區(qū)職業(yè)技術(shù)學(xué)院高職單招高職單招英語2016-2024歷年頻考點(diǎn)試題含答案解析
- 2025年山東力明科技職業(yè)學(xué)院高職單招高職單招英語2016-2024歷年頻考點(diǎn)試題含答案解析
- 2025年安徽揚(yáng)子職業(yè)技術(shù)學(xué)院高職單招數(shù)學(xué)歷年(2016-2024)頻考點(diǎn)試題含答案解析
- 水塔維修施工方案
- 接樁施工方案
- 2025年安康職業(yè)技術(shù)學(xué)院高職單招高職單招英語2016-2024歷年頻考點(diǎn)試題含答案解析
- 2025至2030年中國無機(jī)雙簾卷門機(jī)數(shù)據(jù)監(jiān)測研究報(bào)告
- 2025年太原幼兒師范高等??茖W(xué)校高職單招職業(yè)適應(yīng)性測試近5年??及鎱⒖碱}庫含答案解析
- 2025年天津城市職業(yè)學(xué)院高職單招語文2018-2024歷年參考題庫頻考點(diǎn)含答案解析
- 2025年四川文化產(chǎn)業(yè)職業(yè)學(xué)院高職單招語文2018-2024歷年參考題庫頻考點(diǎn)含答案解析
- 2024年高考八省聯(lián)考地理適應(yīng)性試卷附答案解析
- 足浴技師與店內(nèi)禁止黃賭毒協(xié)議書范文
- 中國高血壓防治指南(2024年修訂版)要點(diǎn)解讀
- 2024-2030年中國光電干擾一體設(shè)備行業(yè)發(fā)展現(xiàn)狀與前景預(yù)測分析研究報(bào)告
- 湖南省岳陽市岳陽樓區(qū)2023-2024學(xué)年七年級下學(xué)期期末數(shù)學(xué)試題(解析版)
- 農(nóng)村自建房安全合同協(xié)議書
- 杜仲葉藥理作用及臨床應(yīng)用研究進(jìn)展
- 4S店售后服務(wù)6S管理新規(guī)制度
- 高性能建筑鋼材的研發(fā)與應(yīng)用
- 無線廣播行業(yè)現(xiàn)狀分析
- 漢語言溝通發(fā)展量表(長表)-詞匯及手勢(8-16月齡)
評論
0/150
提交評論