android 自定义开关

1.先看他在页面布局中的使用,这是布局中的一段

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myattrs="http://schemas.android.com/apk/res/cn.zectec.ptt"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#eee"
    android:orientation="vertical" >

    。。。。。。。
    
    <LinearLayout
        android:id="@+id/ll_group_scan"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        android:layout_weight="1"
        android:background="#fff"
        android:gravity="center_vertical"
        android:orientation="horizontal" >

        <ImageView
            style="@style/setting_image_style"
            android:layout_marginLeft="20dp"
            android:background="@drawable/group_scan" />

        <TextView
            style="@style/setting_text_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:text="@string/group_scan" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <cn.zectec.ptt.view.MToggleButton
            android:id="@+id/btn_mtogglebutton"
            android:layout_width="80dp"
            android:layout_height="30dp"
            android:layout_marginRight="20dp"
            myattrs:mtogglebutton_background_off="@drawable/mtogglebutton_background_off"
            myattrs:mtogglebutton_background_on="@drawable/mtogglebutton_background_on"
            myattrs:mtogglebutton_button="@drawable/mtogglebutton_button" />
        
    
    </LinearLayout>
    
    。。。。。。
</LinearLayout>


2.它用到了自定义属性,为自己设置开关的颜色,关闭的时候是灰色,打开是绿色,滑块是方形

mtogglebutton_background_off:<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <!-- 填充颜色 -->
    <solid android:color="#cccccc" />

    <!-- 矩形的圆角半径 -->
    <corners
        android:bottomLeftRadius="5dp"
        android:bottomRightRadius="5dp"
        android:topLeftRadius="5dp"
        android:topRightRadius="5dp" />
    <!-- 线的宽度,颜色灰色 -->
    <stroke
        android:width="1dp"
        android:color="#FFFFFF" >
    </stroke>
    
    <size 
        android:width="80dp"
        android:height="30dp"/>

</shape>

 
mtogglebutton_background_on:<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <!-- 填充颜色 -->
    <solid android:color="#43D7A3" />

    <!-- 矩形的圆角半径 -->
    <corners
        android:bottomLeftRadius="5dp"
        android:bottomRightRadius="5dp"
        android:topLeftRadius="5dp"
        android:topRightRadius="5dp" />
    <!-- 线的宽度,颜色灰色 -->
    <stroke
        android:width="1dp"
        android:color="#FFFFFF" >
    </stroke>
    
    <size 
        android:width="80dp"
        android:height="30dp"/>

</shape>

 

3.自定义开关的类:

public class MToggleButton extends View {

	private Bitmap sildBtn;
	private Paint paint;
	private boolean currState;
	private Context context;

