近期心血来潮,写了一个自己定义仿iPhone的开关。

有须要的同学能够来下载啦。支持点击自己主动滚动,速率能够自己依据须要改动。触摸滚动,大小自己定义,支持改动样式。就不录制动画,就上传了两张图给大家看看。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHVhbmd5YW5iaW4xMjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="320" height="640" alt="">
      

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHVhbmd5YW5iaW4xMjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="320" height="640" alt="">

主要代码:

package com.example.switchbutton;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration; public class SwitchButton extends View { public static final int DEFAULT_WIDTH = 100;
public static final int DEFAULT_HEIGTH = 45;
public static final int PER_POST_TIME = 20;
public static final int CLICK = 0;
public static final int LEFT = 1;
public static final int RIGHT = 2; private int mSelectBg;
private int mUnSelectBg;
private int mBorderColor;
private int mSelectCirlceColor;
private int mUnSelectCircleColor;
private boolean isChecked;
private Paint mPaint;
private int mWidth;
private int mHeight;
private int mClickTimeout;
private int mTouchSlop;
private float mAnimMove;
private final float VELOCITY = 350;
private float firstDownX;
private float firstDownY;
private float lastDownX;
private int mCriclePostion;
private int mStartCriclePos;
private int mEndCirclePos;
private boolean isScroll;
private int status;
private Handler mHander;
private AnimRunnable mAnim; private OnCheckChangeListener mOnCheckChangeListener; public interface OnCheckChangeListener { void OnCheck(SwitchButton switchButton,boolean isChecked);
} public SwitchButton(Context context, AttributeSet attrs) {
super(context, attrs);
Resources res = getResources();
int defaultSelectBg = res.getColor(R.color.default_switch_button_select_bg);
int defaultUnSelectBg = res.getColor(R.color.default_switch_button_unselect_bg);
int defaultBorderColor = res.getColor(R.color.default_switch_button_border_color);
int defaultSelectCircleColor = res.getColor(R.color.default_switch_button_select_color);
int defaultUnSelectCircleColor = res.getColor(R.color.default_switch_button_unselect_color);
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.SwitchButton);
mSelectBg = a.getColor(R.styleable.SwitchButton_select_bg, defaultSelectBg);
mUnSelectBg = a.getColor(R.styleable.SwitchButton_unselect_bg, defaultUnSelectBg);
mBorderColor = a.getColor(R.styleable.SwitchButton_select_border_color, defaultBorderColor);
mSelectCirlceColor = a.getColor(R.styleable.SwitchButton_select_cricle_color, defaultSelectCircleColor);
mUnSelectCircleColor = a.getColor(R.styleable.SwitchButton_unselect_cricle_color, defaultUnSelectCircleColor);
isChecked = a.getBoolean(R.styleable.SwitchButton_isChecked,false);
a.recycle();
initView(context);
} private void initView(Context context) { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
final float density = getResources().getDisplayMetrics().density;
mAnimMove = (int) (VELOCITY * density + 0.5f) / 150; //自己主动滚动速度
mClickTimeout = ViewConfiguration.getPressedStateDuration()
+ ViewConfiguration.getTapTimeout(); //点击时间
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();//触摸滚动Slop
mHander = new Handler();
mAnim = new AnimRunnable();
} @SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); mPaint.setColor(mBorderColor);
mPaint.setStyle(Paint.Style.STROKE);
RectF rect = new RectF(0, 0, mWidth, mHeight);
canvas.drawRoundRect(rect, mHeight/2, mHeight/2, mPaint);
mPaint.setColor(isChecked ? mSelectBg :mUnSelectBg);
RectF innerRect = new RectF(1, 1, mWidth -1, mHeight -1);
canvas.drawRoundRect(innerRect, mHeight/2 -1, mHeight/2 -1, mPaint);
mPaint.setColor(isChecked ? mSelectCirlceColor : mUnSelectCircleColor);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(mCriclePostion, mHeight/2, mHeight/2 -1, mPaint);
} @Override
public boolean onTouchEvent(MotionEvent event) { float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(isScroll){
return false;
}
firstDownX = x;
firstDownY = y;
lastDownX = x;
mCriclePostion = isChecked ? mEndCirclePos : mStartCriclePos;
break;
case MotionEvent.ACTION_MOVE:
float delaX = x - lastDownX;
setCriclePositon(delaX);
lastDownX = x;
invalidate();
break;
case MotionEvent.ACTION_UP:
float totalX = x - firstDownX;
float totalY = y - firstDownY;
float time = event.getEventTime() - event.getDownTime();
if(totalX < mTouchSlop && totalY <mTouchSlop && time < mClickTimeout){
status = CLICK;
startAutoScroll();
}else{
delaX = x - lastDownX;
setCriclePositon(delaX);
status = mCriclePostion < mWidth / 2 ? LEFT :RIGHT;
startAutoScroll();
}
break;
}
return true;
} //開始自己主动滚动
private void startAutoScroll(){ isScroll = true;
mHander.postDelayed(mAnim, PER_POST_TIME); } class AnimRunnable implements Runnable{ @Override
public void run() { mHander.postDelayed(this, PER_POST_TIME);
moveView();
}
//移动
private void moveView() { if((status == CLICK && isChecked) || status == LEFT){
mCriclePostion -= mAnimMove;
if(mCriclePostion < mHeight /2){
mCriclePostion = mHeight/2;
stopView(false);
}
}else if((status == CLICK && !isChecked) || status == RIGHT) { mCriclePostion += mAnimMove;
if(mCriclePostion > mWidth -mHeight /2){
mCriclePostion = mWidth -mHeight /2;
stopView(true);
}
}
invalidate(); }
//停止移动View
private void stopView(boolean endChecked) { mHander.removeCallbacks(mAnim);
isScroll = false;
isChecked = endChecked;
//回调监听事件
if(mOnCheckChangeListener != null){
mOnCheckChangeListener.OnCheck(SwitchButton.this, isChecked);
}
} } //设置圆心的位置
private synchronized void setCriclePositon(float delaX){ int pos = (int) (mCriclePostion + delaX);
if(pos < mHeight / 2){
mCriclePostion = mHeight / 2;
}else if(pos > mWidth - mHeight /2){
mCriclePostion = mWidth - mHeight /2;
}else{
mCriclePostion = pos;
}
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if(widthMode == MeasureSpec.UNSPECIFIED || widthMode == MeasureSpec.AT_MOST){
mWidth = DEFAULT_WIDTH;
}else{
mWidth = MeasureSpec.getSize(widthMeasureSpec);
}
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if(heightMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.AT_MOST){
mHeight = DEFAULT_HEIGTH;
}else{
mHeight = MeasureSpec.getSize(heightMeasureSpec);
}
mStartCriclePos = mHeight / 2;
mEndCirclePos = mWidth - mHeight /2;
mCriclePostion = isChecked ? mEndCirclePos :mStartCriclePos;
setMeasuredDimension(mWidth, mHeight);
} public boolean isChecked() {
return isChecked;
} public void setChecked(boolean isChecked) { this.isChecked = isChecked;
invalidate();
} public void setOnCheckChangeListener(OnCheckChangeListener onCheckChangeListener) { this.mOnCheckChangeListener = onCheckChangeListener;
} }

