android 自定义开关按钮

public class WiperSwitchButton extends View implements OnTouchListener {
	private Bitmap bg_on, bg_off, slipper_btn;
	/**
	 * 按下时的x和当前的x
	 */
	private float downX, nowX;

	/**
	 * 记录用户是否在滑动
	 */
	private boolean onSlip = false;

	/**
	 * 当前的状态
	 */
	private boolean nowStatus = false;

	/**
	 * 监听接口
	 */
	private OnChangedListener listener;

	public WiperSwitchButton(Context context) {
		super(context);
		init();
	}

	public WiperSwitchButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public WiperSwitchButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	@Override
	public void setLayoutParams(LayoutParams params) {
		super.setLayoutParams(params);
		params.width = bg_on.getScaledWidth(UIUtils.currentDisplayMetrics());
		params.height = bg_on.getScaledHeight(UIUtils.currentDisplayMetrics());
		super.setLayoutParams(params);
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN: {
			if (event.getX() > bg_off.getScaledWidth(UIUtils.currentDisplayMetrics())
					|| event.getY() > bg_off.getScaledHeight(UIUtils.currentDisplayMetrics())) {
				return false;
			} else {
				onSlip = true;
				downX = event.getX();
				nowX = downX;
			}
			break;
		}
		case MotionEvent.ACTION_MOVE: {
			nowX = event.getX();
			break;
		}
		case MotionEvent.ACTION_UP: {
			onSlip = false;

			nowStatus = !nowStatus;
			if (listener != null) {
				listener.OnChanged(WiperSwitchButton.this, nowStatus);
			}
			break;
		}
		}
		// 刷新界面
		invalidate();
		return true;
	}

	public void init() {
		// 载入图片资源
		bg_on = BitmapFactory.decodeResource(getResources(), R.drawable.on_btn);
		bg_off = BitmapFactory.decodeResource(getResources(),
				R.drawable.off_btn);
		slipper_btn = BitmapFactory.decodeResource(getResources(),
				R.drawable.bg_white);
		setOnTouchListener(this);
	}

	protected void onDraw(Canvas canvas) {
//		super.onDraw(canvas);
		Matrix matrix = new Matrix();
		Paint paint = new Paint();
		float x = 0;

	
		if (!nowStatus) {
            canvas.drawBitmap(bg_off, matrix, paint);// 画出关闭时的背景
        } else {
            canvas.drawBitmap(bg_on, matrix, paint);// 画出打开时的背景
        }

		if (onSlip) {// 是否是在滑动状态,
			if (nowX >= bg_on.getScaledWidth(UIUtils.currentDisplayMetrics()))// 是否划出指定范围,不能让滑块跑到外头,必须做这个判断
				x = bg_on.getScaledWidth(UIUtils.currentDisplayMetrics()) - slipper_btn.getScaledWidth(UIUtils.currentDisplayMetrics()) / 2;// 减去滑块1/2的长度
			else
				x = nowX - slipper_btn.getScaledWidth(UIUtils.currentDisplayMetrics()) / 2;
		} else {
			if (nowStatus) {// 根据当前的状态设置滑块的x值
				x = bg_on.getScaledWidth(UIUtils.currentDisplayMetrics()) - slipper_btn.getScaledWidth(UIUtils.currentDisplayMetrics());
			} else {
				x = 0;
			}
		}

		// 对滑块滑动进行异常处理,不能让滑块出界
		if (x < 0) {
			x = 0;
		} else if (x > bg_on.getScaledWidth(UIUtils.currentDisplayMetrics()) - slipper_btn.getScaledWidth(UIUtils.currentDisplayMetrics())) {
			x = bg_on.getScaledWidth(UIUtils.currentDisplayMetrics()) - slipper_btn.getScaledWidth(UIUtils.currentDisplayMetrics());
		}

		// 画出滑块
		canvas.drawBitmap(slipper_btn, x, 0, paint);
	}

	/**
	 * 为WiperSwitch设置一个监听,供外部调用的方法
	 * 
	 * @param listener
	 */
	public void setOnChangedListener(OnChangedListener listener) {
		this.listener = listener;
	}

	/**
	 * 设置滑动开关的初始状态,供外部调用
	 * 
	 * @param checked
	 */
	public void setChecked(boolean checked) {
		if (checked) {
			nowX = bg_off.getScaledWidth(UIUtils.currentDisplayMetrics());
		} else {
			nowX = 0;
		}
		//
		nowStatus = checked;
		//
		invalidate();
	}

	/*
	 * 回调接口
	 */
	public interface OnChangedListener {
		public void OnChanged(WiperSwitchButton wiperSwitch, boolean checkState);
	}
	 protected int measureDimension( int defaultSize, int measureSpec ) {
         
	        int result = defaultSize;
	         
	        int specMode = MeasureSpec.getMode(measureSpec);
	        int specSize = MeasureSpec.getSize(measureSpec);
	                 
	        //1. layout给出了确定的值,比如:100dp
	        //2. layout使用的是match_parent,但父控件的size已经可以确定了,比如设置的是具体的值或者match_parent
	        if (specMode == MeasureSpec.EXACTLY) {      
	            result = specSize; //建议:result直接使用确定值
	        } 
	        //1. layout使用的是wrap_content
	        //2. layout使用的是match_parent,但父控件使用的是确定的值或者wrap_content
	        else if (specMode == MeasureSpec.AT_MOST) {             
	            result = Math.min(defaultSize, specSize); //建议:result不能大于specSize
	        } 
	        //UNSPECIFIED,没有任何限制,所以可以设置任何大小
	        //多半出现在自定义的父控件的情况下,期望由自控件自行决定大小
	        else {      
	            result = defaultSize; 
	        }
	         
	        return result;
	    }

}
使用时:
<pre name="code" class="java"> <包名.WiperSwitchButton
                    android:id="@+id/switch1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="right|center_vertical"
                    android:layout_marginRight="16dp"
                    android:checked="true" />


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值