自定义控件之滑动按钮

1.创建一个类继承view

public class MyToggleButton extends View {

	private static final String NAMESPACE = "http://schemas.android.com/apk/res/com.baidu.togglebutton";
	private Bitmap background;
	private Bitmap icon;
	/**
	 * 移动的位置
	 */
	private int lefticon;
	private int maxLeft;
	/**
	 * 是否抬起鼠标
	 */
	private boolean isHandup;

	public MyToggleButton(Context context) {
		//super(context);
		this(context,null);
	}
	
	public MyToggleButton(Context context, AttributeSet attrs) {
		//super(context, attrs);
		this(context,attrs,0);
	}
	
	public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		
		//获取自定义属性的值
		int backgroundid = attrs.getAttributeResourceValue(NAMESPACE, "backgroundid", R.drawable.slide_background);
		int iconid = attrs.getAttributeResourceValue(NAMESPACE, "iconid", R.drawable.slide_icon);
		boolean istoggle = attrs.getAttributeBooleanValue(NAMESPACE, "istoggle", true);
		
		//设置显示操作
		if (backgroundid != -1 && iconid != -1) {
			setBackgroundAndIcon(backgroundid, iconid);
		}
		//设置开关状态
		setToggle(istoggle);
	}

	//1.将开关背景及按钮传递给自定义控件
	/**
	 * 接受传递过来的背景及按钮的图片
	 * 2016-8-13 上午9:32:00
	 */
	public void setBackgroundAndIcon(int backgroundid,int iconid){
		background = BitmapFactory.decodeResource(getResources(), backgroundid);
		icon = BitmapFactory.decodeResource(getResources(), iconid);
		
		//获取图片之间宽度的距离
		maxLeft = background.getWidth() - icon.getWidth();
	}
	//2.显示控件
	//Android控件的绘制流程:1.测量控件的宽高;2.排版(设置控件的显示位置);3.绘制显示控件
	//只有第一步执行成功,才会去执行第二步,第二步执行成功,才会执行第三步,第三部步执行成功,显示出控件
	//如果activity的oncreate方法没有走完,不能显示出控件,不能获取控件的属性,比如宽高
	
	//1.测量控件的宽高
	//widthMeasureSpec : 当前控件的宽度
	//heightMeasureSpec : 当前控件的高度
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		//根据开关背景的宽高测量自定义控件的宽高
		setMeasuredDimension(background.getWidth(), background.getHeight());
	}
	
	//2.排版(设置控件的显示位置)
	//changed : 控件是否有最新位置
	//left top right bottom : 控件的左上右下的位置
	@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);
	}
	
	//3.绘制显示控件
	@Override
	protected void onDraw(Canvas canvas) {
		
		//绘制开关背景
		//bitmap : 根据那张图片绘制
		//left top : 绘制图片在x轴和y的轴的位置
		//paint : 画笔,因为绘制的是图片,图片的形状颜色已经有了,不需要画笔来绘制
		canvas.drawBitmap(background, 0, 0, null);//绘制图片
		
		//控制滑动的范围
		if (lefticon < 0) {
			lefticon = 0;
		}else if(lefticon > maxLeft){
			lefticon =  maxLeft;
		}
		
		
		//绘制完成,将开关状态存放到接口方法中,通过接口传递数据
		//1.抬起鼠标
		//2.绘制完成,获取到开关状态
		boolean isToggle = lefticon > 0;
		if (isHandup) {
			//2.绘制完成,获取到开关状态,保存到接口方法中
			if (onToggleOnListener != null) {
				onToggleOnListener.onToggleOn(isToggle);
			}
			//将是否抬起的标示设置为false,方便下一次抬起设置接口操作
			isHandup = false;
		}
		
		//绘制按钮
		canvas.drawBitmap(icon, lefticon, 0, null);
		super.onDraw(canvas);
	}
	
	/**
	 * 控件的触摸事件
	 * event : 触摸事件
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			//按下
			//移动位置 = 按下的x的坐标 - 按钮图片的宽度一半
			lefticon = (int) (event.getX()-icon.getWidth()/2);
			break;
		case MotionEvent.ACTION_MOVE:
			//移动
			//移动位置 = 按下的x的坐标 - 按钮图片的宽度一半
			lefticon = (int) (event.getX()-icon.getWidth()/2);
			break;
		case MotionEvent.ACTION_UP:
			//抬起
			isHandup = true;
			//设置自动滑动的操作
			//判断按下的x坐标和开关背景的宽度的一半
			if (event.getX() < background.getWidth()/2) {
				lefticon = 0;
			}else{
				lefticon = maxLeft;
			}
			break;
		}
		
		//获取到新的移动的位置之后,重新绘制控件,显示按钮
		//onDraw(canvas);不能直接使用onDraw方法
		invalidate();//间接的通过系统调用onDraw
		
		//True if the event was handled, false otherwise.
		//返回true:执行事件,返回false:拦截事件
		return true;
	}
	
	
	//回调函数
	//3.保存接口实现对象的变量
	private OnToggleOnListener onToggleOnListener;
	//2.创建获取接口对象的方法
	public void setOnToggleOnListener(OnToggleOnListener onToggleOnListener){
		this.onToggleOnListener = onToggleOnListener;
	}
	//1.创建接口
	public interface OnToggleOnListener{
		public void onToggleOn(boolean isToggle);
	}
	
	
	
	/**
	 * 手动设置开关状态
	 * @param
	 * 		isToggle : 开关状态
	 * 2016-8-13 上午11:23:14
	 */
	public void setToggle(boolean isToggle){
		
		isHandup = true;
		
		if (isToggle) {
			lefticon=maxLeft;
		}else{
			lefticon=0;
		}
		//重新绘制按钮
		invalidate();
	}

2.activity

public class MainActivity extends Activity {

    private MyToggleButton mMyToggleButon;
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    /**
     * 初始化控件
     * 2016-8-13 上午9:36:24
     */
	private void initView() {
		mMyToggleButon = (MyToggleButton) findViewById(R.id.mytogglebutton);
		
		//手动设置自定义控件的样式
		//mMyToggleButon.setBackgroundAndIcon(R.drawable.slide_background, R.drawable.slide_icon);
		//4.调用回调接口
		mMyToggleButon.setOnToggleOnListener(new OnToggleOnListener() {
			
			@Override
			public void onToggleOn(boolean isToggle) {
				Toast.makeText(getApplicationContext(), isToggle ? "开启" : "关闭", 0).show();
			}
		});
		//mMyToggleButon.setToggle(true);
	}    
}
3.main_activity.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:itheima="http://schemas.android.com/apk/res/com.itheima.togglebutton"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >

    <com.itheima.togglebutton.ui.MyToggleButton
        android:id="@+id/mytogglebutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        itheima:backgroundid="@drawable/slide_background"
        itheima:iconid="@drawable/slide_icon2"
        itheima:istoggle="true"
        ></com.itheima.togglebutton.ui.MyToggleButton>

</RelativeLayout>



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值