在好例子网,分享、交流、成长!
您当前所在位置:首页Java 开发实例Android平台开发 → android 自定义开关(滑动条控件) 示例源码

android 自定义开关(滑动条控件) 示例源码

Android平台开发

下载此实例
  • 开发语言:Java
  • 实例大小:1.42M
  • 下载次数:15
  • 浏览次数:470
  • 发布时间:2018-05-10
  • 实例类别:Android平台开发
  • 发 布 人:林夕凡
  • 文件格式:.rar
  • 所需积分:5
 相关标签: 滑动

实例介绍

【实例简介】

【实例截图】

from clipboard

【核心代码】

package com.lewis.customerview;

import com.lewis.slipbutton.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnTouchListener;

public class SlipButton extends View implements OnTouchListener {

	public static final String TAG = "SlipButton";
	// 开关开启时的背景,关闭时的背景,滑动按钮
	private Bitmap slipImg;
	//the background of the slip button
	private Bitmap bg;
	private Bitmap slipBubble;
	
	private Matrix matrix = new Matrix();
	private Paint paint = new Paint();
	// 滑动按钮的左边坐标
	private float leftPosOfSlipImg;
	//the middle value of the slip image,note: its not the half of the 
	//slip image width,its the place where to show the slip on or off
	//so its smaller than the half of the slip image
	private int slipOnEndPos = 0;
	private int slipOffStartPos = 0;
	private int bgWidth = 0;

	private Rect on_Rect;
	private Rect off_Rect;
	private Rect src_Rect;
	private Rect dst_Rect;
	// 是否正在滑动
	private boolean isSlipping = false;
	// 当前开关状态,true为开启,false为关闭
	private boolean isSwitchOn = false;
	
	// 手指按下时的水平坐标X,当前的水平坐标X
	private float previousX, currentX;

	// 开关监听器
	private OnSwitchListener onSwitchListener;
	// 是否设置了开关监听器
	private boolean isSwitchListenerOn = false;

	private VelocityTracker mVelocityTracker;
	private static final int SNAP_VELOCITY = 100;

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

	public SlipButton(Context context, AttributeSet attrs) {
		super(context, attrs);

		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.SlipButton);

		boolean isOn = a.getBoolean(R.styleable.SlipButton_slipOn, false);
		
		int count = a.getIndexCount();
		
		//get the specified recourse id in xml file
		int bgId = 0;
		int slipBtId = 0;
		
		for(int i = 0;i < count; i  ) {
			
			int attr = a.getIndex(i);
			switch(attr) {
			
			case R.styleable.SlipButton_bg:
				bgId = a.getResourceId(attr, 0);
				break;
			case R.styleable.SlipButton_slipImg:
				slipBtId = a.getResourceId(attr, 0);
				break;
			}
		}
		a.recycle();
		//decode the image defined in xml file
		setImageRes(bgId, slipBtId);
		setSwitchState(isOn);

