【Android进阶】Android自定义滑动开关控件,适合所有的android系统

参考地址:http://blog.csdn.net/xiaanming/article/details/8842453

下面为黑马66期自定义开关的实现方式

效果图:




自定义MySwitch.java 代码:

package com.itheima.myswitch66;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * 自定义view流程: 1. 写类继承View 2. 重写onDraw, 进行绘制 3. 重新onMeasure,修改尺寸 4. 在xml布局文件中配置
 * 
 * @author Kevin
 * @date 2015-8-7
 */
public class MySwitch extends View {

	private Paint mPaint;
	private Bitmap mBitmapBg;
	private Bitmap mBitmapSlide;

	private int MAX_LEFT;// 滑块最大左边距
	private int mSlideLeft;// 当前左边距
	private boolean isOpen;// 当前开关状态

	private static final String NAMESPACE = "http://schemas.android.com/apk/res/com.itheima.myswitch66";

	public MySwitch(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView();
	}

	public MySwitch(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView();

		// 获取属性值
		isOpen = attrs.getAttributeBooleanValue(NAMESPACE, "checked", false);

		// 加载自定义滑块图片
		int slideId = attrs.getAttributeResourceValue(NAMESPACE, "slide", -1);
		if (slideId > 0) {
			mBitmapSlide = BitmapFactory
					.decodeResource(getResources(), slideId);
		}

		if (isOpen) {
			mSlideLeft = MAX_LEFT;
		} else {
			mSlideLeft = 0;
		}

		invalidate();
	}

	public MySwitch(Context context) {
		super(context);
		initView();
	}

	private void initView() {
		// 初始化画笔
		mPaint = new Paint();
		mPaint.setColor(Color.RED);// 画笔颜色

		// 初始化背景bitmap
		mBitmapBg = BitmapFactory.decodeResource(getResources(),
				R.drawable.switch_background);

		// 初始化滑块bitmap
		mBitmapSlide = BitmapFactory.decodeResource(getResources(),
				R.drawable.slide_button);

		MAX_LEFT = mBitmapBg.getWidth() - mBitmapSlide.getWidth();

		this.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (isClick) {
					if (isOpen) {
						// 关闭开关
						isOpen = false;
						mSlideLeft = 0;
					} else {
						// 打开开关
						isOpen = true;
						mSlideLeft = MAX_LEFT;
					}

					// view重绘的方法, 刷新view, 重新调用onDraw方法
					invalidate();

					// 回调当前开关状态
					if (mListener != null) {
						mListener.onCheckChanged(MySwitch.this, isOpen);
					}
				}
			}
		});
	}

	int startX = 0;
	int moveX = 0;// 位移距离
	boolean isClick;// 标记当前是触摸还是单击事件

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// 1. 记录起始点x坐标
			startX = (int) event.getX();// 获取相对于当前控件的x坐标
			break;
		case MotionEvent.ACTION_MOVE:
			// 2. 记录移动后的x坐标
			int endX = (int) event.getX();
			// 3. 记录x偏移量
			int dx = endX - startX;
			// 4. 根据偏移量,更新mSlideLeft
			mSlideLeft += dx;

			moveX += Math.abs(dx);// 向左向右移动都要统计下来, 所以要用dx绝对值

			// 避免滑块超出边界
			if (mSlideLeft < 0) {
				mSlideLeft = 0;
			}
			// 避免滑块超出边界
			if (mSlideLeft > MAX_LEFT) {
				mSlideLeft = MAX_LEFT;
			}

			// 5. 刷新界面
			invalidate();
			// 6. 重新初始化起始点坐标
			startX = (int) event.getX();
			break;
		case MotionEvent.ACTION_UP:
			// 根据位移判断是单击事件还是移动事件
			if (moveX < 5) {
				// 单击事件
				isClick = true;
			} else {
				// 移动事件
				isClick = false;
			}

			// 初始化移动的总距离
			moveX = 0;

			if (!isClick) {
				// 根据当前位置, 切换开关状态
				if (mSlideLeft < MAX_LEFT / 2) {
					// 关闭开关
					mSlideLeft = 0;
					isOpen = false;
				} else {
					// 打开开关
					mSlideLeft = MAX_LEFT;
					isOpen = true;
				}

				invalidate();
				// 回调当前开关状态
				if (mListener != null) {
					mListener.onCheckChanged(MySwitch.this, isOpen);
				}
			}
			break;

		default:
			break;
		}

		return super.onTouchEvent(event);
	}

	// 设置尺寸回调
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// setMeasuredDimension(100, 100);// 将当前控件宽高设置为100x100
		setMeasuredDimension(mBitmapBg.getWidth(), mBitmapBg.getHeight());// 依据背景图片来确定控件大小
		// System.out.println("onMeasure");
	}

	// measure->layout->draw
	// onMeasure->onLayout->onDraw
	@Override
	protected void onDraw(Canvas canvas) {
		// 绘制200x200的矩形
		// canvas.drawRect(0, 0, 200, 200, mPaint);
		// System.out.println("onDraw");
		// 绘制背景图片
		canvas.drawBitmap(mBitmapBg, 0, 0, null);
		// 绘制滑块图片
		canvas.drawBitmap(mBitmapSlide, mSlideLeft, 0, null);
	}

	private OnCheckChangeListener mListener;

	// 设置开关状态监听
	public void setOnCheckChangeListener(OnCheckChangeListener listener) {
		mListener = listener;
	}

	/**
	 * 监听开关状态的回调接口
	 */
	public interface OnCheckChangeListener {
		public void onCheckChanged(View view, boolean isChecked);
	}

}

attrs.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MySwitch">
        <attr name="slide" format="reference" />
        <attr name="checked" format="boolean" />
    </declare-styleable>

</resources>


MainActivity.java代码:

package com.itheima.myswitch66;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import com.itheima.myswitch66.MySwitch.OnCheckChangeListener;

public class MainActivity extends Activity {

	private MySwitch mSwitch;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mSwitch = (MySwitch) findViewById(R.id.ms_switch);
		mSwitch.setOnCheckChangeListener(new OnCheckChangeListener() {

			@Override
			public void onCheckChanged(View view, boolean isChecked) {
				Toast.makeText(getApplicationContext(), "当前状态:" + isChecked,
						Toast.LENGTH_SHORT).show();
			}
		});

		// CheckBox cb = new CheckBox(this);
		// cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
		//
		// @Override
		// public void onCheckedChanged(CompoundButton buttonView,
		// boolean isChecked) {
		//
		// }
		// });
	}

}


源代码下载地址http://download.csdn.net/detail/dodod2012/9508122

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值