自定義滑動開關按鈕-SwitchButton
阿新 • • 發佈:2019-02-18
最近,在專案開發中需要用到開關按鈕,因為業務需求,需要適應自己的App style,所以決定親自實操一遍,自定義一個控制元件。
業務需求:
1.開關點選事件
2.開關滑動事件
3.涉及了動態測量繪製文字的寬高
先上效果圖,如下:
因為比較簡單,沒有自定義屬性,註釋比較完整,所以貼上完整程式碼給你們參考,有問題可以私聊。
完整程式碼如下:
public class AutoButton extends View implements View.OnTouchListener{
//開關背景圖
private Bitmap bgBitmap;
//開關按鈕圖
private Bitmap btnBitmap;
private Paint paint;
//標記開關滑動的值
private int leftDis=0;
//標記開關滑動的最大值
private int slidingMax;
//設定開關對應的文字
private final String text1="開";
private final String text2="關;
//標記開關狀態
private boolean mCurrent;
//標記點選事件
private boolean isClickable;
//標記滑動事件
private boolean isMove;
//開關開啟的事件監聽器
private SoftFloorListener softFloorListener;
//開關關閉的事件監聽器
private HydropowerListener hydropowerListener;
//標記開關文字的寬度
float width1,width2;
//記錄文字中心點 cx1:繪製文字1的x座標 cx2:繪製文字2的x座標
//cy記錄繪製文字的高度
float cx1,cy,cx2;
//程式碼例項化需要的方法
public AutoButton(Context context) {
this(context,null);
}
//在xml佈局時需要用到的方法
public AutoButton(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public AutoButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
//初始化資料
private void initView() {
//載入背景圖
bgBitmap= BitmapFactory.decodeResource(getResources(), R.drawable.bg_switchbutton);
//載入開關按鈕圖 btnBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.btn_switchbutton);
paint=new Paint();
slidingMax=bgBitmap.getWidth()-btnBitmap.getWidth();
paint.setTextSize(35);
//測量繪製文字1的寬度
width1= paint.measureText(text1);
//測量文字的寬度
Paint.FontMetricsInt fontMetricsInt=paint.getFontMetricsInt();
cy=btnBitmap.getHeight()/2+(fontMetricsInt.descent-fontMetricsInt.ascent)/2;
width2= paint.measureText(text2);
cx2=(bgBitmap.getWidth()*2-btnBitmap.getWidth())/2-width2/2;
paint.setAntiAlias(true);
setOnTouchListener(this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//根據載入圖片設定控制元件的大小
setMeasuredDimension(bgBitmap.getWidth(),bgBitmap.getHeight());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//繪製背景圖
canvas.drawBitmap(bgBitmap,0,0,paint);
//繪製按鈕圖
canvas.drawBitmap(btnBitmap,leftDis,0,paint);
//根據不同狀態繪製不同顏色,不同位置的文字
if (mCurrent){
paint.setColor(Color.WHITE);
canvas.drawText(text2,cx2,cy,paint);
paint.setColor(Color.BLACK);
canvas.drawText(text1,cx1,cy,paint);
}else {
paint.setColor(Color.WHITE);
canvas.drawText(text1,cx1,cy,paint);
paint.setColor(Color.BLACK);
canvas.drawText(text2,cx2,cy,paint);
}
}
//根據事件重新整理檢視
private void flushView() {
mCurrent=!mCurrent;
if (mCurrent){
leftDis=slidingMax;
if (hydropowerListener!=null){
//按鈕開啟監聽器
hydropowerListener.hydropower();
}
}else {
leftDis=0;
if (softFloorListener!=null){
//按鈕關閉監聽器
softFloorListener.softFloor();
}
}
invalidate();
}
//startX 標記手指按下的X座標, lastX 標記移動後的x座標
//disX 標記x方向移動的距離
float startX,lastX,disX;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
isClickable=true;
startX=event.getX();
isMove=false;
break;
case MotionEvent.ACTION_MOVE:
lastX=event.getX();
disX=lastX-startX;
//設定一個移動的閾值
if (Math.abs(disX)<5) break;
isMove=true;
isClickable=false;
moveBtn();
startX=event.getX();
break;
case MotionEvent.ACTION_UP:
//點選事件
if (isClickable){
flushView();
}
//滑動事件
if (isMove){
if (leftDis>slidingMax/2){
mCurrent=false;
}else {
mCurrent=true;
}
flushView();
}
break;
}
return true;
}
//按鈕滑動時的位置控制
private void moveBtn() {
leftDis+=disX;
if (leftDis>slidingMax){
leftDis=slidingMax;
}else if (leftDis<0){
leftDis=0;
}
invalidate();
}
//設定按鈕開啟監聽器
public void setSoftFloorListener(SoftFloorListener softFloorListener){
this.softFloorListener=softFloorListener;
}
//設定按鈕關閉監聽器
public void setHydropowerListener(HydropowerListener hydropowerListener){
this.hydropowerListener=hydropowerListener;
}
//設定按鈕開啟監聽器介面
public interface SoftFloorListener{
void softFloor();
}
//設定按鈕開啟監聽器介面
public interface HydropowerListener{
void hydropower();
}
}