attrs:

<?

xml version="1.0" encoding="utf-8"?

>
<resources>
<declare-styleable name="SwitchButton">
<attr name="select_bg" format="color"/>
<attr name="unselect_bg" format="color"/>
<attr name="select_border_color" format="color"/>
<attr name="select_cricle_color" format="color"/>
<attr name="unselect_cricle_color" format="color"/>
<attr name="isChecked" format="boolean"></attr>
</declare-styleable>
</resources>

下载地址:http://download.csdn.net/detail/huangyanbin123/8173521

android 自己定义开关(SwitchButton)的更多相关文章

  1. android自己定义开关控件

    近日在android项目要使用开关控件.可是android中自带的开关控件不太惬意,所以就打算通过自己定义View写一个开关控件 ios的开关控件当然就是我要仿照的目标. 先上图:   waterma ...

  2. Android自己定义控件系列三:自己定义开关button(二)

    接上一篇自己定义开关button(一)的内容继续.上一次实现了一个开关button的基本功能.即自己定义了一个控件.开关button,实现了点击切换开关状态的功能.今天我们想在此基础之上.进一步实现触 ...

  3. Android自己定义控件系列五:自己定义绚丽水波纹效果

    尊重原创!转载请注明出处:http://blog.csdn.net/cyp331203/article/details/41114551 今天我们来利用Android自己定义控件实现一个比較有趣的效果 ...

  4. Android-自定义开关(升级版)

    效果图: 定义一个类,取名为MySwitch.java,此类去继承View,为何是继承View而不是去继承ViewGroup呢,是因为自定义开关没有子控件,之需要操作自身绘制即可 package cu ...

  5. Android自己定义DataTimePicker(日期选择器)

    Android自己定义DataTimePicker(日期选择器)  笔者有一段时间没有发表关于Android的文章了,关于Android自己定义组件笔者有好几篇想跟大家分享的,后期会记录在博客中.本篇 ...

  6. Android UI--自定义ListView(实现下拉刷新+加载更多)

    Android UI--自定义ListView(实现下拉刷新+加载更多) 关于实现ListView下拉刷新和加载更多的实现,我想网上一搜就一堆.不过我就没发现比较实用的,要不就是实现起来太复杂,要不就 ...

  7. Android自己定义组件系列【7】——进阶实践(4)

    上一篇<Android自己定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识.这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpa ...

  8. ANDROID自己定义视图——onLayout源代码 流程 思路具体解释

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 简单介绍: 在自己定义view的时候.事实上非常easy.仅仅须要知道3步骤: 1.測量- ...

  9. Android 自己定义View (二) 进阶

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自己定义View之旅.前面已经介绍过一个自己定义View的基础 ...

