简单好用的小控件 ------UISwitchButton

效果图:

使用方法:

1.将下面这段代码copy过去

package cc.android.supu.view;

import cc.android.supu.R;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewParent;
import android.widget.CheckBox;

public class UISwitchButton extends CheckBox {
    private Paint mPaint;
    private RectF mSaveLayerRectF;
    private float mFirstDownY;
    private float mFirstDownX;
    private int mClickTimeout;
    private int mTouchSlop;
    private final int MAX_ALPHA = 255;
    private int mAlpha = MAX_ALPHA;
    private boolean mChecked = true;
    private boolean mBroadcasting;// 标示是否正在执行监听事件中
    private boolean mTurningOn;// 标示位置是否达到开启状态
    private PerformClick mPerformClick;
    private OnCheckedChangeListener mOnCheckedChangeListener;
    private OnCheckedChangeListener mOnCheckedChangeWidgetListener;
    private boolean mAnimating;// 标示是否继续执行移动动画
    private final float VELOCITY = 350;// 定义按钮动画移动的最大长度
    private float mVelocity;// 按钮动画移动的最大像素长度
    private float mAnimationPosition;// 按钮动画移动的当前位置
    private float mAnimatedVelocity;// 按钮动画移动的实际位移(+mVelocity/-mVelocity)
    private Bitmap bmBgGreen;// 绿色背景
    private Bitmap bmBgWhite;// 白色背景
    private Bitmap bmBtnNormal;// 未按下时按钮
    private Bitmap bmBtnPressed;// 按下时按钮
    private Bitmap bmCurBtnPic;// 当前显示的按钮图片
    private Bitmap bmCurBgPic;// 当前背景图片
    private float bgWidth;// 背景宽度
    private float bgHeight;// 背景宽度
    private float btnWidth;// 按钮宽度
    private float offBtnPos;// 按钮关闭时位置
    private float onBtnPos;// 按钮开启时位置
    private float curBtnPos;// 按钮当前位置
    private float startBtnPos;// 开始按钮位置
    private final int COMMON_WIDTH_IN_PIXEL = 82;// 默认宽度
    private final int COMMON_HEIGHT_IN_PIXEL = 50;// 默认高度

