天天用酷我音乐听歌,有天突然发现它顶部的switch控件其实还是蛮不错的,刚刚才学习了aige大神的自定义控件系列,于是就决定自己也仿一个就当是练练手
效果图没有酷我的好看(尤其是中间的那个圆中的wifi我实在是没有模拟出来),学艺不精让大家见笑了
核心代码如下:
自定义属性,方便个性化
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="slideswitch" >
<attr name="themeColor" format="color"/>
<attr name="isOpen" format="boolean" />
</declare-styleable>
</resources>
package com.example.slieswitch;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* 仿酷我音乐顶部switch控件(圆中间的wifi标志不清楚如何画出来的)
* @author Administrator
*
*/
public class SlideSwitch extends View {
private static final String TAG = "SlideSwitch";
private Context context;
//默认背景颜色
private static final int COLOR_THEME = Color.parseColor("#ff00ee00");
//背景及圆的画笔
private Paint mPaint;
//文字画笔
private TextPaint textPaint;
private String mStr;// 绘制的文本
private float mTextSize;// 画笔的文本尺寸
//判断开关状态
private boolean isOpen;
//临时变量
private int color_theme;
//绘制背景的矩形
private Rect backRect;
//绘制的圆与背景边缘必须有一定的缝隙,否则就会重合
private int min_space = 1;
//绘制的圆心的坐标
private float circle_x, circle_y;
//绘制的圆心最左边和最右边的x坐标
private float centre_right, centre_left;
//背景的透明度
private int alpha;
//手指触摸屏幕时的初始坐标x
private float eventStartX;
//手指离开屏幕时的坐标x
private float eventLastX;
//文本的起始坐标x和y(最好应该是文本的中心坐标)
private float text_x,text_y;
//自定义的handler为了处理invalidate()没有及时响应
private SlideListener slideListener=null;
private SlideHander mHander = new SlideHander();
public interface SlideListener {
public void open();
public void close();
}
public SlideSwitch(Context context) {
super(context, null);
}
public SlideSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
// calArgs(context);
init();
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.slideswitch);
color_theme = typedArray.getColor(R.styleable.slideswitch_themeColor, COLOR_THEME);
isOpen = typedArray.getBoolean(R.styleable.slideswitch_isOpen, false);
typedArray.recycle();
}
public SlideSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setSlideListener(SlideListener slideListener) {
this.slideListener = slideListener;
}
/**
* 参数计算
*
* @param context
* 上下文环境引用
*/
private void calArgs(Context context) {
// 获取屏幕宽
int sreenW = MeasureUtil.getScreenSize((Activity) context)[0];
// 计算文本尺寸
mTextSize = getMeasuredWidth() /10F;
// Log.e(TAG, "控件的大小="+getMeasuredWidth());
// Log.e(TAG, "文本字体的大小="+mTextSize);
}
private void init(){
/*
* 初始化画笔并设置参数
*/
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.LINEAR_TEXT_FLAG);
textPaint.setColor(Color.BLACK);
// textPaint.setTextSize(mTextSize);
// textPaint.setTextAlign(Paint.Align.CENTER);
// textPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasureSize(280, widthMeasureSpec);
int height = getMeasureSize(140, heightMeasureSpec);
calArgs(context);
if (width < height) {
width = height * 2;
}
setMeasuredDimension(width, height);
initDraw();
}
private void initDraw() {
int width = getMeasuredWidth();
int height = getMeasuredHeight();
backRect = new Rect(0, 0, width, height);
circle_y = height / 2;
centre_right = width - height / 2 - min_space;
centre_left = height / 2 + min_space;
if (isOpen) {
circle_x = centre_right;
alpha = 255;
} else {
circle_x = centre_left;
alpha = 0;
}
}
private int getMeasureSize(int defaultSize, int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.EXACTLY:
result = measureSpec;
break;
default:
result = defaultSize;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(defaultSize, specSize);
}
break;
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
textPaint.setTextSize(mTextSize);
float raduis = backRect.height() / 2f - min_space;
mPaint.setColor(Color.GRAY);
canvas.drawRoundRect(new RectF(backRect), raduis, raduis, mPaint);
mPaint.setColor(COLOR_THEME);
mPaint.setAlpha(alpha);
if (isOpen) {
mStr="仅在wifi联网";
text_x=(canvas.getWidth()-getMeasuredHeight()-min_space)/2-textPaint.measureText(mStr)/2f;
}else {
mStr="流量保护中";
text_x=(canvas.getWidth()+getMeasuredHeight()+min_space)/2-textPaint.measureText(mStr)/2f;
}
text_y=getMeasuredHeight()/2f-((textPaint.descent() + textPaint.ascent()) / 2);
// Log.e(TAG, "text_x="+text_x);
canvas.drawRoundRect(new RectF(backRect), raduis, raduis, mPaint);
canvas.drawText(mStr, text_x, text_y, textPaint);
mPaint.setColor(Color.WHITE);
// Log.e(TAG, "圆心==="+circle_x);
canvas.drawCircle(circle_x, circle_y, raduis, mPaint);
// Log.e(TAG, "画布的宽canvas.getWidth()="+canvas.getWidth());
// Log.e(TAG, " getMeasuredWidth()="+ getMeasuredWidth());
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
eventStartX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
eventLastX = event.getX();
float tempX = eventLastX;
tempX = (float) (tempX > centre_right ? centre_right : tempX);
tempX = (float) (tempX < centre_left ? centre_left : tempX);
if (tempX >= centre_left && tempX <= centre_right) {
circle_x = tempX;
circle_y = getMeasuredHeight() / 2;
alpha = (int) (255 * circle_x /centre_right);
slide();
}
break;
case MotionEvent.ACTION_UP:
eventLastX = event.getX();
text_y=getMeasuredHeight()/2;
if (isOpen) {
if (eventLastX >getMeasuredWidth() / 2) {
circle_x = centre_right;
alpha = 255;
isOpen=true;
slideListener.open();
} else {
circle_x = centre_left;
alpha = 0;
isOpen=false;
slideListener.close();
}
} else {
if (eventLastX < getMeasuredWidth() / 2) {
circle_x = centre_left;
alpha = 0;
isOpen=false;
slideListener.close();
} else {
circle_x = centre_right;
alpha = 255;
slideListener.open();
isOpen=true;
}
}
slide();
break;
}
return true;
}
private void slide() {
mHander.sleep(1);
}
//借鉴aige大神的解决办法,让圆能随着手指的滑动能不停的invalidate()
private class SlideHander extends Handler {
@Override
public void handleMessage(Message msg) {
SlideSwitch.this.invalidate();
}
public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
}
public boolean getState() {
return isOpen;
}
}
那个工程不知道怎么上传,有需要的可以留言!(PS:其实这个控件的主要思路是http://blog.csdn.net/chziroy/article/details/44146911这位博主提供的,但是由于我水平有限对于他文中的一些逻辑判断实在是没看懂就自己写了,依然表示非常感谢!)