使用Scroller制作滑块开关ToggleButton

一、实现思路

Toggle需要三张图片,一个是背景图片、一个状态为开的图片、一个状态为关的图片。

由于不会美工,仅仅使用photozoom缩放了三张图片,并不是那么完美,各位看官凑活着看吧。

第一张图片是我们的背景图片,当然也是通过android:background=”@drawable/xxx”来设置的,第二张是状态为开的时候的图片,当然,最后一张就是关了。

实现思路就这么简单,接下载我们来看一下代码。

二、实现代码

public class Toggle extends View {private int mNowX; // 当前滑块的x位置private int mSmoothDuration = 500;private boolean isOpen; // 是否为打开状态private Drawable mOpenDrawable; // 打开状态的图片private Drawable mCloseDrawable; // 关闭状态的图片private Scroller mScroller;public Toggle(Context context, AttributeSet attrs) {this(context, attrs, 0);}public Toggle(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mScroller = new Scroller(context, new LinearInterpolator());// 获取两张图片TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.toggle, defStyleAttr, 0);mOpenDrawable = ta.getDrawable(R.styleable.toggle_drawable_open);mCloseDrawable = ta.getDrawable(R.styleable.toggle_drawable_close);ta.recycle();}/** * 状态改变时,保存一下isOpen变量 * 例如 屏幕旋转,防止在旋转后恢复原样了 */@Overrideprotected Parcelable onSaveInstanceState() {Bundle bundle = new Bundle();bundle.putBoolean("open", isOpen);bundle.putParcelable("state", super.onSaveInstanceState());return bundle;}/** * 获取保存的isOpen */@Overrideprotected void onRestoreInstanceState(Parcelable state) {if(state instanceof Bundle) {Bundle bundle = (Bundle) state;isOpen = bundle.getBoolean("open");state = bundle.getParcelable("state");}super.onRestoreInstanceState(state);}/** * 测量 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);/** * 获取背景的宽高 */Drawable background = getBackground();// background.getBounds().width()是在背景绘制完成后才返回值// 此时返回0//background.getBounds().width();// 获取宽度int width = Math.max(background.getIntrinsicWidth(), 50);// 获取高度int height = Math.max(background.getIntrinsicHeight(), 20);// 父布局给指定了大小if(widthMode == MeasureSpec.EXACTLY) {width = widthSize;}else if(widthMode == MeasureSpec.AT_MOST) { // 父布局给指定了最大限度width = Math.min(width, widthSize);}setMeasuredDimension(width, height);// 如果“关闭” 则滑块的位置为当前view宽度-关闭图片宽度if(!isOpen) mNowX = getMeasuredWidth() – mCloseDrawable.getIntrinsicWidth();}@Overrideprotected void onDraw(Canvas canvas) {// 根据isOpen获取当前要绘制的drawableDrawable drawing = isOpen ? mOpenDrawable : mCloseDrawable;// clip boundsdrawing.setBounds(mNowX, 0, mNowX + mOpenDrawable.getIntrinsicWidth(), getMeasuredHeight());// draw on the canvasdrawing.draw(canvas);}@Overridepublic void computeScroll() {if(mScroller.computeScrollOffset()) {mNowX = mScroller.getCurrX();if(mScroller.isFinished()) {isOpen = !isOpen;if(isOpen) mNowX = 0;else mNowX = getMeasuredWidth() – mCloseDrawable.getIntrinsicWidth();}postInvalidate();}}public void toggle() {mScroller.abortAnimation();// open -> closeif(isOpen) {mScroller.startScroll(0, 0, getMeasuredWidth() – mOpenDrawable.getIntrinsicWidth() ,0, mSmoothDuration);}else {mScroller.startScroll(getMeasuredWidth() – mCloseDrawable.getIntrinsicWidth(), 0,mOpenDrawable.getIntrinsicWidth()-getMeasuredWidth(), 0, mSmoothDuration);}postInvalidate();}/** * 设置Scroller的Interpolator * @param interpolator */public void setInterpolator(Interpolator interpolator) {mScroller = new Scroller(getContext(), interpolator);}/** * 设置动画完成的时间间隔 * @param duration */public void setSmoothDuration(int duration) {mSmoothDuration = duration;}public boolean isOpen() {return isOpen;}public void open() {isOpen = true;mNowX = 0;postInvalidate();}public void close() {isOpen = false;mNowX = getMeasuredWidth() – mCloseDrawable.getIntrinsicWidth();postInvalidate();}}代码量不是很多,而且很清晰,下面我们就来分析分析几个方法。

三、代码分析

首先我们在第二个构造方法中,获取了两个Drawable,分别对应了开和关时的图片。

如果说对云南有进一步的了解的话就是鲜花。

使用Scroller制作滑块开关ToggleButton

相关文章:

你感兴趣的文章:

标签云: