转载请注明出处:http://blog.csdn.net/forwardyzk/article/details/42526343
当开发的时候,使用开关的时候,效果不能不满足我们的需求,要表现出滑动的效果。我们就可以自定义开关。
思路:
1.把开关分为两部分,一部分是开关的背景,另一部分是滑动按钮。
2.测量开关的长和宽,当然是在onMeasure中进行处理
3.在onTouchEvent()根据触摸开关进行滑动位置进行监听,在onDraw()中进行绘画。
当然也要绘画两部分:开关背景和滑动按钮
4.对触摸位置和滑动位置进行判断
1.触摸位置要在开关背景的范围内。
2.在绘画的时候,滑动按钮不能超出开关背景的范围。
在onTouchEvent()方法中调用invalidate()方法,会根据位置的变化不断的在onDraw()方法中绘画按钮。
设置开关的背景和滑动按钮
onXPosition和offXPosition为开关状态的变化之间,滑动按钮左侧的X坐标不能必须在两者之间。
public void setImageResource(int switchOnBg, int slipBtn) {
Log.d(TAG, "setImageResource");
switch_bg = BitmapFactory.decodeResource(getResources(), switchOnBg);
slip_Btn = BitmapFactory.decodeResource(getResources(), slipBtn);
onXPosition = switch_bg.getWidth() - slip_Btn.getWidth();
offXPosition = 0;
}
在OnTouchEvent()中监听手势滑动的位置
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
// 按下,判断按下的位置在开关上,才可以做后面的操作
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "MotionEvent.ACTION_DOWN");
if (event.getX() > switch_bg.getWidth()
|| event.getY() > switch_bg.getHeight()) {
return false;
}
isSlipping = true;
currentX = event.getX();
break;
// 滑动,记录当前的按下的位置
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "MotionEvent.ACTION_MOVE");
currentX = event.getX();
break;
// 松开,设置开关的监听器,设置开关的状态
case MotionEvent.ACTION_UP:
Log.d(TAG, "MotionEvent.ACTION_UP");
isSlipping = false;
// 松开前开关的状态
boolean previousSwitchState = isSwitchOn;
// 如果当前的位置在开关背景中间位置的右侧,表示的是开的状态,否则为关
if (event.getX() >= (switch_bg.getWidth() / 2)) {
isSwitchOn = true;
} else {
isSwitchOn = false;
}
// 如果设置了监听器,则调用此方法
if (onSwitchListener != null && (previousSwitchState != isSwitchOn)) {
onSwitchListener.onSwitched(isSwitchOn);
}
break;
default:
break;
}
// 重新绘制控件
invalidate();// 不要忘了重绘开关
return true;
}
在最后不要忘了调用invalidate(),否则不会进行绘画开关。
判断了触摸的范围必须在开关上
在onDraw()绘画开关
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Log.d(TAG, "onDraw");
Matrix matrix = new Matrix();
Paint paint = new Paint();
// 滑动按钮的X方向左侧坐标
float left_SlipBtn;
// 把开关的背景画出来
canvas.drawBitmap(switch_bg, matrix, paint);
// 判断当前是否正在滑动
if (isSlipping) {
if (currentX > switch_bg.getWidth()) {
left_SlipBtn = switch_bg.getWidth() - slip_Btn.getWidth();
} else {
// 保持滑动的位置是滑动按钮的中间位置
left_SlipBtn = currentX - slip_Btn.getWidth() / 2;
}
} else {
// 根据当前的开关状态设置滑动按钮的位置
if (isSwitchOn) {
left_SlipBtn = onXPosition;
} else {
left_SlipBtn = offXPosition;
}
}
// 对滑动按钮左侧和右侧进行判断,不能超过背景的范围
if (left_SlipBtn < 0) {
left_SlipBtn = 0;
} else if (left_SlipBtn > switch_bg.getWidth() - slip_Btn.getWidth()) {
left_SlipBtn = switch_bg.getWidth() - slip_Btn.getWidth();
}
// 绘制滑动开关
canvas.drawBitmap(slip_Btn, left_SlipBtn, 0, paint);
}
canvas.drawBitmap(switch_bg, matrix, paint)绘画开关背景
canvas.drawBitmap(slip_Btn, left_SlipBtn, 0, paint)绘画滑动按钮
滑动按钮滑动的时,保持不能超过开关背景的范围,保持点击的位置在滑动按钮的中间位置。
使用步骤:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/main_button_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:paddingBottom="3dp"
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:paddingTop="3dp"
android:text="切换状态"
android:textSize="15sp" />
<com.example.view.MySlipSwitch
android:id="@+id/main_myslipswitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="20dp" />
</RelativeLayout>
在MainActivity.java中使用
public class MainActivity extends Activity {
private Button switch_Btn;
private MySlipSwitch slipswitch_MSL;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setListener();
}
public void initView() {
slipswitch_MSL = (MySlipSwitch) findViewById(R.id.main_myslipswitch);
slipswitch_MSL.setImageResource(R.drawable.switch_bkg_switch,
R.drawable.switch_btn_slip);
slipswitch_MSL.setSwitchState(true);
switch_Btn = (Button) findViewById(R.id.main_button_switch);
}
public void setListener() {
//设置开关状态变化监听器
slipswitch_MSL.setOnSwitchListener(new OnSwitchListener() {
@Override
public void onSwitched(boolean isSwitchOn) {
// TODO Auto-generated method stub
if (isSwitchOn) {
Toast.makeText(getApplicationContext(), "开关已经开启", 0).show();
} else {
Toast.makeText(getApplicationContext(), "开关已经关闭", 0).show();
}
}
});
switch_Btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
slipswitch_MSL.setSwitchState(!slipswitch_MSL.getSwitchState());
if (slipswitch_MSL.getSwitchState()) {
Toast.makeText(getApplicationContext(), "开关已经开启", 0).show();
} else {
Toast.makeText(getApplicationContext(), "开关已经关闭", 0).show();
}
}
});
}
}
点击切换按钮,获取开关的状态
设置滑动开关状态的的监听器,滑动的位置影响到了开关的状态,有响应的监听。
源码下载: http://download.csdn.net/detail/forwardyzk/8341363
效果图: