Android自定義控制元件模仿iOS滑塊SwitchButton
SwitchButton可以點選的時候切換狀態,類似CheckBox
在拖動的時候,也可以根據拖動的距離判斷是否切換狀態,類似ToggleButton
因此要區別出單擊事件和拖動事件
實現效果如圖所示:
自定義的SwitchButton如下:
public class SwitchButton extends View implements View.OnTouchListener {
private Bitmap bg_on, bg_off, slipper_btn;
/**
* 按下時的x和當前的x
*/
private float downX, nowX;
/**
* 記錄使用者是否在滑動
*/
private boolean onSlip = false;
/**
* 當前的狀態
*/
private boolean nowStatus = false;
/**
* 監聽介面
*/
private OnChangedListener listener;
/*
* 一個滑動的距離臨界值,判斷是滑動還是點選
* getScaledTouchSlop():
* Distance in pixels a touch can wander before we think the user is scrolling
* */
private int mTouchSlop=new ViewConfiguration().getScaledTouchSlop();
public SwitchButton(Context context) {
super(context);
init();
}
public SwitchButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public void init(){
//載入圖片資源
bg_on = BitmapFactory.decodeResource(getResources(), R.mipmap.switch_on_on);
bg_off = BitmapFactory.decodeResource(getResources(), R.mipmap.switch_off_off);
slipper_btn = BitmapFactory.decodeResource(getResources(), R.mipmap.switch_ball_ball);
setOnTouchListener(this);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Matrix matrix = new Matrix();
Paint paint = new Paint();
float x = 0;
//根據nowX設定背景,開或者關狀態
if (nowX < (bg_on.getWidth()/2)){
canvas.drawBitmap(bg_off, matrix, paint);//畫出關閉時的背景
}else{
canvas.drawBitmap(bg_on, matrix, paint);//畫出開啟時的背景
}
if (onSlip) {//是否是在滑動狀態,
if(nowX >= bg_on.getWidth())//是否劃出指定範圍,不能讓滑塊跑到外頭,必須做這個判斷
x = bg_on.getWidth() - slipper_btn.getWidth()/2;//減去滑塊1/2的長度
else
x = nowX - slipper_btn.getWidth()/2;
}else {
if(nowStatus){//根據當前的狀態設定滑塊的x值
x = bg_on.getWidth() - slipper_btn.getWidth();
}else{
x = 0;
}
}
//對滑塊滑動進行異常處理,不能讓滑塊出界
if (x < 0 ){
x = 0;
}
else if(x > bg_on.getWidth() - slipper_btn.getWidth()){
x = bg_on.getWidth() - slipper_btn.getWidth();
}
//畫出滑塊
canvas.drawBitmap(slipper_btn, x, 0, paint);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:{
if (event.getX() > bg_off.getWidth() || event.getY() > bg_off.getHeight()){
return false;
}else{
onSlip = true;
downX = event.getX();
nowX = downX;
}
break;
}
case MotionEvent.ACTION_MOVE:{
nowX = event.getX();
break;
}
case MotionEvent.ACTION_UP:{
DebugLog.e("mTouchSlop:"+mTouchSlop);
onSlip = false;
nowX = event.getX();
float float_distance=nowX - downX;
int int_disatnce=(int)float_distance;
DebugLog.e("int_disatnce:"+int_disatnce);
/*滑動距離太短,認定是點選事件*/
if(Math.abs(int_disatnce)<mTouchSlop){
if(this.isChecked()){
this.setChecked(false);
nowX = 0;
}else{
this.setChecked(true);
nowX = bg_on.getWidth() - slipper_btn.getWidth();
}
}else{
/*滑動距離足夠,認為是滑動事件*/
if(event.getX() >= (bg_on.getWidth()/2)){
nowStatus = true;
nowX = bg_on.getWidth() - slipper_btn.getWidth();
}else{
nowStatus = false;
nowX = 0;
}
}
if(listener != null){
listener.OnChanged(SwitchButton.this, nowStatus);
}
break;
}
}
//重新整理介面
invalidate();
return true;
}
/**
* 為WiperSwitch設定一個監聽,供外部呼叫的方法
* @param listener
*/
public void setOnChangedListener(OnChangedListener listener){
this.listener = listener;
}
/**
* 設定滑動開關的初始狀態,供外部呼叫
* @param checked
*/
public void setChecked(boolean checked){
if(checked){
nowX = bg_off.getWidth();
}else{
nowX = 0;
}
nowStatus = checked;
}
public boolean isChecked() {
return nowStatus;
}
/**
* 回撥介面
*
*/
public interface OnChangedListener {
public void OnChanged(SwitchButton wiperSwitch, boolean checkState);
}
}
佈局檔案中使用:
<com.uestcneon.chuji.changjianglife.share.SwitchButton android:id="@+id/user_privacy_state" android:layout_width="wrap_content" android:layout_height="20dp" android:layout_marginLeft="30dp" />
控制元件用到的3個資源圖片:
相關文章
- iOS 自定義雙向滑塊SlideriOSIDE
- WPF滑塊控制元件(Slider)的自定義樣式控制元件IDE
- iOS自定義控制元件 SlideriOS控制元件IDE
- iOS自定義控制元件 AlertViewiOS控制元件View
- iOS自定義控制元件 SegmentiOS控制元件
- Android 自定義View 滑動解鎖AndroidView
- Android自定義滑動刻度尺Android
- 【Android】自定義樹形控制元件Android控制元件
- iOS自定義控制元件:簡易下拉控制元件iOS控制元件
- iOS 自定義拖拽式控制元件:QiDragViewiOS控制元件View
- Android自定義View(四)側滑佈局AndroidView
- iOS 自定義卡片式控制元件:QiCardViewiOS控制元件View
- 【朝花夕拾】Android自定義View篇之(十一)View的滑動,彈性滑動與自定義PagerViewAndroidView
- [C#] (原創)一步一步教你自定義控制元件——03,SwitchButton(開關按鈕)C#控制元件
- iOS 自定義日曆(日期選擇)控制元件iOS控制元件
- iOS 自定義的卡片流互動控制元件iOS控制元件
- iOS自定義控制元件:自定義TableView、CollectionView空資料佔點陣圖iOS控制元件View
- Android 控制元件架構與自定義控制元件詳解Android控制元件架構
- Android自定義View--翻書控制元件(一)AndroidView控制元件
- Android自定義控制元件(神級)+MediaRecoder錄音Android控制元件
- Android自定義多宮格解鎖控制元件Android控制元件
- Android自定義控制元件 帶文字提示的SeekBarAndroid控制元件
- iOS自定義控制元件:精簡的底部彈框iOS控制元件
- [譯] 教你如何用 Flutter 的 GestureDetector 構建自定義滑塊Flutter
- Android側滑(右滑、下拉)返回控制元件 - SwipeBackLayoutAndroid控制元件
- Android自定義View之區塊選擇器AndroidView
- 自定義控制元件ViewPager控制元件Viewpager
- 自定義Switch控制元件控制元件
- 4. 自定義控制元件(4) --- 自定義屬性控制元件
- Android自定義控制元件(高手級)--JOJO同款能力分析圖Android控制元件
- Android自定義控制元件(高手級)–JOJO同款能力分析圖Android控制元件
- 從Android到ReactNative開發(三、自定義原生控制元件支援)AndroidReact控制元件
- Android開發之自定義隨機驗證碼控制元件Android隨機控制元件
- iOS 一個滑動選擇控制元件iOS控制元件
- winform 自定義容器控制元件ORM控制元件
- WPF Blend 自定義控制元件控制元件
- Flutter 之 自定義控制元件Flutter控制元件
- PyQT5之滑塊控制元件QSliderQT控制元件IDE
- Android自定義控制元件之區域性圖片放大鏡–BiggerViewAndroid控制元件View