自定义控件—滑动开关

    


自定义滑动开关就是控制右图在左图上左右滑动实现的效果


activity_main.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:itheima="http://schemas.android.com/apk/res/com.itheima.togglebutton85"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <com.itheima.togglebutton85.MyToggleButton
        android:id="@+id/toggle_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        itheima:slideBackground="@drawable/slide_background2"
        itheima:slideIcon="@drawable/slide_icon2"
        itheima:state="false"
        />

</RelativeLayout>


MainActivity


public class MainActivity extends Activity {

    private MyToggleButton toggleButton;

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toggleButton = (MyToggleButton) findViewById(R.id.toggle_button);
        toggleButton.setOnStateChangedListener(new OnStateChangedListener() {
			
			@Override
			public void onStateChanged(boolean state) {
				Toast.makeText(MainActivity.this, state ? "开" : "关", Toast.LENGTH_SHORT).show();
			}
		});
    }

}

MyToggleButton.java


public class MyToggleButton extends View {

	/** 开关按钮背景图片 */
	private Bitmap background;
	/** 开关按钮的滑块icon */
	private Bitmap slideIcon;
	/** 开关按钮的状态 */
	private boolean state;
	/**  开关按钮状态改变的监听器 */
	private OnStateChangedListener mOnStateChangedListener;
	/** 滑块背景图片的宽 */
	private int backgroundWidth;
	/** 滑块背景图片的高 */
	private int backgroundHeight;
	/** 滑块icon图片的宽*/
	private int slideIconWidth;
	/** 滑块icon图片的高 */
	private int slideIconHeight;
	/** 滑块icon left坐标 */
	private int slideIconLeft;
	/** 滑块向右移动的时候,滑块left的最大值 */
	private int maxSlideIconLeft;

	public MyToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		// 自定义属性的命令空间
		String namespace = "http://schemas.android.com/apk/res/com.itheima.togglebutton85";
		
		// 读取自定义属性
		// 读取滑块图片属性
		int slideBackgroundResId = attrs.getAttributeResourceValue(namespace, "slideBackground", -1);
		int slideIconResId = attrs.getAttributeResourceValue(namespace, "slideIcon", -1);
		if (slideBackgroundResId != -1 && slideIconResId != -1) {
			setSwitchImage(slideBackgroundResId, slideIconResId);
		}
		
		// 读取开关状态属性
		boolean state = attrs.getAttributeBooleanValue(namespace, "state", false);
		setState(state);
	}

	/**
	 * 设置开关的图片
	 * @param slideBackgroundResId 开关的背景图片资源id
	 * @param slideIconResId 开关上面的滑块icon
	 */
	public void setSwitchImage(int slideBackgroundResId, int slideIconResId) {
		background = BitmapFactory.decodeResource(getResources(), slideBackgroundResId);
		slideIcon = BitmapFactory.decodeResource(getResources(), slideIconResId);
		
		backgroundWidth = background.getWidth();
		backgroundHeight = background.getHeight();
		slideIconWidth = slideIcon.getWidth();
		slideIconHeight = slideIcon.getHeight();
		
		maxSlideIconLeft = backgroundWidth - slideIconWidth;
	}

	/** 设置开关按钮的状态 */
	public void setState(boolean state) {
		checkState(state);
		if (state) {
			// 如果要设置成开的状态,则把滑块画图到最右边
			slideIconLeft = maxSlideIconLeft;
		} else {
			// 如果要设置成关的状态,则把滑块画图到最左边
			slideIconLeft = 0;
		}
	}

	public void setOnStateChangedListener(OnStateChangedListener mOnStateChangedListener) {
		this.mOnStateChangedListener = mOnStateChangedListener;
	}
	
	/** 开关按钮状态改变的监听器 */
	public interface OnStateChangedListener {
		/**
		 * 状态发生改变的时候
		 * @param state ture代表开,false代表关
		 */
		void onStateChanged(boolean state);
	}
	
	/**
	 * 对View进行测量的方法 
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(backgroundWidth, backgroundHeight);	// 设置View的测量的宽高
	}
	
	/** 把View画出来的方法 
	 * @param canvas 画布
	 * */
	@Override
	protected void onDraw(Canvas canvas) {
		// 画滑块的背景
		int left = 0;
		int top = 0;
		canvas.drawBitmap(background, left, top, null);
		
		// 画滑块icon
		canvas.drawBitmap(slideIcon, slideIconLeft, 0, null);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
		case MotionEvent.ACTION_MOVE:
			// 滑动的时候计算滑块left = 触摸位置event.getX() – 滑块宽 / 2
			slideIconLeft = (int) (event.getX() - slideIconWidth / 2);
			
			// 预防滑动位置超出范围
			if (slideIconLeft < 0) {
				// 滑块往左移动时,left不能小于0
				slideIconLeft = 0;
			} else if (slideIconLeft > maxSlideIconLeft) {
				// 滑块往右移动时,滑块left的最大值 = 背景宽 – 滑块宽
				slideIconLeft = maxSlideIconLeft;
			}
			break;
		case MotionEvent.ACTION_UP:
			if (event.getX() < backgroundWidth / 2) {
				// 手指松开时,计算滑块应该滑到最左边,还是滑到最右边: 如果手指抬起的位置 < 背景宽 / 2,把滑块滑到最左边
				slideIconLeft = 0;
				checkState(false);
			} else {
				// 否则滑到最右边
				slideIconLeft = maxSlideIconLeft;
				checkState(true);
			}
			break;
		}
		invalidate();	// 重新刷新View,内部会调用onDraw方法
		return true;
	}

	private void checkState(boolean state) {
		if (this.state != state) {
			// 原来的状态和现在的状态如果不一样,则状态发生了改变
			this.state = state;
			
			// 如果状态发生改变,则通知监听器
			if (mOnStateChangedListener != null) {
				mOnStateChangedListener.onStateChanged(state);
			}
		}
	}
	
	

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值