您的位置:首页 > 移动开发 > Android开发

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戳这里:点击打开链接

写博客,更多的是对自己的一个积累,方便日后总结。最后贴出代码,代码不是很好,欢迎指正!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: