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

Android自定义View 之 SwitchButtonView

2016-04-19 14:29 453 查看
转载请注明原作者:/article/11247554.html

Demo :APK托管地址

这个控件主要解决多个自定义button,textview或者imageview切换繁琐的问题。通过这个控件可以简单快速的实现相应功能。监听切换也非常简单。


通过继承view实现一个SwitchButtonView的控件,并通过onTuch事件实现精确onClick效果,下面是实现效果图。



首先写一个SwitchButtonView继承view并实现OnTouchListener方法。

public class SwitchButtonView extends View implements OnTouchListener{


在values 文件夹下创建一个attrs资源文件并给自定义View配置相关属性,以便在布局中动态传入这些属性值。

<declare-styleable name="labelSwitch">
<attr name="switchwidth" format="dimension" />
<attr name="switchheight" format="dimension" />
<attr name="switchlableNames" format="string" />
<attr name="switchbgcolor" format="color" />
<attr name="switchlovalcolor" format="color" />
<attr name="norswitchTextColor" format="color" />
<attr name="nelswitchTextColor" format="color" />
<attr name="switchTextSize" format="dimension" />
<attr name="StrokeWidth" format="integer" />
</declare-styleable>


并在SwitchButtonView(Context context, AttributeSet attrs, int defStyleAttr)方法中引用这些属性做一些初始化操作。为了达到通用效果defValue值设置相应合适的参数。

参数获得后在初始化各种Paint为onDraw做相应准备。

private void init(){

bgPaint = new Paint();
bgPaint.setAntiAlias(true);
bgPaint.setColor(switchbgcolor);

cPaint = new Paint();
//设置抗锯齿
cPaint.setAntiAlias(true);
//设置空心
cPaint.setStyle(Paint.Style.STROKE);
//设置画出的线的 粗细程度
cPaint.setStrokeWidth(StrokeWidth);
cPaint.setColor(switchlovalcolor);

//选中矩形画笔
scPaint = new Paint();
scPaint.setAntiAlias(true);
scPaint.setColor(switchlovalcolor);

rtPaint = new Paint();
rtPaint.setAntiAlias(true);
rtPaint.setTextSize(textSzie);
rtPaint.setColor(norswitchTextColor);

wtPaint = new Paint();
wtPaint.setAntiAlias(true);
wtPaint.setTextSize(textSzie);
wtPaint.setColor(nelswitchTextColor);
}


在onMeasure方法中设置view的大小以便onDraw绘制出控件,为什么加10?这是为了达到绘制边缘完全显示出效果,在onDraw方法中我会将原点平移到(5,5)。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
//件尺寸增加10目的是让画最外层矩形时粗细设置可见
setMeasuredDimension(measuredWidth+10, measuredHeight+10);
}


最核心的方法在onDraw中实现。代码如下:

@Override
protected void onDraw(Canvas canvas) {
//将坐标原点移到(5,5)
canvas.translate(5, 5);
// 设置个矩形,扫描测量
RectF oval = new RectF(0, 0, measuredWidth, measuredHeight);
//画背景颜色
canvas.drawRoundRect(oval, measuredHeight/2, measuredHeight/2,bgPaint);//第二个参数是x半径,第三个参数是y半径
//画圆角矩形
canvas.drawRoundRect(oval, measuredHeight/2, measuredHeight/2,cPaint);
//根据数据动态计算画直线i=1开始画线
for (int i = 1; i < lable.size(); i++) {
float X = measuredWidth/lable.size()*i;
//画直线
canvas.drawLine(X, 0, X, measuredHeight, cPaint);
}

//特殊化最后一个和第一个
if (clickIndex==0) {
//初始化选中lable
oval.set(0, 0, measuredWidth/lable.size(), measuredHeight);
canvas.drawRoundRect(oval, measuredHeight/2, measuredHeight/2,scPaint);
oval.set(measuredHeight/2, 0, measuredWidth/lable.size(), measuredHeight);
//画矩形
canvas.drawRoundRect(oval, 0, 0,scPaint);
}else if (clickIndex==lable.size()-1) {
oval.set(measuredWidth/lable.size()*clickIndex, 0, measuredWidth, measuredHeight);
canvas.drawRoundRect(oval, measuredHeight/2, measuredHeight/2,scPaint);
oval.set(measuredWidth/lable.size()*clickIndex, 0, measuredWidth/lable.size()*clickIndex + measuredHeight/2, measuredHeight);
//画矩形
canvas.drawRoundRect(oval, 0, 0,scPaint);
}else {
oval.set(measuredWidth/lable.size()*clickIndex, 0,measuredWidth/lable.size()*(clickIndex+1), measuredHeight);
canvas.drawRoundRect(oval, 0, 0,scPaint);
}

//动态画文字
for (int i = 0; i < lable.size(); i++) {
//获得画笔TextBounds以便获取字体宽度和高度
rtPaint.getTextBounds(lable.get(i), 0, lable.get(i).length(), bounds);
float startX = (float)measuredWidth/lable.size()*i + ((float)measuredWidth/lable.size() - (float)bounds.width())/2;
float startY = (float)measuredHeight/2 + (float)bounds.height()/3;
if (i==clickIndex) {
canvas.drawText(lable.get(i), startX, startY, wtPaint);
}else {
canvas.drawText(lable.get(i), startX, startY, rtPaint);
}
}

}


为了达到精确点击某一块的onCick方法,通过ontouch获得坐标判断点击区域实现,就不做过多讲解了,代码如下:

/**
* 通过onTouch实现onClick效果
*/
@SuppressLint("NewApi")
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN://按下
int tempX = (int) (arg1.getRawX()-arg0.getX());
clickIndex = tempX/((measuredWidth+10)/lable.size());
//通知onDraw重新绘制
invalidate();
try {
//接口回调
switchOnClickListener.onClick(arg0,clickIndex,lable.get(clickIndex));
} catch (Exception e) {
//不打印log,这里接口回调会报空指针,属正常
}
break;
case MotionEvent.ACTION_UP://抬起
//          Log.i("", "抬起");
//          //接口回调
//          switchOnClickListener.onClick(arg0,clickIndex,lable.get(clickIndex));
break;

default:
break;
}
return true;
}


下面是简单的使用方法:

<com.example.SwitchButtonView
android:id="@+id/switchview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
app:StrokeWidth="5"
app:nelswitchTextColor="#ffffff"
app:norswitchTextColor="#ffffff"
app:switchTextSize="17sp"
app:switchbgcolor="#e0e0e0"
app:switchheight="40dp"
app:switchlableNames="全部,未服务,已服务,无服务"
app:switchlovalcolor="#ae0000"
app:switchwidth="250dp" />


SwitchButtonView view = (SwitchButtonView)findViewById(R.id.switchview);
view.setSwitchOnClickListener(new SwitchOnClickListener() {
@Override
public void onClick(View view, int index, String buttonName) {
// TODO Auto-generated method stub
String string = "index:" + index + "---buttonName:" + buttonName;
textview.append("\n");
textview.append(string);
}
});


下载链接:源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: