您的位置:首页 > 移动开发 > IOS开发

Android 仿ios 可滑动切换效果按钮 实例代码

2015-03-11 20:09 811 查看
我们经常可以在ios上看到许多炫彩华丽的可拖动切换的Switch 按钮,前几天看了一篇博客写的是仿蘑菇街可滑动切换的按钮,然后就按着那篇博客作者的思路亲自试验了一次,然后查阅了相关的资料,在这里跟大家分享一下心得, 本文主要说一下具体实现的过程与思路,以及一些重要函数的意思,图像是如何移动的,并附上自己的Demo,给像[b]我一样的新手一些参考。[/b]原作者博客地址http://blog.csdn.net/swust_chenpeng/article/details/19967501首先看下效果图 这边是自己的效果图

1.开发前需要知道的

1.重写VIew来实现切换按钮2.我们同过Canves(画布)来把我们的界面弄出来 ,http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html(详细介绍Canves的使用)3.基本的绘制图片方法, 对图片的剪切和限定显示的区域1.voiddrawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) 这个函数的作用是画一个位图,也就是我们的那个按钮其中 Rect src: 是对图片进行裁截,若是空null则显示整个图片RectF dst:是图片在Canvas画布中显示的区域,

2.接下来我说下实现的思路吧

12 341.其实他这个按钮是通过四张图片叠放在一起的,然后在使用图层对他们进行摆放,一个叠放在其他上面,这篇文章有很好的解释 canves 与 图层的解释 ,/article/2174447.html2.然后我们用Canves 绘制一个显示的区域,也就是上面图片中白色(3号)的图片的那个,接着我们用下面这个函数来截取 mSrc = new Rect(); 我们的白红相接(1号)的图片,来显示在3号图片内,由于我们截取图片的位置不同,则显示在区域内的截取图片也不同最后我们通过手机的移动来动态移动(1号)图片,然后随时刷新页面,于是则动态产生了手指能拖动2号按钮的效果。(主要思路)3。一个画图需要四大基本要素:1、一个用来保存像素的Bitmap;2、一个Canvas画布,绘制Bitmap操作;3、绘制的东西4、绘制的画笔Paint(颜色和样式)

4、如何获得一个Canvas对象。

Canvas对象的获取方式有三种:第一种我们通过重写View.onDraw方法,View中的Canvas对象会被当做参数传递过来,我们操作这个Canvas,效果会直接反应在View中。第二种就是当你想自己创建一个Canvas对象。从上面的基本要素可以明白,一个Canvas对象一定是结合了一个Bitmap对象的。所以一定要为一个Canvas对象设置一个Bitmap对象。

3.下面贴上SwitchButton.java 的核心代码

public class SwitchButton extends View implements android.view.View.OnClickListener{
private Bitmap mSwitchBottom, mSwitchThumb, mSwitchFrame, mSwitchMask;
private float mCurrentX = 0;
private boolean mSwitchOn = true;//开关默认是开着的
/**最大移动距离  */
private int mMoveLength;//最大移动距离
/**第一次按下的有效区域  */
private float mLastX = 0;//第一次按下的有效区域
/**绘制的目标区域大小  */
private Rect mDest = null;//绘制的目标区域大小
/**截取源图片的大小  */
private Rect mSrc = null;//
/**移动的偏移量  */
private int mDeltX = 0;//移动的偏移量
private Paint mPaint = null;
private OnChangeListener mListener = null;
private boolean mFlag = false;

public SwitchButton(Context context) {
this(context, null);
// TODO Auto-generated constructor stub
}

public SwitchButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// TODO Auto-generated constructor stub
}

public SwitchButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}

/**
* 初始化相关资源
*/
public void init() {
mSwitchBottom = BitmapFactory.decodeResource(getResources(),
R.drawable.switch_bottom);
mSwitchThumb = BitmapFactory.decodeResource(getResources(),
R.drawable.switch_btn_pressed);
mSwitchFrame = BitmapFactory.decodeResource(getResources(),
R.drawable.switch_frame);
mSwitchMask = BitmapFactory.decodeResource(getResources(),
R.drawable.switch_mask);
setOnClickListener(this);
setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
});

mMoveLength = mSwitchBottom.getWidth() - mSwitchFrame.getWidth();
mDest = new Rect(0, 0, mSwitchFrame.getWidth(), mSwitchFrame.getHeight());
mSrc = new Rect();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setAlpha(255);
mPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
setMeasuredDimension(mSwitchFrame.getWidth(), mSwitchFrame.getHeight());
}

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (mDeltX > 0 || mDeltX == 0 && mSwitchOn) {
if(mSrc != null) {
mSrc.set(mMoveLength - mDeltX, 0, mSwitchBottom.getWidth()
- mDeltX, mSwitchFrame.getHeight());
}
} else if(mDeltX < 0 || mDeltX == 0 && !mSwitchOn){
if(mSrc != null) {
mSrc.set(-mDeltX, 0, mSwitchFrame.getWidth() - mDeltX,
mSwitchFrame.getHeight());
}
}

int count = canvas.saveLayer(new RectF(mDest), null, Canvas.MATRIX_SAVE_FLAG
| Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
| Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG);

canvas.drawBitmap(mSwitchBottom, mSrc, mDest, null);
canvas.drawBitmap(mSwitchThumb, mSrc, mDest, null);
canvas.drawBitmap(mSwitchFrame, 0, 0, null);
canvas.drawBitmap(mSwitchMask, 0, 0, mPaint);
canvas.restoreToCount(count);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
mCurrentX = event.getX();
mDeltX = (int) (mCurrentX - mLastX);
// 如果开关开着向左滑动,或者开关关着向右滑动(这时候是不需要处理的)
if ((mSwitchOn && mDeltX < 0) || (!mSwitchOn && mDeltX > 0)) {
mFlag = true;
mDeltX = 0;
}

if (Math.abs(mDeltX) > mMoveLength) {
mDeltX = mDeltX > 0 ? mMoveLength : - mMoveLength;
}
invalidate();
return true;
case MotionEvent.ACTION_UP:
if (Math.abs(mDeltX) > 0 && Math.abs(mDeltX) < mMoveLength / 2) {
mDeltX = 0;
invalidate();
return true;
} else if (Math.abs(mDeltX) > mMoveLength / 2 && Math.abs(mDeltX) <= mMoveLength) {
mDeltX = mDeltX > 0 ? mMoveLength : -mMoveLength;
mSwitchOn = !mSwitchOn;
if(mListener != null) {
mListener.onChange(this, mSwitchOn);
}
invalidate();
mDeltX = 0;
return true;
} else if(mDeltX == 0 && mFlag) {
//这时候得到的是不需要进行处理的,因为已经move过了
mDeltX = 0;
mFlag = false;
return true;
}
return super.onTouchEvent(event);
default:
break;
}
invalidate();
return super.onTouchEvent(event);
}

public void setOnChangeListener(OnChangeListener listener) {
mListener = listener;
}

public interface OnChangeListener {
public void onChange(SwitchButton sb, boolean state);
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
mDeltX = mSwitchOn ? mMoveLength : -mMoveLength;
mSwitchOn = !mSwitchOn;
if(mListener != null) {
mListener.onChange(this, mSwitchOn);
}
invalidate();
mDeltX = 0;
}
}

4.最后附上Demo的源代码,其中我说明一下,手指移动的时候mSrc 是动态变化,这样我们在那个显示区域中显示的mSrc也是变化

的,http://download.csdn.net/detail/u014738387/8493205

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: