Android_自己定义切换控件SwitchView
1.示意图
![]()
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemltbzIwMTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="300" height="60" alt="">
2.自己定义控件SwitchView
public class SwitchView extends View {
public static final String TAG = SwitchView.class.getSimpleName();
// 状态
public static final int STATUS_OFF = 0;
public static final int STATUS_ON = 1;
public static final int STATUS_SCROLING = 2;
// 用于显示的文本
private String mOnText = "打开";
private String mOffText = "关闭";
private int mSwitchStatus = STATUS_OFF;
private boolean mHasScrolled = false;// 表示是否发生过滚动
private int mSrcX = 0, mDstX = 0;
private int mBmpWidth = 0;
private int mBmpHeight = 0;
private int mThumbWidth = 0;
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private OnSwitchChangedListener mOnSwitchChangedListener = null;
// 开关状态图
Bitmap mSwitch_off, mSwitch_on, mSwitch_thumb;
public SwitchView(Context context) {
this(context, null);
}
public SwitchView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SwitchView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
// 初始化三幅图片
private void init() {
Resources res = getResources();
mSwitch_off = BitmapFactory.decodeResource(res, R.drawable.bg_switch_off);
mSwitch_on = BitmapFactory.decodeResource(res, R.drawable.bg_switch_on);
mSwitch_thumb = BitmapFactory.decodeResource(res, R.drawable.switch_thumb);
mBmpWidth = mSwitch_on.getWidth();
mBmpHeight = mSwitch_on.getHeight();
mThumbWidth = mSwitch_thumb.getWidth();
}
@Override
public void setLayoutParams(LayoutParams params) {
params.width = mBmpWidth;
params.height = mBmpHeight;
super.setLayoutParams(params);
}
/**
* 设置监听器
*
*/
public void setOnSwitchChangedListener(OnSwitchChangedListener l) {
mOnSwitchChangedListener = l;
}
/**
* 设置文本
*/
public void setText(final String onText, final String offText) {
mOnText = onText;
mOffText = offText;
invalidate();
}
/**
* 设置开关的状态
*/
public void setStatus(boolean on) {
mSwitchStatus = (on ? STATUS_ON : STATUS_OFF);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mSrcX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
mDstX = Math.max((int) event.getX(), 10);
mDstX = Math.min(mDstX, 62);
if (mSrcX == mDstX)
return true;
mHasScrolled = true;
AnimationTransRunnable aTransRunnable = new AnimationTransRunnable(mSrcX, mDstX, 0);
new Thread(aTransRunnable).start();
mSrcX = mDstX;
break;
case MotionEvent.ACTION_UP:
if (mHasScrolled == false) {// 假设没有发生过滑动,就意味着这是一次单击过程
mSwitchStatus = Math.abs(mSwitchStatus - 1);
int xFrom = 10, xTo = 62;
if (mSwitchStatus == STATUS_OFF) {
xFrom = 62;
xTo = 10;
}
AnimationTransRunnable runnable = new AnimationTransRunnable(xFrom, xTo, 1);
new Thread(runnable).start();
} else {
invalidate();
mHasScrolled = false;
}
// 状态改变的时候 回调事件函数
if (mOnSwitchChangedListener != null) {
mOnSwitchChangedListener.onSwitchChanged(this, mSwitchStatus);
}
break;
default:
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 画图的时候 内部用到了一些数值的硬编码,事实上不太好,
// 主要是考虑到图片的原因,图片周围有透明边界,所以要有一定的偏移
// 硬编码的数值仅仅要看懂了代码,事实上能够理解其含义,能够做对应改进。
mPaint.setTextSize(14);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
if (mSwitchStatus == STATUS_OFF) {
drawBitmap(canvas, null, null, mSwitch_off);
drawBitmap(canvas, null, null, mSwitch_thumb);
mPaint.setColor(Color.rgb(105, 105, 105));
canvas.translate(mSwitch_thumb.getWidth(), 0);
canvas.drawText(mOffText, 0, 20, mPaint);
} else if (mSwitchStatus == STATUS_ON) {
drawBitmap(canvas, null, null, mSwitch_on);
int count = canvas.save();
canvas.translate(mSwitch_on.getWidth() - mSwitch_thumb.getWidth(), 0);
drawBitmap(canvas, null, null, mSwitch_thumb);
mPaint.setColor(Color.WHITE);
canvas.restoreToCount(count);
canvas.drawText(mOnText, 17, 20, mPaint);
} else { // SWITCH_SCROLING
mSwitchStatus = mDstX > 35 ? STATUS_ON : STATUS_OFF;
drawBitmap(canvas, new Rect(0, 0, mDstX, mBmpHeight), new Rect(0, 0, (int) mDstX, mBmpHeight), mSwitch_on);
mPaint.setColor(Color.WHITE);
canvas.drawText(mOnText, 17, 20, mPaint);
int count = canvas.save();
canvas.translate(mDstX, 0);
drawBitmap(canvas, new Rect(mDstX, 0, mBmpWidth, mBmpHeight),
new Rect(0, 0, mBmpWidth - mDstX, mBmpHeight), mSwitch_off);
canvas.restoreToCount(count);
count = canvas.save();
canvas.clipRect(mDstX, 0, mBmpWidth, mBmpHeight);
canvas.translate(mThumbWidth, 0);
mPaint.setColor(Color.rgb(105, 105, 105));
canvas.drawText(mOffText, 0, 20, mPaint);
canvas.restoreToCount(count);
count = canvas.save();
canvas.translate(mDstX - mThumbWidth / 2, 0);
drawBitmap(canvas, null, null, mSwitch_thumb);
canvas.restoreToCount(count);
}
}
public void drawBitmap(Canvas canvas, Rect src, Rect dst, Bitmap bitmap) {
dst = (dst == null ?
new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()) : dst);
Paint paint = new Paint();
canvas.drawBitmap(bitmap, src, dst, paint);
}
/**
* AnimationTransRunnable 做滑动动画所使用的线程
*/
private class AnimationTransRunnable implements Runnable {
private int srcX, dstX;
private int duration;
public AnimationTransRunnable(float srcX, float dstX, final int duration) {
this.srcX = (int) srcX;
this.dstX = (int) dstX;
this.duration = duration;
}
@Override
public void run() {
final int patch = (dstX > srcX ?
5 : -5);
if (duration == 0) {
SwitchView.this.mSwitchStatus = STATUS_SCROLING;
SwitchView.this.postInvalidate();
} else {
int x = srcX + patch;
while (Math.abs(x - dstX) > 5) {
mDstX = x;
SwitchView.this.mSwitchStatus = STATUS_SCROLING;
SwitchView.this.postInvalidate();
x += patch;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mDstX = dstX;
SwitchView.this.mSwitchStatus = mDstX > 35 ?
STATUS_ON : STATUS_OFF;
SwitchView.this.postInvalidate();
}
}
}
public static interface OnSwitchChangedListener {
public abstract void onSwitchChanged(SwitchView obj, int status);
}
}
3.源代码下载
Android_自己定义切换控件SwitchView的更多相关文章
- MUI框架-03-自定义MUI控件样式
MUI框架-03-自定义MUI控件样式 开发请查阅:官方文档:http://dev.dcloud.net.cn/mui/ui/ 如何自定义MUI控件样式 mui 以 iOS 7的 UI 为基础,补充了 ...
- Xamarin自定义布局系列——PivotPage,多页面切换控件
PivotPage ---- 多页面切换控件 PivotPage是一个多页面切换控件,类似安卓中的ViewPager和UWP中的Pivot枢轴控件. 起初打算直接通过ScrollView+StackL ...
- android:自己定义组合控件Weight(高仿猫眼底部菜单条)
在我们实际开发其中.会碰见一些布局结构类似或者同样的界面.比如应用的设置界面.tabbutton界面等. 这时候.对于刚開始学习的人来说,xml里面一个个绘制出来也许是最初的想法.可能随着经验的积累, ...
- Android 使用shape定义不同控件的的颜色、背景色、边框色
Android 使用shape定义不同控件的的颜色.背景色.边框色 设置按钮的右边框和底边框颜色为红色,边框大小为3dp: 在drawable新建一个 buttonstyle.xml的文件,内容如下: ...
- Quartz2D-二维画图引擎 、自己定义UI控件
// // MyDraw.m // 绘图 #import "MyDraw.h" @implementation MyDraw //Quartz2D 是一个二维绘图引擎 //自己定义 ...
- android 自己定义组合控件
自己定义控件是一些android程序猿感觉非常难攻破的难点,起码对我来说是这种,可是我们能够在网上找一些好的博客关于自己定义控件好好拿过来学习研究下,多练,多写点也能找到感觉,把一些原理弄懂,今天就讲 ...
- delphi Table切换控件顺序问题
delphi Table切换控件顺序问题 Tagorder的值就是确定Table键切换顺序的 以上做法只能解决同一类型的多个控件(如Edit1,edit2....)显示顺序问题 假如有不同类型的控件如 ...
- ImageSwitch图像切换控件
ImageSwitch图像切换控件 继承ViewAnimator所以可以做动画 继承ViewGroup所以可以装别的控件,所以ImageSwitch里面装的就是image,不过要找个ImageView ...
- android自己定义开关控件
近日在android项目要使用开关控件.可是android中自带的开关控件不太惬意,所以就打算通过自己定义View写一个开关控件 ios的开关控件当然就是我要仿照的目标. 先上图: waterma ...
随机推荐
- day03_11 if语句实现猜年龄01
老男孩猜年龄游戏 age_of_princal = 56 guess_age = int( input(">>:") ) #以下为伪代码 ''' if guess_ag ...
- 如何解决border的重叠问题
我现在在做一个ul列表,然后给每个li加上边框,但是加完了之后,相邻列表的边框就会变成2px,比如第一个li的下边框和第二个li的上边框就会重叠在一起,请问这有什么办法解决一下么? 解决方法是: 试试 ...
- verilog 实现中值滤波
图像信号在形成.传输和记录的过程中,由于成像系统.传输介质.工作环境和记录设备等的固有缺陷,不可避免地产生各种类型的噪声,降低了图像的质量,进而影响后续处理(如边缘检测.图像分割.特征提取.模式识别等 ...
- 九度oj 题目1083:特殊乘法 清华大学2010年机试题目
题目描述: 写个算法,对2个小于1000000000的输入,求结果. 特殊乘法举例:123 * 45 = 1*4 +1*5 +2*4 +2*5 +3*4+3*5 输入: 两个小于1000000000的 ...
- 【bzoj4407】于神之怒加强版 莫比乌斯反演+线性筛
题目描述 给下N,M,K.求 输入 输入有多组数据,输入数据的第一行两个正整数T,K,代表有T组数据,K的意义如上所示,下面第二行到第T+1行,每行为两个正整数N,M,其意义如上式所示. 输出 如题 ...
- Agile工作方法
[工具] Slack https://slack.com/ 看板 https://trello.com/ 其他TBC
- MGW——美团点评高性能四层负载均衡
转自美团点评技术博客:https://tech.meituan.com/MGW.html 前言 在高速发展的移动互联网时代,负载均衡有着举足轻重的地位,它是应用流量的入口,对应用的可靠性和性能起着决定 ...
- 【bzoj4596】[Shoi2016]黑暗前的幻想乡 (矩阵树定理+容斥)
Description 四年一度的幻想乡大选开始了,最近幻想乡最大的问题是很多来历不明的妖怪涌入了幻想乡,扰乱了幻想乡昔日的秩序.但是幻想乡的建制派妖怪(人类)博丽灵梦和八云紫等人整日高谈所有妖怪平等 ...
- 22深入理解C指针之---通过指针传递函数
一.通过指针传递函数与通过指针传递数据的本质是一样的,区别就是此时的数据是函数指针(函数的开始的地址) 1.定义:通过函数指针将函数传入函数:通过函数返回函数指针实现函数返回函数的目标 2.特征: 1 ...
- PHPCMS内链设置,PHPCMS关联链接设置
需求: 在网站中的关键词,自动加上链接. 在PHPCMS中叫做“关联链接”,在DEDECMS中叫做TAG标签. 第1步:后台 -> 扩展 -> 关联链接 -> 添加关联链接: 第2步 ...