android三檔自定義滑動開關,禁止點擊功能的實現,普通開關網上有很多例子,三檔滑動開關的則找了整天都沒有相關例子,開始用普通開關的源碼修改了自己實現了一個類,但效果不如人意,各種邊界情況的算法很難考慮周全很難調試出滿意的效果。
今天嘗試用系統組件seekbar實現自定義風格的滑動條,但禁止點擊和判斷滑動不到指定范圍返回花了不少時間,網上基本上都說用繼承seekbar修改里面的方法實現,但整了半天也沒有一個能夠達到效果了,而且感覺太麻煩了,所以自己把默認的實現的幾個接口返回的信息詳細打印出來調試了下,發現可以通過返回參數來實現自己想要的結果。
先上個效果圖
核心部分代碼:
private SeekBar seekbar;
private int lastProgress = 0;
private int newProgress = 0;
seekbar = (SeekBar)findViewById(R.id.seekBar);
seekbar.setOnSeekBarChangeListener( this);
// lastProgress=? 從配置文件中讀取
seekbar.setProgress(lastProgress);
1 @Override
2
public
void onProgressChanged(SeekBar paramSeekBar,
int progress,
3 boolean fromUser) {
4 Log.i("onProgressChanged=","cc progress="+ progress + " lastProgress="+ lastProgress+" newProgress="+ newProgress);
5 if(progress >newProgress+10 || progress<newProgress-10){
6 newProgress = lastProgress;
7 paramSeekBar.setProgress(lastProgress);
8 return;
9 }
10
11 newProgress = progress;
12 }
13
14 @Override
15 public void onStartTrackingTouch(SeekBar paramSeekBar) {
16 Log.i("onStartTrackingTouch="," lastProgress="+ lastProgress+" newProgress="+ newProgress);
17
18 }
19
20 @Override
21 public void onStopTrackingTouch(SeekBar paramSeekBar) {
22 Log.i("onStopTrackingTouch="," lastProgress="+ lastProgress+" newProgress="+ newProgress);
23
24 if(newProgress<30){
25 lastProgress = 0;
26 newProgress =0;
27 paramSeekBar.setProgress(0);
28 } else if(newProgress>70){
29 // 設置lastProgress 要放在setProgress之前,否則可能導致執行多次onProgressChanged 改變了原值
30 lastProgress = 100;
31 newProgress = 100;
32 paramSeekBar.setProgress(100);
33 } else{
34 lastProgress = 50;
35 newProgress =50;
36 paramSeekBar.setProgress(50);
37 }
38 Log.v("onStopTrackingTouch2="," lastProgress="+ lastProgress+" newProgress="+ newProgress);
39 changeProgressStateImg(lastProgress);
40 }
3 boolean fromUser) {
4 Log.i("onProgressChanged=","cc progress="+ progress + " lastProgress="+ lastProgress+" newProgress="+ newProgress);
5 if(progress >newProgress+10 || progress<newProgress-10){
6 newProgress = lastProgress;
7 paramSeekBar.setProgress(lastProgress);
8 return;
9 }
10
11 newProgress = progress;
12 }
13
14 @Override
15 public void onStartTrackingTouch(SeekBar paramSeekBar) {
16 Log.i("onStartTrackingTouch="," lastProgress="+ lastProgress+" newProgress="+ newProgress);
17
18 }
19
20 @Override
21 public void onStopTrackingTouch(SeekBar paramSeekBar) {
22 Log.i("onStopTrackingTouch="," lastProgress="+ lastProgress+" newProgress="+ newProgress);
23
24 if(newProgress<30){
25 lastProgress = 0;
26 newProgress =0;
27 paramSeekBar.setProgress(0);
28 } else if(newProgress>70){
29 // 設置lastProgress 要放在setProgress之前,否則可能導致執行多次onProgressChanged 改變了原值
30 lastProgress = 100;
31 newProgress = 100;
32 paramSeekBar.setProgress(100);
33 } else{
34 lastProgress = 50;
35 newProgress =50;
36 paramSeekBar.setProgress(50);
37 }
38 Log.v("onStopTrackingTouch2="," lastProgress="+ lastProgress+" newProgress="+ newProgress);
39 changeProgressStateImg(lastProgress);
40 }
===================================
相關自定義樣式,layout里面的布局
<LinearLayout
android:layout_width
="fill_parent"
android:layout_height ="wrap_content"
android:layout_marginTop ="25dip" >
< SeekBar
android:id ="@+id/seekBar"
android:layout_width ="520px"
android:layout_height ="wrap_content"
android:layout_centerInParent ="true"
android:max ="100"
android:maxHeight ="32px"
android:minHeight ="32px"
android:paddingLeft ="25px"
android:paddingRight ="25px"
android:progressDrawable ="@drawable/seekbar_style"
android:thumb ="@drawable/seekbar_thumb" />
</ LinearLayout >
android:layout_height ="wrap_content"
android:layout_marginTop ="25dip" >
< SeekBar
android:id ="@+id/seekBar"
android:layout_width ="520px"
android:layout_height ="wrap_content"
android:layout_centerInParent ="true"
android:max ="100"
android:maxHeight ="32px"
android:minHeight ="32px"
android:paddingLeft ="25px"
android:paddingRight ="25px"
android:progressDrawable ="@drawable/seekbar_style"
android:thumb ="@drawable/seekbar_thumb" />
</ LinearLayout >
簡單解釋下seekbar中幾個重要的屬性:
android:layout_height
="wrap_content"
//建議使用wrap_content,否則一定要保證設置的值不小於seekbar圖片資源中的最高值
android:paddingLeft="25px"
android:paddingRight="25px"
//說明進度條的最低和最大高度,解決高度問題。
android:paddingLeft="18px"
android:paddingRight="18px"
//解決拖動按鈕在最左最右顯示不全的問題,padding的值一般是thumb的一半寬度。
android:progressDrawable
="@drawable/seekbar_style"
//設置了此值,就表示使用自定義的進度條樣式,在其中可以設置進度條背景圖,進度條圖,緩沖條圖。
android:thumb
="@drawable/seekbar_thumb"
//seekbar的拖動按鈕圖片
seekbar_style.xml
<?
xml version="1.0" encoding="utf-8"
?>
< layer-list
xmlns:android ="http://schemas.android.com/apk/res/android" >
< item
android:id ="@android:id/background"
android:drawable ="@drawable/seekbar_bg" />
< item
android:id ="@android:id/progress"
android:drawable ="@drawable/seekbar_bg" />
< item
android:id ="@android:id/secondaryProgress"
android:drawable ="@drawable/seekbar_bg" />
< layer-list
xmlns:android ="http://schemas.android.com/apk/res/android" >
< item
android:id ="@android:id/background"
android:drawable ="@drawable/seekbar_bg" />
< item
android:id ="@android:id/progress"
android:drawable ="@drawable/seekbar_bg" />
< item
android:id ="@android:id/secondaryProgress"
android:drawable ="@drawable/seekbar_bg" />
</layer-list>
seekbar_thumb.xml
<?
xml version="1.0" encoding="utf-8"
?>
< selector xmlns:android ="http://schemas.android.com/apk/res/android" >
<!-- 按下狀態 -->
< item
android:state_focused ="true"
android:state_pressed ="true"
android:drawable ="@drawable/thumb_normal" />
<!-- 普通無焦點狀態 -->
< item
android:state_focused ="false"
android:state_pressed ="false"
android:drawable ="@drawable/thumb_normal" />
<!-- 有焦點狀態 -->
< item
android:state_focused ="true"
android:state_pressed ="false"
android:drawable ="@drawable/thumb_normal" />
<!-- 有焦點 -->
< item
android:state_focused ="true"
android:drawable ="@drawable/thumb_normal" />
< selector xmlns:android ="http://schemas.android.com/apk/res/android" >
<!-- 按下狀態 -->
< item
android:state_focused ="true"
android:state_pressed ="true"
android:drawable ="@drawable/thumb_normal" />
<!-- 普通無焦點狀態 -->
< item
android:state_focused ="false"
android:state_pressed ="false"
android:drawable ="@drawable/thumb_normal" />
<!-- 有焦點狀態 -->
< item
android:state_focused ="true"
android:state_pressed ="false"
android:drawable ="@drawable/thumb_normal" />
<!-- 有焦點 -->
< item
android:state_focused ="true"
android:drawable ="@drawable/thumb_normal" />
</selector>
===================================
注:在實際應用中對上面代碼進行了多次調優,這里把最終發布版本的代碼再共享下,效果圖如下:
核心代碼(優化部分,和上面相同的就不再重復了):
@Override
public
void onProgressChanged(SeekBar paramSeekBar,
int progress,
boolean fromUser) {
// Log.i("onProgressChanged=", "cc progress=" + progress
// + " lastProgress=" + lastProgress + " newProgress="
// + newProgress);
// +- 20 根據滑動條的寬度確定對應的比例
if (progress > newProgress + 20 || progress < newProgress - 20) {
newProgress = lastProgress;
paramSeekBar.setProgress(lastProgress);
return;
}
newProgress = progress;
}
@Override
public void onStartTrackingTouch(SeekBar paramSeekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar paramSeekBar) {
// Log.i("onStopTrackingTouch=", " lastProgress=" + lastProgress
// + " newProgress=" + newProgress+ " functionType=" + functionType);
if(newProgress == lastProgress){
return;
}
if("proximitytag".equals(functionType) && newProgress <30 ){
lastProgress = 0;
newProgress = 0;
paramSeekBar.setProgress(0);
return;
}
if("findme".equals(functionType) && newProgress >70){
lastProgress = 100;
newProgress = 100;
paramSeekBar.setProgress(100);
return;
}
if("stop".equals(functionType) && newProgress >30 && newProgress <70){
lastProgress = 50;
newProgress = 50;
paramSeekBar.setProgress(50);
return;
}
if (newProgress < 30) {
lastProgress = 0;
newProgress = 0;
paramSeekBar.setProgress(0);
functionType = "proximitytag";
} else if (newProgress > 70) {
// 設置lastProgress 要放在setProgress之前,否則可能導致執行多次onProgressChanged 改變了原值
lastProgress = 100;
newProgress = 100;
paramSeekBar.setProgress(100);
functionType = "findme";
} else {
lastProgress = 50;
newProgress = 50;
paramSeekBar.setProgress(50);
functionType = "stop";
}
Log.v("onStopTrackingTouch2=", " lastProgress=" + lastProgress
+ " newProgress=" + newProgress);
changeProgressStateImg(lastProgress);
}
public void changeProgressStateImg( int last_progress) {
ImageView proximitytag = (ImageView) MainActivity. this.findViewById(R.id.proximitytag);
ImageView stop = (ImageView) MainActivity. this.findViewById(R.id.stop);
ImageView findme = (ImageView) MainActivity. this.findViewById(R.id.findme);
proximitytag.setBackgroundResource(R.drawable.proximityblack);
stop.setBackgroundResource(R.drawable.stopblack);
findme.setBackgroundResource(R.drawable.findblack);
if (last_progress == 0) {
proximitytag.setBackgroundResource(R.drawable.proximityblue);
} else if (last_progress == 50) {
stop.setBackgroundResource(R.drawable.stopblue);
} else {
findme.setBackgroundResource(R.drawable.findblue);
}
}
boolean fromUser) {
// Log.i("onProgressChanged=", "cc progress=" + progress
// + " lastProgress=" + lastProgress + " newProgress="
// + newProgress);
// +- 20 根據滑動條的寬度確定對應的比例
if (progress > newProgress + 20 || progress < newProgress - 20) {
newProgress = lastProgress;
paramSeekBar.setProgress(lastProgress);
return;
}
newProgress = progress;
}
@Override
public void onStartTrackingTouch(SeekBar paramSeekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar paramSeekBar) {
// Log.i("onStopTrackingTouch=", " lastProgress=" + lastProgress
// + " newProgress=" + newProgress+ " functionType=" + functionType);
if(newProgress == lastProgress){
return;
}
if("proximitytag".equals(functionType) && newProgress <30 ){
lastProgress = 0;
newProgress = 0;
paramSeekBar.setProgress(0);
return;
}
if("findme".equals(functionType) && newProgress >70){
lastProgress = 100;
newProgress = 100;
paramSeekBar.setProgress(100);
return;
}
if("stop".equals(functionType) && newProgress >30 && newProgress <70){
lastProgress = 50;
newProgress = 50;
paramSeekBar.setProgress(50);
return;
}
if (newProgress < 30) {
lastProgress = 0;
newProgress = 0;
paramSeekBar.setProgress(0);
functionType = "proximitytag";
} else if (newProgress > 70) {
// 設置lastProgress 要放在setProgress之前,否則可能導致執行多次onProgressChanged 改變了原值
lastProgress = 100;
newProgress = 100;
paramSeekBar.setProgress(100);
functionType = "findme";
} else {
lastProgress = 50;
newProgress = 50;
paramSeekBar.setProgress(50);
functionType = "stop";
}
Log.v("onStopTrackingTouch2=", " lastProgress=" + lastProgress
+ " newProgress=" + newProgress);
changeProgressStateImg(lastProgress);
}
public void changeProgressStateImg( int last_progress) {
ImageView proximitytag = (ImageView) MainActivity. this.findViewById(R.id.proximitytag);
ImageView stop = (ImageView) MainActivity. this.findViewById(R.id.stop);
ImageView findme = (ImageView) MainActivity. this.findViewById(R.id.findme);
proximitytag.setBackgroundResource(R.drawable.proximityblack);
stop.setBackgroundResource(R.drawable.stopblack);
findme.setBackgroundResource(R.drawable.findblack);
if (last_progress == 0) {
proximitytag.setBackgroundResource(R.drawable.proximityblue);
} else if (last_progress == 50) {
stop.setBackgroundResource(R.drawable.stopblue);
} else {
findme.setBackgroundResource(R.drawable.findblue);
}
}