    public UISwitchButton(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.checkboxStyle);
    }

    public UISwitchButton(Context context) {
        this(context, null);
    }

    public UISwitchButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        mPaint = new Paint();
        mPaint.setColor(Color.WHITE);
        Resources resources = context.getResources();

        // get attrConfiguration
        TypedArray array = context.obtainStyledAttributes(attrs,
                R.styleable.SwitchButton);
        int width = (int) array.getDimensionPixelSize(
                R.styleable.SwitchButton_bmWidth, 0);
        int height = (int) array.getDimensionPixelSize(
                R.styleable.SwitchButton_bmHeight, 0);
        array.recycle();

        // size width or height
        if (width <= 0 || height <= 0) {
            width = COMMON_WIDTH_IN_PIXEL;
            height = COMMON_HEIGHT_IN_PIXEL;
        } else {
            float scale = (float) COMMON_WIDTH_IN_PIXEL
                    / COMMON_HEIGHT_IN_PIXEL;
            if ((float) width / height > scale) {
                width = (int) (height * scale);
            } else if ((float) width / height < scale) {
                height = (int) (width / scale);
            }
        }

        // get viewConfiguration
        mClickTimeout = ViewConfiguration.getPressedStateDuration()
                + ViewConfiguration.getTapTimeout();
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

        // get Bitmap
        bmBgGreen = BitmapFactory.decodeResource(resources,
                R.drawable.switch_btn_bg_green);
        bmBgWhite = BitmapFactory.decodeResource(resources,
                R.drawable.switch_btn_bg_white);
        bmBtnNormal = BitmapFactory.decodeResource(resources,
                R.drawable.switch_btn_normal);
        bmBtnPressed = BitmapFactory.decodeResource(resources,
                R.drawable.switch_btn_pressed);

        // size Bitmap
        bmBgGreen = Bitmap.createScaledBitmap(bmBgGreen, width, height, true);
        bmBgWhite = Bitmap.createScaledBitmap(bmBgWhite, width, height, true);
        bmBtnNormal = Bitmap.createScaledBitmap(bmBtnNormal, height, height,
                true);
        bmBtnPressed = Bitmap.createScaledBitmap(bmBtnPressed, height, height,
                true);

        bmCurBtnPic = bmBtnNormal;// 初始按钮图片
        bmCurBgPic = mChecked ? bmBgGreen : bmBgWhite;// 初始背景图片
        bgWidth = bmBgGreen.getWidth();// 背景宽度
        bgHeight = bmBgGreen.getHeight();// 背景高度
        btnWidth = bmBtnNormal.getWidth();// 按钮宽度
        offBtnPos = 0;// 关闭时在最左边
        onBtnPos = bgWidth - btnWidth;// 开始时在右边
        curBtnPos = mChecked ? onBtnPos : offBtnPos;// 按钮当前为初始位置

        // get density
        float density = resources.getDisplayMetrics().density;
        mVelocity = (int) (VELOCITY * density + 0.5f);// 动画距离
        mSaveLayerRectF = new RectF(0, 0, bgWidth, bgHeight);
    }

    @Override
    public void setEnabled(boolean enabled) {
        mAlpha = enabled ? MAX_ALPHA : MAX_ALPHA / 3;
        super.setEnabled(enabled);
    }

    public boolean isChecked() {
        return mChecked;
    }

    public void toggle() {
        setChecked(!mChecked);
    }

    private void setCheckedDelayed(final boolean checked) {
        postDelayed(new Runnable() {
            @Override
            public void run() {
                setChecked(checked);
            }
        }, 10);
    }

    public void setChecked(boolean checked) {
        if (mChecked != checked) {
            mChecked = checked;

            // 初始化按钮位置
            curBtnPos = checked ? onBtnPos : offBtnPos;
            // 改变背景图片
            bmCurBgPic = checked ? bmBgGreen : bmBgWhite;
            invalidate();

            if (mBroadcasting) {
                // NO-OP
                return;
            }
            // 正在执行监听事件
            mBroadcasting = true;
            if (mOnCheckedChangeListener != null) {
                mOnCheckedChangeListener.onCheckedChanged(UISwitchButton.this,
                        mChecked);
            }
            if (mOnCheckedChangeWidgetListener != null) {
                mOnCheckedChangeWidgetListener.onCheckedChanged(
                        UISwitchButton.this, mChecked);
            }
            // 监听事件结束
            mBroadcasting = false;
        }
    }

    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        mOnCheckedChangeListener = listener;
    }

    void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) {
        mOnCheckedChangeWidgetListener = listener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        float x = event.getX();
        float y = event.getY();
        float deltaX = Math.abs(x - mFirstDownX);
        float deltaY = Math.abs(y - mFirstDownY);
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            ViewParent mParent = getParent();
            if (mParent != null) {
                // 通知父控件不要拦截本view的触摸事件
                mParent.requestDisallowInterceptTouchEvent(true);
            }
            mFirstDownX = x;
            mFirstDownY = y;
            bmCurBtnPic = bmBtnPressed;
            startBtnPos = mChecked ? onBtnPos : offBtnPos;
            break;
        case MotionEvent.ACTION_MOVE:
            float time = event.getEventTime() - event.getDownTime();
            curBtnPos = startBtnPos + event.getX() - mFirstDownX;
            if (curBtnPos >= onBtnPos) {
                curBtnPos = onBtnPos;
            }
            if (curBtnPos <= offBtnPos) {
                curBtnPos = offBtnPos;
            }
            mTurningOn = curBtnPos > bgWidth / 2 - btnWidth / 2;
            break;
        case MotionEvent.ACTION_UP:
            bmCurBtnPic = bmBtnNormal;
            time = event.getEventTime() - event.getDownTime();
            if (deltaY < mTouchSlop && deltaX < mTouchSlop
                    && time < mClickTimeout) {
                if (mPerformClick == null) {
                    mPerformClick = new PerformClick();
                }
                if (!post(mPerformClick)) {
                    performClick();
                }
            } else {
                startAnimation(mTurningOn);
            }
            break;
        }
        invalidate();
        return isEnabled();
    }

    private class PerformClick implements Runnable {
        public void run() {
            performClick();
        }
    }

    @Override
    public boolean performClick() {
        startAnimation(!mChecked);
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.saveLayerAlpha(mSaveLayerRectF, mAlpha, 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(bmCurBgPic, 0, 0, mPaint);

        // 绘制按钮
        canvas.drawBitmap(bmCurBtnPic, curBtnPos, 0, mPaint);

        canvas.restore();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension((int) bgWidth, (int) bgHeight);
    }

    private void startAnimation(boolean turnOn) {
        mAnimating = true;
        mAnimatedVelocity = turnOn ? mVelocity : -mVelocity;
        mAnimationPosition = curBtnPos;
        new SwitchAnimation().run();
    }

    private void stopAnimation() {
        mAnimating = false;
    }

    private final class SwitchAnimation implements Runnable {
        @Override
        public void run() {
            if (!mAnimating) {
                return;
            }
            doAnimation();
            requestAnimationFrame(this);
        }
    }

    private void doAnimation() {
        mAnimationPosition += mAnimatedVelocity * ANIMATION_FRAME_DURATION
                / 1000;
        if (mAnimationPosition <= offBtnPos) {
            stopAnimation();
            mAnimationPosition = offBtnPos;
            setCheckedDelayed(false);
        } else if (mAnimationPosition >= onBtnPos) {
            stopAnimation();
            mAnimationPosition = onBtnPos;
            setCheckedDelayed(true);
        }
        curBtnPos = mAnimationPosition;
        invalidate();
    }

    private static final int MSG_ANIMATE = 1000;
    public static final int ANIMATION_FRAME_DURATION = 1000 / 60;

    public void requestAnimationFrame(Runnable runnable) {
        Message message = new Message();
        message.what = MSG_ANIMATE;
        message.obj = runnable;
        mHandler.sendMessageDelayed(message, ANIMATION_FRAME_DURATION);
    }

    private Handler mHandler = new Handler() {
        public void handleMessage(Message m) {
            switch (m.what) {
            case MSG_ANIMATE:
                if (m.obj != null) {
                    ((Runnable) m.obj).run();
                }
                break;
            }
        }
    };
}

