Android-自定义可滑动开关控件之SlidingSwitchView
2015-11-16 15:33
393 查看
首先上两张蹩脚的效果图:
效果:可以点击切换,也可以拖动切换
先上代码:
[html]
view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<com.example.slidingswitchview.slideswitch.SlidingSwitchView
android:id="@+id/swithview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
1,初始化部分:
[java]
view plaincopy
private Bitmap mSwitch_on, mSwitch_off, mTthumb;
private Paint mPaint;
private int viewWidth, viewHeigth, thumbWidthHalf, thumbWidth;
//记录上一次点击的X坐标和当前的X坐标
private int mLastX, mCurrentX;
// 是否滑动
private boolean isScrolling = false;
// 开关所在的方向,左or右
private boolean isSwitchLeft = false;
// 是否是移动状态
private boolean isMoving = false;
//是否移动过,如果为false代表是单机时间
private boolean hasMoving = false;
private int mMoveDistance = 0;
private int mMoveX = 0;
private FontMetrics mFontMetrics;
private float mTextX, mTextY;
private String mOnText = "on";
private String mOffText = "off";
// 0:静止、1:向左、2:向右
private int mScrollingStatus = 0;
private static final float GESTURE_THRESHOLD_DIP = 10.0f;
final float scale = getContext().getResources().getDisplayMetrics().density;
private IOnSwitchChangerListener mChangerListener = null;
public SlidingSwitchView(Context context, AttributeSet attrs) {
super(context, attrs);
initBitmapResource();
initConstant();
initPaint();
initFontMetrics();
}
private void initConstant() {
viewWidth = mSwitch_on.getWidth() + getPaddingLeft() + getPaddingRight();
viewHeigth = mSwitch_on.getHeight() + getPaddingTop() + getPaddingBottom();
thumbWidth = mTthumb.getWidth();
thumbWidthHalf = thumbWidth / 2;
if (isSwitchLeft) {
mMoveDistance = 0;
} else {
mMoveDistance = viewWidth - thumbWidthHalf;
}
mScrollingStatus = 0;
}
private void initBitmapResource() {
mSwitch_on = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.on);
mSwitch_off = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.off);
mTthumb = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.thumb);
}
private void initPaint() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
private void initFontMetrics() {
// viewWidth: 155,
// viewHeigth: 61
// ascent: -11.1328125
// top: -12.673828
// bottom: 3.2519531 ,
// descent: 2.9296875 ,
// leading: 0.0 ,
mPaint.setTextSize(getTextSize(GESTURE_THRESHOLD_DIP));
mFontMetrics = mPaint.getFontMetrics();
mTextX = (viewWidth >> 1) - (int) (mPaint.measureText(mOnText)) >> 1;
// baseline位置字体下基准线位置
// mTextY代表baseline的位置 字体高度为:(mFontMetrics.descent -
// mFontMetrics.ascent) / 2
// 字体上下居中的推到公式为:控件高度/2 + 字体高度/2 -
// mFontMetrics.bottom(注:bottom的高度通常情况下比较小)
mTextY = ((mFontMetrics.descent - mFontMetrics.ascent) / 2 - mFontMetrics.bottom) + viewHeigth / 2;
}
注:initFontMetrics()方法是在是因为没有现成的图,就手动把文字写上去
2,绘制部分:
重写onDraw方法完成绘制,分3种情况:1、手指移动状态:isMoveing 2、控件处于滑动状态:isScrolling 3、初始化状态 。 其中isScrolling状态分为手指滑动过和未滑动过(也视为单击状态)两种情况。通过mMoveDistance和mCurrentX判断如何绘制。
重写onTouchEvent方法,ACTION_UP中hasMoving判断此次点击是不是单击事件。
[java]
view plaincopy
@Override
protected void onDraw(Canvas canvas) {
if (isMoving) {
if (mMoveDistance <= 0) {
drawbitmap(canvas, 0, 0);
} else if (mMoveDistance >= viewWidth - thumbWidth) {
drawbitmap(canvas, viewWidth - thumbWidthHalf, viewWidth - thumbWidth);
} else {
drawbitmap(canvas, mMoveDistance + thumbWidthHalf, mMoveDistance);
}
} else if (isScrolling) {
drawbitmap(canvas, mMoveDistance + thumbWidthHalf, mMoveDistance);
// 点击向右滑动
if (mCurrentX > viewWidth / 2 && mScrollingStatus == 2) {
mMoveDistance = mMoveDistance + SCROLLING_OFFSET;
}
// 点击向左滑动
else if (mCurrentX <= viewWidth / 2 && mScrollingStatus == 1) {
mMoveDistance = mMoveDistance - SCROLLING_OFFSET;
} else
// MOVE向右滑动
if (mMoveDistance + thumbWidthHalf > viewWidth / 2) {
mMoveDistance = mMoveDistance + SCROLLING_OFFSET;
}
// MOVE向左滑动
else {
mMoveDistance = mMoveDistance - SCROLLING_OFFSET;
}
refreshState();
} else {
// 初始化状态 这个应该跟外部关联
drawbitmap(canvas, mMoveDistance, mMoveDistance == 0 ? 0 : viewWidth - thumbWidth);
mLastX = 0;
mCurrentX = 0;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isScrolling) {
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
isMoving = true;
hasMoving = true;
mCurrentX = (int) event.getX();
mMoveX = mCurrentX - mLastX;
mLastX = mCurrentX;
mMoveDistance = mMoveDistance + mMoveX;
postInvalidate();
break;
case MotionEvent.ACTION_UP:
isMoving = false;
mCurrentX = (int) event.getX();
if (!hasMoving) {
if (mCurrentX < viewWidth / 2 && !isSwitchLeft) {
mMoveDistance = viewWidth - thumbWidth - SCROLLING_OFFSET;
mScrollingStatus = 1;
} else if (mCurrentX >= viewWidth / 2 && isSwitchLeft) {
mMoveDistance = mMoveDistance + SCROLLING_OFFSET;
mScrollingStatus = 2;
}
hasMoving = false;
}
refreshState();
break;
default:
break;
}
return true;
}
private void refreshState() {
if (mScrollingStatus != 0 && (viewWidth - thumbWidth > mMoveDistance && mMoveDistance > 0)) {
isScrolling = true;
} else {
if (mMoveDistance <= 0) {
relaseConstant();
mMoveDistance = 0;
isSwitchLeft = true;
if (mChangerListener != null) {
mChangerListener.onSwitchChanger(this, isSwitchLeft);
}
} else if (mMoveDistance >= viewWidth - thumbWidth) {
relaseConstant();
mMoveDistance = viewWidth - thumbWidthHalf;
isSwitchLeft = false;
if (mChangerListener != null) {
mChangerListener.onSwitchChanger(this, isSwitchLeft);
}
} else {
isScrolling = true;
}
}
postInvalidate();
}
private void relaseConstant() {
isMoving = false;
isScrolling = false;
hasMoving = false;
mScrollingStatus = 0;
}
/**
* 绘制按钮
*
* @param canvas
* @param mDistance
* @param mTthumb_to_left
*/
private void drawbitmap(Canvas canvas, int mDistance, int mTthumb_to_left) {
canvas.drawBitmap(mSwitch_on, new Rect(0, 0, mDistance, viewHeigth), new Rect(0, 0, mDistance, viewHeigth), mPaint);
mPaint.setColor(Color.WHITE);
canvas.drawText(mOnText, getTextSize(GESTURE_THRESHOLD_DIP), mTextY, mPaint);
canvas.drawBitmap(mSwitch_off, new Rect(mDistance, 0, viewWidth, viewHeigth), new Rect(mDistance, 0, viewWidth, viewHeigth), mPaint);
mPaint.setColor(Color.GRAY);
canvas.drawText(mOffText, viewWidth / 2 + getTextSize(12f), mTextY, mPaint);
canvas.drawBitmap(mTthumb, mTthumb_to_left, 0, mPaint);
}
demo戳这里:点击打开链接
写博客,更多的是对自己的一个积累,方便日后总结。最后贴出代码,代码不是很好,欢迎指正!
效果:可以点击切换,也可以拖动切换
先上代码:
[html]
view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<com.example.slidingswitchview.slideswitch.SlidingSwitchView
android:id="@+id/swithview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
1,初始化部分:
[java]
view plaincopy
private Bitmap mSwitch_on, mSwitch_off, mTthumb;
private Paint mPaint;
private int viewWidth, viewHeigth, thumbWidthHalf, thumbWidth;
//记录上一次点击的X坐标和当前的X坐标
private int mLastX, mCurrentX;
// 是否滑动
private boolean isScrolling = false;
// 开关所在的方向,左or右
private boolean isSwitchLeft = false;
// 是否是移动状态
private boolean isMoving = false;
//是否移动过,如果为false代表是单机时间
private boolean hasMoving = false;
private int mMoveDistance = 0;
private int mMoveX = 0;
private FontMetrics mFontMetrics;
private float mTextX, mTextY;
private String mOnText = "on";
private String mOffText = "off";
// 0:静止、1:向左、2:向右
private int mScrollingStatus = 0;
private static final float GESTURE_THRESHOLD_DIP = 10.0f;
final float scale = getContext().getResources().getDisplayMetrics().density;
private IOnSwitchChangerListener mChangerListener = null;
public SlidingSwitchView(Context context, AttributeSet attrs) {
super(context, attrs);
initBitmapResource();
initConstant();
initPaint();
initFontMetrics();
}
private void initConstant() {
viewWidth = mSwitch_on.getWidth() + getPaddingLeft() + getPaddingRight();
viewHeigth = mSwitch_on.getHeight() + getPaddingTop() + getPaddingBottom();
thumbWidth = mTthumb.getWidth();
thumbWidthHalf = thumbWidth / 2;
if (isSwitchLeft) {
mMoveDistance = 0;
} else {
mMoveDistance = viewWidth - thumbWidthHalf;
}
mScrollingStatus = 0;
}
private void initBitmapResource() {
mSwitch_on = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.on);
mSwitch_off = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.off);
mTthumb = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.thumb);
}
private void initPaint() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
private void initFontMetrics() {
// viewWidth: 155,
// viewHeigth: 61
// ascent: -11.1328125
// top: -12.673828
// bottom: 3.2519531 ,
// descent: 2.9296875 ,
// leading: 0.0 ,
mPaint.setTextSize(getTextSize(GESTURE_THRESHOLD_DIP));
mFontMetrics = mPaint.getFontMetrics();
mTextX = (viewWidth >> 1) - (int) (mPaint.measureText(mOnText)) >> 1;
// baseline位置字体下基准线位置
// mTextY代表baseline的位置 字体高度为:(mFontMetrics.descent -
// mFontMetrics.ascent) / 2
// 字体上下居中的推到公式为:控件高度/2 + 字体高度/2 -
// mFontMetrics.bottom(注:bottom的高度通常情况下比较小)
mTextY = ((mFontMetrics.descent - mFontMetrics.ascent) / 2 - mFontMetrics.bottom) + viewHeigth / 2;
}
注:initFontMetrics()方法是在是因为没有现成的图,就手动把文字写上去
2,绘制部分:
重写onDraw方法完成绘制,分3种情况:1、手指移动状态:isMoveing 2、控件处于滑动状态:isScrolling 3、初始化状态 。 其中isScrolling状态分为手指滑动过和未滑动过(也视为单击状态)两种情况。通过mMoveDistance和mCurrentX判断如何绘制。
重写onTouchEvent方法,ACTION_UP中hasMoving判断此次点击是不是单击事件。
[java]
view plaincopy
@Override
protected void onDraw(Canvas canvas) {
if (isMoving) {
if (mMoveDistance <= 0) {
drawbitmap(canvas, 0, 0);
} else if (mMoveDistance >= viewWidth - thumbWidth) {
drawbitmap(canvas, viewWidth - thumbWidthHalf, viewWidth - thumbWidth);
} else {
drawbitmap(canvas, mMoveDistance + thumbWidthHalf, mMoveDistance);
}
} else if (isScrolling) {
drawbitmap(canvas, mMoveDistance + thumbWidthHalf, mMoveDistance);
// 点击向右滑动
if (mCurrentX > viewWidth / 2 && mScrollingStatus == 2) {
mMoveDistance = mMoveDistance + SCROLLING_OFFSET;
}
// 点击向左滑动
else if (mCurrentX <= viewWidth / 2 && mScrollingStatus == 1) {
mMoveDistance = mMoveDistance - SCROLLING_OFFSET;
} else
// MOVE向右滑动
if (mMoveDistance + thumbWidthHalf > viewWidth / 2) {
mMoveDistance = mMoveDistance + SCROLLING_OFFSET;
}
// MOVE向左滑动
else {
mMoveDistance = mMoveDistance - SCROLLING_OFFSET;
}
refreshState();
} else {
// 初始化状态 这个应该跟外部关联
drawbitmap(canvas, mMoveDistance, mMoveDistance == 0 ? 0 : viewWidth - thumbWidth);
mLastX = 0;
mCurrentX = 0;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isScrolling) {
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
isMoving = true;
hasMoving = true;
mCurrentX = (int) event.getX();
mMoveX = mCurrentX - mLastX;
mLastX = mCurrentX;
mMoveDistance = mMoveDistance + mMoveX;
postInvalidate();
break;
case MotionEvent.ACTION_UP:
isMoving = false;
mCurrentX = (int) event.getX();
if (!hasMoving) {
if (mCurrentX < viewWidth / 2 && !isSwitchLeft) {
mMoveDistance = viewWidth - thumbWidth - SCROLLING_OFFSET;
mScrollingStatus = 1;
} else if (mCurrentX >= viewWidth / 2 && isSwitchLeft) {
mMoveDistance = mMoveDistance + SCROLLING_OFFSET;
mScrollingStatus = 2;
}
hasMoving = false;
}
refreshState();
break;
default:
break;
}
return true;
}
private void refreshState() {
if (mScrollingStatus != 0 && (viewWidth - thumbWidth > mMoveDistance && mMoveDistance > 0)) {
isScrolling = true;
} else {
if (mMoveDistance <= 0) {
relaseConstant();
mMoveDistance = 0;
isSwitchLeft = true;
if (mChangerListener != null) {
mChangerListener.onSwitchChanger(this, isSwitchLeft);
}
} else if (mMoveDistance >= viewWidth - thumbWidth) {
relaseConstant();
mMoveDistance = viewWidth - thumbWidthHalf;
isSwitchLeft = false;
if (mChangerListener != null) {
mChangerListener.onSwitchChanger(this, isSwitchLeft);
}
} else {
isScrolling = true;
}
}
postInvalidate();
}
private void relaseConstant() {
isMoving = false;
isScrolling = false;
hasMoving = false;
mScrollingStatus = 0;
}
/**
* 绘制按钮
*
* @param canvas
* @param mDistance
* @param mTthumb_to_left
*/
private void drawbitmap(Canvas canvas, int mDistance, int mTthumb_to_left) {
canvas.drawBitmap(mSwitch_on, new Rect(0, 0, mDistance, viewHeigth), new Rect(0, 0, mDistance, viewHeigth), mPaint);
mPaint.setColor(Color.WHITE);
canvas.drawText(mOnText, getTextSize(GESTURE_THRESHOLD_DIP), mTextY, mPaint);
canvas.drawBitmap(mSwitch_off, new Rect(mDistance, 0, viewWidth, viewHeigth), new Rect(mDistance, 0, viewWidth, viewHeigth), mPaint);
mPaint.setColor(Color.GRAY);
canvas.drawText(mOffText, viewWidth / 2 + getTextSize(12f), mTextY, mPaint);
canvas.drawBitmap(mTthumb, mTthumb_to_left, 0, mPaint);
}
demo戳这里:点击打开链接
写博客,更多的是对自己的一个积累,方便日后总结。最后贴出代码,代码不是很好,欢迎指正!
相关文章推荐
- Android启动icon切图大小
- Android不规则点击区域详解
- Android启动icon切图大小
- 转载 android service 使用以及aidl使用
- android 配置ndk
- 怎么为DragonBoard 410c定制Android系统
- android 签名、混淆打包网址链接
- android定位:获取当前位置的经纬度
- Android 调用系统拍照及相册裁剪后作为头像,兼容到5.0
- 基于Android代码实现常用布局
- Android Fragment 间通信
- 【android studio】 the logging tag can be at most 23 characters
- Android 自定义View
- Android RSA加密
- Android代码实现图片和文字上下布局
- 学习封装双击返回键退出
- android的四种设计模式
- Cordova 非CLI的环境搭建(WIN+ANDROID)
- android studio 使用gradle 导出jar包,并打包assets目录
- Android——Fragment介绍及两种基本使用方法