1 序言
网上很多自定义View的例子都非常详细讲解了如何写出一个高效实用的自定义View,但是这些由于过于详细,给予一些新手的学习造成了一定的困难,比如说,当初我要学习如何自定义下拉刷新控件,结果,很多大神顺便把一些在我看来 学习自定义View非必要的技术带了进来,如数据结构啊,事件分发机制啊.这些东西不是说不必要,但是他们应该放到别的文章里面,否则对新手来说,让他们去思考这些繁杂的机制,而容易陷入细节不能自拔.这些技术在这篇文章里,他们只是充当辅助的角色,不是我们的主角,我们的主角就是在ondraw里面花时间,然后写出来一个自定义View.这样我们就能更加专注写出一个View,在此基础上,我们再谈扩展和高效.
2 实现思路
我们首先观察一下,这个按钮在打开和关闭时的状态,最终可以发现,他只是一些简单的几何组合,所以我们可以通过代码来实现这个效果,
3 代码
public class SwithcButton extends View {
private Paint mPaint;
public int state=1; //状态,0位开,1位关.默认为关闭状态
public SwithcButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
mPaint=new Paint();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
postInvalidate();
isAnim=true;
break;
default:
break;
}
return true;
}
boolean isAnim; //是否在播放动画
float scale=0.9f; //画布缩放比例
float offsetX=0; //按钮X轴偏移量
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
if(state==1){
mPaint.setColor(0xffcccccc);
}else{
mPaint.setColor(Color.GREEN);
}
mPaint.setShadowLayer(0, 0, 0, Color.GRAY);
RectF mRectF=new RectF(0, 0, 100,50);
canvas.drawRoundRect(mRectF, 50, 50, mPaint);
mPaint.setColor(0xffffffff);
canvas.save();
canvas.scale(scale, scale, 50, 25);
canvas.drawRoundRect(mRectF, 50, 50, mPaint);
canvas.restore();
if(state==1 && isAnim){
scale-=0.1;
offsetX+=5;
invalidate();
if(scale<=0.01){
isAnim=false;
state=0;
scale=0.01f;
offsetX=50;
Log.i("test", "open");
}
}
if(state==0 && isAnim){
scale+=0.1;
offsetX-=5;
invalidate();
if(scale>=0.9f){
isAnim=false;
state=1;
scale=0.9f;
offsetX=0;
Log.i("test", "close");
}
}
mPaint.setColor(0xffdddddd);
mPaint.setShadowLayer(10, 0, 0, Color.GRAY);
canvas.save();
canvas.translate(offsetX, 0);
canvas.drawRoundRect(new RectF(1,1,48,48), 48, 48,mPaint);
canvas.restore();
}
}
4 最终效果