	public MToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		// 根据属性集合和上下文 来设置id
		 TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MToggleBtn);
		
		 Drawable drawable = ta.getDrawable(R.styleable.MToggleBtn_mtogglebutton_background_on);
		 Bitmap bitmap = BitmapUtil.drawableToBitmap(drawable);
		 bitmap_bg_on = Bitmap.createScaledBitmap(bitmap,DensityUtil.dip2px(context, 80), DensityUtil.dip2px(context, 26), true);
		 
		 Drawable drawable3 = ta.getDrawable(R.styleable.MToggleBtn_mtogglebutton_background_off);
		 Bitmap bitmap3 = BitmapUtil.drawableToBitmap(drawable3);
		 bitmap_bg_off = Bitmap.createScaledBitmap(bitmap3,DensityUtil.dip2px(context, 80), DensityUtil.dip2px(context, 26), true);
		 
		 Drawable drawable2=ta.getDrawable(R.styleable.MToggleBtn_mtogglebutton_button);
		 Bitmap bitmap2 = BitmapUtil.drawableToBitmap(drawable2);
		 sildBtn = Bitmap.createScaledBitmap(bitmap2, DensityUtil.dip2px(context, 38), DensityUtil.dip2px(context, 22), true);

		initView();
	}

	public MToggleButton(Context context) {
		super(context);
		this.context = context;
		initView();
	}

	@SuppressWarnings("deprecation")
	private void initView() {
//		bitmap_bg = BitmapFactory.decodeResource(getResources(),
//				R.drawable.mtogglebutton_background_off);
//		sildBtn = BitmapFactory.decodeResource(getResources(),
//				R.drawable.mtogglebutton_button);
//		Drawable drawable = getResources().getDrawable(R.drawable.mtogglebutton_background);
//		Bitmap bitmap = BitmapUtil.drawableToBitmap(drawable);
//		bitmap_bg = Bitmap.createScaledBitmap(bitmap,DensityUtil.dip2px(context, 80), DensityUtil.dip2px(context, 30), true);
//		
//		Drawable drawable2 = getResources().getDrawable(R.drawable.mtogglebutton_button);
//		Bitmap bitmap2 = BitmapUtil.drawableToBitmap(drawable);
//		sildBtn = Bitmap.createScaledBitmap(bitmap2, DensityUtil.dip2px(context, 40), DensityUtil.dip2px(context, 30), true);
		

		sildBtnLeftMax = bitmap_bg_on.getWidth() - sildBtn.getWidth() - DensityUtil.dip2px(context, 4);

		paint = new Paint();
		paint.setAntiAlias(true);

		// 添加按钮的监听事件
		setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// 如果是滑动,不执行点击
				if (isDrop) {
					return;
				}
				// 点击时切换按钮的状态,声明一个布尔的变量
				currState = !currState;

				// 设置按钮状态的监听
				if (onBtnClickListener != null) {
					onBtnClickListener.onBtnClick(currState);
				}
				// 刷新状态
				flushState();
			}
		});
	}

	// 添加滑动事件,这里需要重写onTouchEvent(MotionEvent event)
	/**
	 * 判断是否发生拖动,我们定义:如果按下,移动在15像素之内,抬起,我们认为是点击,按点击的逻辑处理开关 如果,按下并移动超过15
	 * 个像素,我们认为是拖动,按拖动的逻辑处理开关
	 */
	private int startx;
	private int endx;
	private boolean isDrop;

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		/**
		 * 点击事件,也是触摸事件的一种,当发生UP事件时,
		 * 系统就认为发生了点击的动作,就会执行,onclickListener.onClick(View) 方法
		 * 但系统对点击事件的解析很粗糙,只要发生UP事件,就认为发生了点击的动作
		 */
		super.onTouchEvent(event);

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			startx = (int) event.getRawX();
			isDrop = false;
			break;
		case MotionEvent.ACTION_MOVE:
			endx = (int) event.getRawX();

			int disx = endx - startx;
			sildBtnLeft += disx;
			// 刷新view
			flushView();

			startx = endx;

			// 当移动距离大于15时,设为true
			if (Math.abs(disx) > 15) {
				isDrop = true;
			}

			break;
		case MotionEvent.ACTION_UP:
			if (isDrop) {
				if (sildBtnLeft > sildBtnLeftMax / 2) {
					currState = true;
				} else {
					currState = false;
				}
				flushState();
			}

			break;

		default:
			break;
		}

		return true;
	}

	public void flushState() {
		if (currState) {
			sildBtnLeft = sildBtnLeftMax;
		} else {
			sildBtnLeft = 0;
		}
		// 刷新view
		flushView();
	}

	private void flushView() {
		// 先对sildBtnLeft的值进行判断
		if (sildBtnLeft < 0) {
			sildBtnLeft = 0;
		} else if (sildBtnLeft > sildBtnLeftMax) {
			sildBtnLeft = sildBtnLeftMax;
		}
		// 通知系统 ,刷新页面,会导致 onDraw 方法的执行
		invalidate();
	}

	/**
	 * 一个view从创建到显示到屏幕上,要经历的步骤 一、测量控件的大小 onMeasure(int widthMeasureSpec, int
	 * heightMeasureSpec); 二、指定位置。 onLayout(boolean changed, int left, int top,
	 * int right,int bottom); 三、绘制控件 onDraw(Canvas canvas);
	 * 
	 */

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int width = bitmap_bg_on.getWidth();
		int height = bitmap_bg_on.getHeight();
		// 设置背景图片与控件的大小相同
		setMeasuredDimension(width, height);
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		// TODO Auto-generated method stub
		super.onLayout(changed, left, top, right, bottom);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		// 绘制背景
		/**
		 * 参数二,是图片在左边距, 参数三,是图片在上边距,
		 */
		if (currState) {
			canvas.drawBitmap(bitmap_bg_on, 0, 0, paint);
		}else {
			canvas.drawBitmap(bitmap_bg_off, 0, 0, paint);
		}
		// 绘制按钮
		canvas.drawBitmap(sildBtn, sildBtnLeft+DensityUtil.dip2px(context, 2), DensityUtil.dip2px(context, 2), paint);
	}

	// 定义按钮距离左边的距离
	private float sildBtnLeft = 0;
	private int sildBtnLeftMax;
	private Bitmap bitmap_bg_on;
	private Bitmap bitmap_bg_off;

	// 开关的监听
	private OnBtnClickListener onBtnClickListener;

	public void setOnBtnClick(OnBtnClickListener onBtnClickListener) {
		this.onBtnClickListener = onBtnClickListener;
	}

	public interface OnBtnClickListener {
		void onBtnClick(boolean currState);
	}

	public void initToggleState(boolean isOpenGroupScan) {
		if (isOpenGroupScan) {
			currState = true;
			sildBtnLeft = sildBtnLeftMax;
		} else {
			currState = false;
			sildBtnLeft = 0;
		}
		// 刷新view
		flushView();
	}

}

这里,自定义的开关可拖动也可点击,里面有个px和dp的转换工具类,以及图片的转换工具类,请参考我的以前博客。


4.页面中的使用

mToggleButton.initToggleState(false);//初始化开关状态
//为开关设置点击事件监听
<pre name="code" class="java">mToggleButton.setOnBtnClick(new OnBtnClickListenerImplementation());
private final class OnBtnClickListenerImplementation implements
			OnBtnClickListener{
		@Override
		public void onBtnClick(boolean currState) {//点击开关按钮			
<span style="white-space:pre">			</span>//开启或关闭。。。。
		}
	}


 



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值