很久之前就想写博客对自己的过去进行总结,由于个人比较懒这一原因而导致一直都未开始。现在鼓起勇气,克服这一懒惰心理开始写下第一篇博文。另外个人也是技术比较差,有什么写得不够好,不够详细的请各位同学多多指出,我将逐一改正。
好了,下面开始我们的自定义ToggleButton。那么我们先上图
首先ToggleButton这个view控件由一张可拖动,可点击的小圆点和背景图组成。
上代码: 那么我们开始代码实战,逐一解析
package com.example.togglebutton;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
public class MyToggleButton extends View implements OnClickListener {
// 背景图
private Bitmap backgroundBitmap;
// 拖动的button
private Bitmap slideBtn;
private Paint paint;
private float slideBtn_left;
// slideBtn的状态
private boolean currState = false;
// 是否为拖动状态
private boolean isDrag = false;
public MyToggleButton(Context context) {
super(context);
}
public MyToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
initData();
initListener();
}
private void initView() {
backgroundBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.radio_i);
slideBtn = BitmapFactory.decodeResource(getResources(),
R.drawable.radio_slider_big);
}
private void initData() {
paint = new Paint();
paint.setAntiAlias(true);
}
private void initListener() {
setOnClickListener(this);
}
@Override
/**
* 设置view的测量值
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(backgroundBitmap.getWidth(),
backgroundBitmap.getHeight());
}
@Override
protected void onDraw(Canvas canvas) {
// draw背景
canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
// draw拖动的按钮
canvas.drawBitmap(slideBtn, slideBtn_left, 2, paint);
}
@Override
/**
* 完整的一次down和up就是onclick事件
*/
public void onClick(View v) {
if (!isDrag) {
currState = !currState;
flushState();
}
}
private int firstX;
private int lastX;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
firstX = (int) event.getX();
isDrag = false;
break;
case MotionEvent.ACTION_MOVE:
lastX = (int) event.getX();
int distance = (int) (lastX - firstX);
if (Math.abs(distance) > 5) {// 如果移动距离超过5,则认为拖动了按钮
isDrag = true;
}
slideBtn_left = slideBtn_left + distance;
firstX = lastX;
break;
case MotionEvent.ACTION_UP:// 不管是onclick还是拖动都会触发up事件,所以在这里设置view的最终状态即可
if (isDrag) {
int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth();
if (slideBtn_left > maxLeft / 2) {// 如果拖动的距离超过可拖动距离的一半
currState = true;
} else {
currState = false;
}
flushState();
}
break;
}
// move与up事件时刷新view
refreshView();
return true;
}
private void flushState() {
if (currState) {
slideBtn_left = backgroundBitmap.getWidth() - slideBtn.getWidth();
} else {
slideBtn_left = 0;
}
refreshView();
switchChangedListener.currState(this, currState);
}
private void refreshView() {
int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth();
slideBtn_left = (slideBtn_left > 0) ? slideBtn_left : 0;
slideBtn_left = (slideBtn_left < maxLeft) ? slideBtn_left : maxLeft;
invalidate();
}
private MySwitchChangedListener switchChangedListener;
public interface MySwitchChangedListener {
void currState(View view, boolean state);
}
// 注册回调
public void setOnSwitchChangedListener(
MySwitchChangedListener switchChangedListener) {
this.switchChangedListener = switchChangedListener;
}
}
ToggleButton使用时就是可点击,可拖动。
那么我们先在构造方法中初始化2张图,再初始化画笔paint,再对该view(ToggleButton)注册单击事件,仿照SDK原生的togglebutton,再复写onTouchEvent方法监听3种事件down,move,up。
首先draw背景图是不变的,我们只需要draw小圆点的位置
onclick时,比较简单,小圆点要么在整个view的最左边,要么在最右边。关键是这个draw图的距离 算好 即可。
捕捉移动事件:
down时,我们只需要记录初始时的X坐标,以及设置为非拖动状态。
move时,如果移动的距离超过5我们则认为拖动了小圆点,获取拖动的距离再从新绘制一遍view即可,设置为拖动状态。
up时,如果触发过move事件则不是onclick事件,注意:一次onclick就是完整的一次down和up组成,中间不包含move事件。onclick事件这个是比较好绘制的,如果触发过move时可能有点困难,这里可以取的distance其实是背景图的width减去小圆点的width这段距离,如上图。当拖动的距离超过这段距离的一半时,我们就在up这边直接设置小圆点到view的最左边或者最右边。
好了,其实就那么多东西了,还有就是在添加一个回调接口返回开关的状态。回调也即是设计模式中的观察者模式,在Android中很多地方都有用到,这个是必须要掌握的。
最后在xml布局文件中引用该view
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.togglebutton.MyToggleButton
android:id="@+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="开关状态" />
</RelativeLayout>
还需要在Activity中注册togglebutton的切换监听
第一次写文章,文章写得很丑,很多功能都还不知道,以后再慢慢改进。今天就到这了!