随机推荐

  1. 微凉大大,教你一步一步在linux中正确的安装Xcache加速php。

    首先,强烈吐槽,百度上的教程,都左复制右复制的,乱七八糟,缺东缺西的.借此微凉大大我提供我苦心整理好的教程.以便各位小菜能顺利的使用Xcache加速php,假设看完了,也操作了,还是失败了的话,请联系 ...

  2. CRectTracker类的使用--橡皮筋窗口

    CRectTracker(俗称“橡皮筋”类)是一个非常有意思的类.你在Windows中经常看到这样的情况:它可以用做显示边界,你也可以扽它的八个角用来放大缩小,或做框选使用.如何通过编程来实现这种功能 ...

  3. 两道二分coming~

    第一道:poj 1905Expanding Rods 题意:两道墙(距离L)之间架一根棒子,棒子受热会变长,弯曲,长度变化满足公式( s=(1+n*C)*L),求的是弯曲的高度h. 首先来看这个图: ...

  4. UI编辑器

    本篇教程通过制作捕鱼达人的启动界面来说明CocoStudio UI编辑器的用法.先看看效果图 好了,下面一步一步的动手做吧! 1.打开软件 2.新建项目 依次打开软件主界面左上角菜单栏的:“文件”-- ...

  5. meminfo,df,

    yx100:root@yxRouter:/# cat /proc/meminfoMemTotal:         126584 kBMemFree:          103156 kBBuffer ...

  6. HP-UX查看版本

    首先采用uname -a查看服务器类型 $ uname -a    HP-UX WEBDB1 B.11.31 U ia64 0749665296 unlimited-user license 服务器的 ...

  7. ListView数据动态刷新

    在Android开发中用到ListView时,经常遇到要更改ListView内容的情形,比如删除或增加ListView中显示的条目,这里给大家提供一下思路:不论ListView要显示的对象是什么(如: ...

  8. Delphi结构中使用String时遇到的内存泄露问题(没有利用String的引用计数自动销毁字符串的功能)

    先定义一个结构: TUserInfo = record  UserID: Integer; // 用户编号  UserName: string; // 用户名end; 然后编写如下代码: proced ...

  9. jsp 中对jar 包的引用

    <%@ page language="java" import="你需要的带包名的类" pageEncoding="gb2312"%& ...

  10. C++ 11 右值引用以及std::move

    转载请注明出处:http://blog.csdn.net/luotuo44/article/details/46779063 新类型: int和int&是什么?都是类型.int是整数类型,in ...