2.将这段属性文件代码copy到attr.xml文件下:(没有的话自己在values文件夹下新建)

<!--switchButton 的相关属性start-->
<resources>
    <declare-styleable name="SwitchButton">
        <attr name="bmWidth" format="dimension"></attr>
        <attr name="bmHeight" format="dimension"></attr>
    </declare-styleable>
    </resources>
    <!--switchButton 的相关属性end-->

3.

下载下面的这几张图片,放到drawable文件夹下:

http://download.csdn.net/detail/fangchao3652/8469245

4.在layout.xml中直接使用即可,如下:

  <RelativeLayout
                android:id="@+id/setting_open_send"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/default_margin_mid"
                android:layout_marginRight="@dimen/default_margin_mid"
                android:background="@drawable/function_item_bg"
                android:clickable="true"
                android:paddingRight="@dimen/default_margin_big">

                <cc.android.fc.view.UISwitchButton
                    android:id="@+id/switch_open_send"
                    android:layout_width="32dp"
                    android:layout_height="15dp"

                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                  />

            </RelativeLayout>
时间: 2024-10-10 16:52:54

简单好用的小控件 ------UISwitchButton的相关文章

简单好用的小控件------自定义checkbox

1.首先在drawable文件夹中添加drawable文件checkbox_style.xml. [html] view plaincopy <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@

如何在Android实现桌面清理内存简单Widget小控件

