自定義View之ToggleView
Android自定義View一般就2中方式,第一種是自定義某個控件,就是寫一個類繼承View,還有一種就是自定義某個佈局,就是寫一個類繼承Viewgroup,這篇文章主要學習一下如何自定義滑動塊(ToggleView)
1、寫一個類繼承View,重寫裏面的3個構造方法。
public class ToggleView extends View {
private static final String TAG = "Hsia";
private Bitmap toggleBackgroudBitmap;
private Bitmap toggleSlideBitmap;
private boolean toggleState = false;
private OnToggleStateListener onToggleStateListener;
private int currentX;
private boolean isSlideing = false;
private int midCurrentX;
//當創建對象的時候調用
public ToggleView(Context context) {
super(context);
}
public ToggleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ToggleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
2、設置自定義View的基本屬性(背景,狀態)
//設置toggle背景圖片
public void setToggleBackgroundResource(int toggleBackgroundResource) {
toggleBackgroudBitmap = BitmapFactory.decodeResource(getResources(), toggleBackgroundResource);
}
//設置滑動塊的圖片
public void setSlideResource(int slideResource) {
toggleSlideBitmap = BitmapFactory.decodeResource(getResources(), slideResource);
}
//滑動塊的狀態
public void setToggleState(boolean toggleState) {
this.toggleState = toggleState;
}
//滑動塊的狀態監聽
public void setonToggleStateListener(OnToggleStateListener onToggleStateListener) {
this.onToggleStateListener = onToggleStateListener;
}
public interface OnToggleStateListener {
public void onState(boolean state);
}
3、在layout佈局中引用,並設置相關屬性
佈局:
<com.example.testview.ToggleView
android:id="@+id/tg"
android:layout_width="wrap_content"
android:layout_centerInParent="true"
android:layout_height="wrap_content" />
Activi:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ToggleView mTG = (ToggleView) findViewById(R.id.tg);
//設置基本屬性
mTG.setToggleBackgroundResource(R.drawable.slide_background);
mTG.setSlideResource(R.drawable.slide_button);
//設置狀態
mTG.setToggleState(false);
//Toggle的狀態監聽
mTG.setonToggleStateListener(new ToggleView.OnToggleStateListener() {
@Override
public void onState(boolean state) {
if (state){
Toast.makeText(MainActivity.this, "當前爲開", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this, "當前爲關", Toast.LENGTH_SHORT).show();
}
}
});
}
4、自定義控件一般必須重寫 onMeasure onDraw onLayout 方法
重寫onMeasure,用於測量控件的大小,並設置。
/**
* 自定義控件一般必須重寫 onMeasure onDraw onLayout 方法,這裏繼承自View就不用重寫onLayout了
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//設置Toggle的大小,根據背景圖片大小設置
setMeasuredDimension(toggleBackgroudBitmap.getWidth(),toggleBackgroudBitmap.getHeight());
}
重寫onDraw,用於畫自定義View的佈局。主要是對滑動塊的邊界處理。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 開始畫背景
* @bitmap 背景的Bitmap
* @left X軸位置
* @top Y軸位置
* @paint 畫筆
*/
canvas.drawBitmap(toggleBackgroudBitmap,0,0,null);
//畫滑動塊 根據滑動位置畫
if (isSlideing) {
//將X位置設置到滑動塊中間
midCurrentX = currentX - toggleSlideBitmap.getWidth()/2;
int maxCurrentX = toggleBackgroudBitmap.getWidth() - toggleSlideBitmap.getWidth();
//不讓滑動塊超出背景的邊界
if (midCurrentX <= 0 ) {
midCurrentX = 0;
//調用toggleState讓滑動塊靠邊對齊
toggleState = false;
}else if (midCurrentX >=maxCurrentX){
midCurrentX = maxCurrentX;
toggleState = true;
}
canvas.drawBitmap(toggleSlideBitmap, midCurrentX,0,null);
}else {
//畫滑動塊 根據狀態去畫
if (toggleState) {
//計算X軸畫筆的位置
int canvasX = toggleBackgroudBitmap.getWidth()-toggleSlideBitmap.getWidth();
//開
canvas.drawBitmap(toggleSlideBitmap,canvasX,0,null);
}else {
//關
canvas.drawBitmap(toggleSlideBitmap,0,0,null);
// Log.d(TAG, "toggleState: "+toggleState);
}
}
}
onLayout一般在繼承Viewgroup的時候纔會重寫。
5、重寫onTouchEvent方法,監聽3種基本動作事件
/**
* 重寫點擊事件,用於監聽滑動塊的位置
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
currentX = (int) event.getX();
//定義一個狀態,當我按下的時候,通過滑動來畫
isSlideing = true;
break;
case MotionEvent.ACTION_UP:
currentX = (int) event.getX();
//當我鬆開鼠標,canvas按狀態去畫
isSlideing = false;
//判斷滑動結束後X軸的位置,如果超過背景的一半,就畫到另一邊
if (currentX <= toggleBackgroudBitmap.getWidth()/2) {
toggleState = false;
}else {
toggleState = true;
}
//當鼠標擡起手更新回調事件
if (onToggleStateListener != null) {
onToggleStateListener.onState(toggleState);
}
break;
case MotionEvent.ACTION_MOVE:
currentX = (int) event.getX();
break;
}
//刷新Draw
invalidate();
return true;
}
關於作者
- 個人網站:北京互聯科技
- Email:[email protected]
- 項目地址:https://github.com/swordman20/CustomizedToggleView