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
新闻热点
疑难解答