SwichButton是一個繼承自View自定義開關,剛好也通過這個自定義View來總結回顧下
** 第一步: 新建一個命名為SwichButton的類,繼承自View,重寫三個構造方法
第二步:在布局文件中使用
<com.cd.swichdemo.SwichButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/swichbutton"/>注意:自定義View要使用完整路徑名稱,系統控件則不需要
第三步:在Activity中找到這個控件的id
第四步:分析自定義的控件的需求,包括要設置什么屬性,有幾種狀態,等等
比如,分析這個自定義開關需要設置開關背景,需要設置滑塊背景,以及開和關兩種狀態,那么就需要分別定義設置開關背景的方法,設計滑塊背景的方法和設置狀態的方法
mSwichButton.setSwichBackgroundResouce(R.drawable.switch_background); mSwichButton.setSwichButtonResource(R.drawable.slide_button); mSwichButton.setSwichState(false);所以要在自定義的SwichButton中創建這三個方法
public void setSwichState(boolean swichState) { mSwichState = swichState; }
public void setSwichBackgroundResouce(int swichBackgroundResouce) { mBackgroundResouce = BitmapFactory.decodeResource(getResources(), swichBackgroundResouce);}public void setSwichButtonResource(int slide_button) { mSlidbutton = BitmapFactory.decodeResource(getResources(), slide_button);}可以手動創建也可以使用快捷鍵,setSwichState方法中mSwichState默認為false,setSwichBackgroundResouce(int swichBackgroundResouce)和setSwichButtonResource(int slide_button)方法中拿到設置的圖片資源,轉換成bitmap對象
補充:
Android View繪制流程 測量 擺放 大小 View :onMeasure(測量自己的寬高) –》onDraw(繪制自己的內容) viewGrounp: onMeasure(測量自己的寬高,所有子View的寬高) –》onLayout(擺放內部控件,只有容器才要重寫這個方法) –》onDraw(繪制自己的內容) */第五步:測量控件的寬高:該控件的寬高就是圖片的寬高,也可以寫死或者使用dimens
@Override PRotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(mBackgroundResouce.getWidth(), mBackgroundResouce.getHeight()); }重寫onMeasure方法,調用setMeasuredDimension傳入寬高,這樣這個控件的寬高就確定了
第六步:繪制視圖,重寫onDraw方法
@Override protected void onDraw(Canvas canvas) { //繪制背景 canvas.drawBitmap(mBackgroundResouce, 0, 0, mPaint); if (isTouchMode) {//如果是觸摸模式,則執行if //這些要畫圖理解,位置都是從控件的左上角開始計算的,移動即計算位移距離 float newLeft = mCurrentX - mSlidbutton.getWidth() / 2.0f; int maxLeft = mBackgroundResouce.getWidth() - mSlidbutton.getWidth(); //控制滑塊按鈕超過背景區域 if (newLeft < 0) { newLeft = 0; } else if (newLeft > maxLeft) { newLeft = maxLeft; } //繪制滑塊 canvas.drawBitmap(mSlidbutton, newLeft, 0, mPaint); } else {//非觸摸模式則通過設置的狀態來判斷開關 if (mSwichState) {//開 int newLeft = mBackgroundResouce.getWidth() - mSlidbutton.getWidth(); canvas.drawBitmap(mSlidbutton, newLeft, 0, mPaint); } else {//關 canvas.drawBitmap(mSlidbutton, 0, 0, mPaint); } } }繪制視圖必須有一支筆,創建一個init()方法,在里面創建一個paint,然后在每個構造方法中調用init()
private void init() { mPaint = new Paint(); }筆創建好了,才能在onDraw中使用,這里的paint,不建議直接在onDraw中創建
第七步:重寫觸摸事件
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: isTouchMode = false; mCurrentX = event.getX(); System.out.println("==:" + mCurrentX); //控件中間的位置, float center = mBackgroundResouce.getWidth() / 2.0f; //根據當前按下的位置和控件中心的位置進行比較 boolean state = mCurrentX > center; //如果當前狀態變化了,通知開關切換狀態 if (state != mSwichState && mSwichStateChangeListen != null) { mSwichStateChangeListen.stateChange(state); } //更新mSwichState 狀態 mSwichState = state; break; case MotionEvent.ACTION_MOVE: isTouchMode = true; mCurrentX = event.getX(); System.out.println("==:" + mCurrentX); break; case MotionEvent.ACTION_DOWN: isTouchMode = true; mCurrentX = event.getX(); System.out.println("==:" + mCurrentX); break; } invalidate();//一定要調用這個方法哦,不然不會重新繪制,導致滑動沒效果 return true;//返回true表示消費該事件 }第八步:定義接口設置狀態監聽回調
swichStateChangeListen mSwichStateChangeListen; public interface swichStateChangeListen { void stateChange(boolean state); } public void setSwichStateChangeListen(swichStateChangeListen swichStateChangeListen) { mSwichStateChangeListen = swichStateChangeListen; }在ACTION_UP的時候調用
case MotionEvent.ACTION_UP: isTouchMode = false; mCurrentX = event.getX(); System.out.println("==:" + mCurrentX); //控件中間的位置, float center = mBackgroundResouce.getWidth() / 2.0f; //根據當前按下的位置和控件中心的位置進行比較 boolean state = mCurrentX > center; //如果當前狀態變化了,通知開關切換狀態 if (state != mSwichState && mSwichStateChangeListen != null) { mSwichStateChangeListen.stateChange(state); } mSwichState = state; break;在Activity中設置監聽
mSwichButton.setSwichStateChangeListen(new SwichButton.swichStateChangeListen() { @Override public void stateChange(boolean state) { Toast.makeText(MainActivity.this, "state:" + state, Toast.LENGTH_SHORT).show(); } });使用如下
public class MainActivity extends AppCompatActivity { SwichButton mSwichButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSwichButton= (SwichButton) findViewById(R.id.swichbutton); mSwichButton.setSwichBackgroundResouce(R.drawable.switch_background); mSwichButton.setSwichButtonResource(R.drawable.slide_button); mSwichButton.setSwichState(false); mSwichButton.setSwichStateChangeListen(new SwichButton.swichStateChangeListen() { @Override public void stateChange(boolean state) { Toast.makeText(MainActivity.this, "state:" + state, Toast.LENGTH_SHORT).show(); } }); }}第一步:在values下新建attrs.xml,如果已經有了就直接添加屬性
<resources> <declare-styleable name="SwichButton"> <attr name="SwichBackground" format="reference"/> <attr name="swichButtonRes" format="reference"/> <attr name="swich_state" format="boolean"/> </declare-styleable></resources>第二步:
在自定義視圖中獲取到屬性,進行處理
//在xml中定義屬性使用的的構造方法 public SwichButton(Context context, AttributeSet attrs) { super(context, attrs); init(); String nameSpace="http://schemas.android.com/apk/res-auto"; int swichBackground = attrs.getAttributeResourceValue(nameSpace, "SwichBackground", -1); int swichButtonRes = attrs.getAttributeResourceValue(nameSpace, "swichButtonRes", -1); boolean swich_state = attrs.getAttributeBooleanValue(nameSpace, "swich_state", false); setSwichBackgroundResouce(swichBackground); setSwichButtonResource(swichButtonRes); setSwichState(swich_state); }第三步:在布局文件中設置
<com.cd.swichdemo.SwichButton android:layout_width="wrap_content" cd:SwichBackground="@drawable/switch_background" cd:swichButtonRes="@drawable/slide_button" cd:swich_state="false" android:layout_height="wrap_content" android:id="@+id/swichbutton"/>記得在跟布局上添加命名空間:http://schemas.android.com/apk/res-auto 這樣就完成了,activity中不需要在去另外設置,如下
public class MainActivity extends AppCompatActivity { SwichButton mSwichButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSwichButton= (SwichButton) findViewById(R.id.swichbutton); mSwichButton.setSwichStateChangeListen(new SwichButton.swichStateChangeListen() { @Override public void stateChange(boolean state) { Toast.makeText(MainActivity.this, "state:" + state, Toast.LENGTH_SHORT).show(); } }); }}demo下載:http://download.csdn.net/detail/cdhahaha/9748837
新聞熱點
疑難解答