		init();
	}

	/**
	 * set touch listener
	 */
	private void init() {

		setOnTouchListener(this);
	}
	
	public void setImageRes(int bgId, int slipId){
		
		bg = BitmapFactory.decodeResource(getResources(),bgId);
		slipImg = BitmapFactory.decodeResource(getResources(), slipId);
		
		slipBubble = BitmapFactory.decodeResource(getResources(),R.drawable.sb_slip_bubble);
		bgWidth = bg.getWidth();
		//The end position of the switch on state
		//25 is the value which half of slip image add to the bubble's right side
		slipOnEndPos = slipImg.getWidth()/2   slipBubble.getWidth()/2;
		//The start position of the switch off state
		slipOffStartPos = slipImg.getWidth()/2 - slipBubble.getWidth()/2;
		
		on_Rect = new Rect(0, 0,slipOnEndPos, slipImg.getHeight());
		off_Rect = new Rect(slipOffStartPos, 0, slipImg.getWidth(), slipImg.getHeight());			
		src_Rect = new Rect(0, 0, bg.getWidth(), slipImg.getHeight());		
		dst_Rect = new Rect(0, 0, bg.getWidth(), bg.getHeight());
		
		//this method should be called to initialize the rect state
		setDrawImgRect();
	}

	public void setSwitchState(boolean switchState) {
		isSwitchOn = switchState;

		if (isSwitchListenerOn) {

			onSwitchListener.onSwitched(isSwitchOn);
		}
		
		//reset the draw rect
		setDrawImgRect();
		//redraw the view
		invalidate();
	}

	public boolean getSwitchState() {
		return isSwitchOn;
	}

	public void updateSwitchState(boolean switchState) {
		isSwitchOn = switchState;
		invalidate();
	}
	
	@Override
	protected void onDraw(Canvas canvas) {

		super.onDraw(canvas);
		
		canvas.drawBitmap(slipImg, src_Rect, dst_Rect, paint);
		
		canvas.drawBitmap(bg, matrix, paint);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	
		setMeasuredDimension(bg.getWidth(),
				bg.getHeight());
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {

		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(event);

		boolean isUpAlreadyCatch = false;
		boolean previousState = false;

		switch (event.getAction()) {

		case MotionEvent.ACTION_MOVE:
			currentX = event.getX();
						
			previousState = isSwitchOn;
			//check whether need change the state of the switch
			changeSwitchState(event.getX());		
			
			if (isSwitchListenerOn && (previousState != isSwitchOn)) {

				onSwitchListener.onSwitched(isSwitchOn);
			}
			break;

		case MotionEvent.ACTION_DOWN:

			if (event.getX() > bg.getWidth() || event.getY() > bg.getHeight()) {
				return false;
			}

			isSlipping = true;
			previousX = event.getX();
			currentX = previousX;
			break;

		case MotionEvent.ACTION_UP:
			//catch up motion, the default should not change the state of the switch
			isUpAlreadyCatch = true;

			previousState = isSwitchOn;
			
			changeSwitchState(event.getX());			

		default:

			do {

				if (isUpAlreadyCatch) {
					break;
				}
				//when not catch the up motion, check the state of the switch by the move speed of the touch
				final VelocityTracker velocityTracker = mVelocityTracker;
				velocityTracker.computeCurrentVelocity(1000);
				int velocityX = (int) velocityTracker.getXVelocity();

				previousState = isSwitchOn;
				
				//when the move speed greater than the specified speed, we consider it has a state change
				if (velocityX > SNAP_VELOCITY) {

					isSwitchOn = true;
					break;
				}

				if (velocityX < -SNAP_VELOCITY) {

					isSwitchOn = false;
					break;
				}

			} while (false);

			isSlipping = false;
			
			//call the listener
			if (isSwitchListenerOn && (previousState != isSwitchOn)) {

				onSwitchListener.onSwitched(isSwitchOn);
			}

			if (mVelocityTracker != null) {
				mVelocityTracker.recycle();
				mVelocityTracker = null;
			}
			break;
		}
		
		//reset the draw rect
		setDrawImgRect();
		//redraw the view
		invalidate();
		return true;
	}
	
	private void changeSwitchState(float currentPos) {
		
		if (currentPos >= (bgWidth / 2)) {
			isSwitchOn = true;
		} else {
			isSwitchOn = false;
		}
	}
	
	private void setDrawImgRect(){
		
		do{
			
			//when slipping, calculator the left position of the slip image to be drawn
			if(isSlipping) {
				
				if (currentX > bgWidth) {
					
					leftPosOfSlipImg = on_Rect.left;			
				} else {		
					
					leftPosOfSlipImg = slipOffStartPos - currentX;
				}
			}
			
			if(isSlipping && leftPosOfSlipImg >= 0 && leftPosOfSlipImg <= bgWidth){
				
				break;
			}
			
			//need reset the position of the slip image
			if(isSwitchOn) {
				
				leftPosOfSlipImg = on_Rect.left;
			}else {
				leftPosOfSlipImg = off_Rect.left;
			}
			
		}while(false);
				
		int srcLeft = (int) leftPosOfSlipImg;
		
		src_Rect.left = srcLeft;
		src_Rect.right = srcLeft   bgWidth;
	}
	
	public void setOnSwitchListener(OnSwitchListener listener) {
		onSwitchListener = listener;
		isSwitchListenerOn = true;
	}

	public interface OnSwitchListener {
		abstract void onSwitched(boolean isSwitchOn);
	}
}

标签: 滑动

实例下载地址

android 自定义开关(滑动条控件) 示例源码

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警