閑的沒事,寫一個自定義的滑動開關按鈕ToggleButton
按鈕圖可以使用圖檔或者xml繪制的drawable檔案,demo中使用的是預設的,可以直接替換成自己需要的。
效果:
使用很簡單
1.将toggle-1.0.arr檔案放入libs目錄下(aar檔案可以直接在下面貼的github中下載下傳)
2.在build.gradle中加入依賴
implementation(name: 'toggle-1.0', ext: 'aar')
以上兩步完成就可以使用了
1.在xml布局中使用
xmlns:app="http://schemas.android.com/apk/res-auto"
<com.lange.toggle.ToggleButton
android:id="@+id/btn_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:btn_open_bg="@drawable/toggle_open_background"//自己替換打開時的背景圖或圖檔
app:btn_close_bg="@drawable/toggle_close_background"//自己替換關閉時的背景圖或圖檔
app:btn_slide_bg="@drawable/toggle_slide_background"//自己替換滑動按鈕的圖或圖檔
app:btn_left_right_padding="1dp"//按鈕距離背景圖左右的距離
android:layout_centerInParent="true"/>
2.activitu中使用
ToggleButton btn_toggle = findViewById(R.id.btn_toggle);
//這是方式2,方式1可以在xml布局檔案中直接設定開關圖檔
//btn_toggle.setToggleButtonOpenBackgroundResId(R.mipmap.switch_background);//設定滑動按鈕背景
//btn_toggle.setToggleButtonCloseBackgroundResId(R.mipmap.switch_background);//設定滑動按鈕背景
//btn_toggle.setToggleButtonSlideResId(R.mipmap.slide_button_background);//設定滑動按鈕圖
//btn_toggle.setToggleButtonState(ToggleButton.ToggleButtonState.Close);//設定開關狀态
//回調監聽狀态
btn_toggle.setOnToggleStateChangeListener(new ToggleButton.OnToggleStateChangeListener() {
@Override
public void onStateChange(ToggleButton.ToggleButtonState state) {
Toast.makeText(MainActivity.this, state== ToggleButton.ToggleButtonState.Close?"關":"開", Toast.LENGTH_SHORT).show();
}
});
大功告成!!!!就是這麼簡單!
下面貼上源碼,也可以直接去github上下載下傳源碼:github位址
/**
* 自定義滑動開關
*/
public class ToggleButton extends View {
private Bitmap btn_open_bg;
private Bitmap btn_close_bg;
private Bitmap btn_slide_bg;
private float leftOrRightPadding = 0;//設定觸摸按鈕左右邊距
public enum ToggleButtonState{
Open,Close;
}
//開關狀态變量
private ToggleButtonState mCurrentState = ToggleButtonState.Close;
/**
* 在Java代碼中直接new一個CustomView執行個體的時候,會調用該構造函數
* @param context
*/
public ToggleButton(Context context) {
this(context,null);
}
/**
* 在xml中引用CustomView标簽的時候,會調用2參數的構造函數。
* 這種方式通常是我們需要自定義View的屬性的時候,使用2參數的構造函數。
*/
public ToggleButton(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public ToggleButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//加載資源
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ToggleButton);
//設定xml中的背景圖
int imgOpenBgId = a.getResourceId(R.styleable.ToggleButton_btn_open_bg,R.drawable.toggle_open_background);
setToggleButtonOpenBackgroundResId(context,imgOpenBgId);
int imgCloseBgId = a.getResourceId(R.styleable.ToggleButton_btn_close_bg,R.drawable.toggle_close_background);
setToggleButtonCloseBackgroundResId(context,imgCloseBgId);
//設定xml中的按鈕圖
int imgSlideId = a.getResourceId(R.styleable.ToggleButton_btn_slide_bg,R.drawable.toggle_slide_background);
setToggleButtonSlideResId(context,imgSlideId);
//設定左右padding,自動轉成px
leftOrRightPadding = a.getDimensionPixelSize(R.styleable.ToggleButton_btn_left_right_padding,0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//設定view的大小區域
setMeasuredDimension(btn_open_bg.getWidth(),btn_open_bg.getHeight());
}
private float currentX;//記錄滑動的x位置
private boolean isSliding = false;//是否正在滑動
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
currentX = event.getX();
isSliding = true;
break;
case MotionEvent.ACTION_MOVE:
currentX = event.getX();
isSliding = true;
break;
case MotionEvent.ACTION_UP:
isSliding = false;
if(event.getX()>btn_open_bg.getWidth()/2){
if(mCurrentState == ToggleButtonState.Close) {
//打開狀态
mCurrentState = ToggleButtonState.Open;
if (stateChangeListener != null) {
stateChangeListener.onStateChange(mCurrentState);
}
}
}else {
if(mCurrentState == ToggleButtonState.Open){
//關閉狀态
mCurrentState = ToggleButtonState.Close;
if(stateChangeListener!=null){
stateChangeListener.onStateChange(mCurrentState);
}
}
}
/*if(mCurrentState == ToggleButtonState.Close) {
//打開狀态
mCurrentState = ToggleButtonState.Open;
}else{
//關閉狀态
mCurrentState = ToggleButtonState.Close;
}
if (stateChangeListener != null) {
stateChangeListener.onStateChange(mCurrentState);
}*/
break;
}
invalidate();
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//設定背景
canvas.drawBitmap(mCurrentState== ToggleButtonState.Open?btn_open_bg:btn_close_bg,0,0,null);
int top = (btn_open_bg.getHeight()-btn_slide_bg.getHeight())/2;
if(isSliding){
//設定滑動開關
float left = currentX-btn_slide_bg.getWidth()/2;
if(left<leftOrRightPadding)left = leftOrRightPadding;
if(left>btn_open_bg.getWidth()-btn_slide_bg.getWidth()-leftOrRightPadding){
left = btn_open_bg.getWidth()-btn_slide_bg.getWidth()-leftOrRightPadding;
}
canvas.drawBitmap(btn_slide_bg,left,top,null);
}else{
int left = (int)leftOrRightPadding;
if(mCurrentState== ToggleButtonState.Open){
left = btn_open_bg.getWidth()-btn_slide_bg.getWidth()-left;
}
canvas.drawBitmap(btn_slide_bg,left,top,null);
}
}
/**
* 代碼設定開關的背景圖檔
* @param resId
*/
@SuppressLint("NewApi")
public void setToggleButtonOpenBackgroundResId(Context context, int resId){
// btn_bg = BitmapFactory.decodeResource(getResources(),resId);
Drawable vectorDrawable = context.getDrawable(resId);
btn_open_bg = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(btn_open_bg);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
}
/**
* 代碼設定開關的背景圖檔
* @param resId
*/
@SuppressLint("NewApi")
public void setToggleButtonCloseBackgroundResId(Context context, int resId){
// btn_bg = BitmapFactory.decodeResource(getResources(),resId);
Drawable vectorDrawable = context.getDrawable(resId);
btn_close_bg = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(btn_close_bg);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
}
/**
* 代碼設定開關的按鈕圖檔
* @param resId
*/
@SuppressLint("NewApi")
public void setToggleButtonSlideResId(Context context,int resId){
//btn_slide_bg = BitmapFactory.decodeResource(getResources(),resId);
Drawable vectorDrawable = context.getDrawable(resId);
btn_slide_bg = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(btn_slide_bg);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
}
/**
* 代碼設定開關狀态
* @param state
*/
public void setToggleButtonState(ToggleButtonState state){
this.mCurrentState = state;
}
/**
* 設定位移動畫
* @param v
* @param fromX
* @param toX
*/
private void setTranslationAnim(View v,int fromX,int toX){
ObjectAnimator oa = ObjectAnimator.ofFloat(v,"translationX",fromX,toX,0,0);
oa.setDuration(200);
oa.start();
}
/**
* 設定監聽
*/
private OnToggleStateChangeListener stateChangeListener;
public interface OnToggleStateChangeListener{
void onStateChange(ToggleButtonState state);
}
public void setOnToggleStateChangeListener(OnToggleStateChangeListener stateChangeListener){
this.stateChangeListener = stateChangeListener;
}
}
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--自定義開關view-->
<declare-styleable name="ToggleButton">
<attr name="btn_open_bg" format="reference" />
<attr name="btn_close_bg" format="reference" />
<attr name="btn_slide_bg" format="reference" />
<attr name="btn_left_right_padding" format="dimension" />
</declare-styleable>
</resources>