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 ...
随机推荐
- [python 函数学习篇] 关键字参数
函数可以通过 关键字参数 的形式来调用,形如 keyword = value .例如,以下的函数: def parrot(voltage, state='a stiff', action='voom' ...
- acmer之ubuntu下安装Eclipse
ubuntu是acmer常用的系统,配置起CB还是比较简单的三行命令就OK了 //Current stable version of Code::Blocks IDE (16.01) //To ins ...
- Thinkphp5.1手册太简单,有的功能用起来不确定结果是否和预料的一样,顾整理记录
//模板{if false} 1 {else/} //====>可以使用 效果同 {else /} 2 {/if} {if condition="(1 eq 1) and false& ...
- Linux定时任务Crontab命令详解 转
linux 系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另 外, 由于使用者自己也可以设置计划任务,所 ...
- Multiset ------ 多重集合
Multiset的中文名是多重集合,其实就是集合的扩展版.唯一的不同是集合中一个值只能出现一次,而多重集合中一个值可以出现多次. 粗略看了看MSDN,在STL中,multiset和set的成员函数声明 ...
- STL学习笔记(七) 程序中使用STL
条款43:算法调用优先于手写循环 class Widget { public: bool test(); }; vector<Widget> vec; 算法调用: for_each(vec ...
- Codeforces 622C Not Equal on a Segment 【线段树 Or DP】
题目链接: http://codeforces.com/problemset/problem/622/C 题意: 给定序列,若干查询,每个查询给定区间和t,输出区间内任意一个不等于t的元素的位置. 分 ...
- Codeforces Educational Round 33 题解
题目链接 Codeforces Educational Round 33 Problem A 按照题目模拟,中间发现不对就直接输出NO. #include <bits/stdc++.h> ...
- [笔记][FPGA]如何使用SignalTap观察wire与reg值
0. 简介 在FPGA程序调试时,我们除了仿真还经常的会用到SignalTap进行板级调试,其可以真实有效的反应某些变量的变化,方便我们理解内在跳转,方便Debug的运行.SignalTap需要制定时 ...
- codevs——1814 最长链
1814 最长链 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 现给出一棵N个结点二叉树,问这棵二叉 ...