首页 > 代码库 > 自定义滑动开关

自定义滑动开关

转载请注明出处: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

效果图:

技术分享





自定义滑动开关