如何在Android实现桌面清理内存简单Widget小控件 我们经常会看到类似于360.金山手机卫士一类的软件会带一个widget小控件,显示在桌面上,上面会显示现有内存大小,然后会带一个按键功能来一键清理内存,杀死后台进程的功能,那么这个功能是如何实现的呢,我们今天也来尝试做一个类似的功能的小控件. 效果图: 一.UI部分的编写: 参照Google的文档,首先在建立一个类继承AppWidgetProvider import android.appwidget.AppWidgetProvider

javascript翻页小控件paginator

$(container).paginator({  totalrecords : totalRecords,  recordsperpage : recordsPerpage,  pagebtncount : pageBtnCount,  initval : currentPage,  next : '次へ',  prev : '前へ',  first : '',  last : '',  theme : '',  controlsalways : false,  onchange : func

Android UI设计之&lt;十一&gt;自定义ViewGroup,打造通用的关闭键盘小控件ImeObserverLayout

转载请注明出处:http://blog.csdn.net/llew2011/article/details/51598682 我们平时开发中总会遇见一些奇葩的需求,为了实现这些需求我们往往绞尽脑汁有时候还茶不思饭不香的,有点夸张了(*^__^*)--我印象最深的一个需求是在一段文字中对部分词语进行加粗显示.当时费了不少劲,不过还好,这个问题最终解决了,有兴趣的童靴可以看一下:Android UI设计之<六>使用HTML标签,实现在TextView中对部分文字进行加粗显示. 之前产品那边提了这样

android中常用的小控件------Widgets的使用

好久没有写博客了,都不知博客怎么写了,最近突然想写博客,以帮助更多的人,却又不知道写什么好呢? 好吧  我承认我有点懒惰了,可是程序猿是不应该懒惰的哦,俺要做个好孩子. 好了言归正传,开始介绍下今天的主要内容吧! Widgets一个桌面的小控件    个人认为是很常用的,不知道大神们是不是这么觉得的呢?比如说你开发的一款音乐播放器的软件,可把基本的上一曲和下一曲.暂停的几个功能放在这个小控件里面将它显示在桌面上来,这样就很方便啦,你想要下一曲.上一曲.暂停播放的时候,就不用再打开播放器了,而是直

等级显示小控件

等级控件效果图: 实现方式: 自定义小控件,通过frame来获取它的坐标,然后通过富文本的方式来实现不同文字,由于文字粗体和斜体要同时使用,所以通过富文本实现比较方便: 声明文件: 其中有两个方法,一个是初始化,一个是改变等级需要调用的方法: #import <UIKit/UIKit.h> @interface IDSLevelconView : UIImageView @property (nonatomic, strong) UILabel *levelabel; - (instancet

桌面小控件的实例-----数字时钟

为了实现一个数字时钟的桌面组件,开发者需要在程序界面上定义8个ImageView,其中6个ImageView用于显示小时.分钟.秒钟的数字,另外两个ImageView用于显示小时.分钟.秒钟之间的冒号. 为了让桌面组件实时的显示当前时间,程序需要每个1秒更新一次程序界面上的6个ImageView,让它们显示当前小时.分钟.秒钟的数字即可. import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;

UI各种小控件的使用方法

今天给大家列举出来UI中的一些小控件的使用方法,方便大的学习与使用 一些方法和属性我们可以查看API文档,不必将每个控件的功能都记住, 因为在使用的过程中,我们可以查看API文档,方便使用,我们只要记住常见的一些方法 这里列举几个例子,其他的还要靠自己在下面学习 1.分段控制器 // // UISegmentedControl.h // UIKit // // Copyright (c) 2005-2014 Apple Inc. All rights reserved. // #import <

mac下dashboard小控件开发实例(附源码)

1.背景 用mac的用户都应该知道,mac有一个很好的功能,就是dashboard小控件的功能,按下F12键就可以自由切换.博主最近在背GRE单词,就尝试这开发了一个背单词的dashboard小控件.效果如图 2.步骤 (1)安转dashcode 这个是开发工具,用起来有点像xcode, 下载地址:https://developer.apple.com/downloads/index.action (2)打开dashcode,新建项目 打开右上角的资源库,可以随意拖拉控件在里面.然后右键需要添加