Canvas的实际使用--自定义搜索效果

来源:互联网 发布:韩国抄袭知乎 编辑:程序博客网 时间:2024/05/20 09:26

这里写图片描述
上面效果是使用Canvas实现的一个搜索效果,涉及到三个部分的绘制:搜索放大镜的圆、放大镜的手柄、线条,根据属性动画执行的多少及移动的距离进行绘制;
1、extends View 并重写onDraw方法

public class MySearchView extends View{    private Paint mPaint;    private BaseController mController;    public MySearchView(Context context) {        this(context,null);    }    public MySearchView(Context context, AttributeSet attrs) {        this(context, attrs,0);    }    public MySearchView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setStrokeWidth(5);        mPaint.setColor(Color.RED);    }    public void setController(BaseController controller){        this.mController=controller;        mController.setSearchView(this);        invalidate();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        mController.draw(canvas,mPaint);    }    /**     * 开启动画     */    public void startAnimation(){        if(mController!=null){            mController.startAnim();        }    }    /**     * 重置动画     */    public void resetAnimation(){        if(mController!=null){            mController.resetAnim();        }    }}

在这里类里面会发现只有一个Paint画笔,开启动画,重置动画的方法,正真onDraw绘制的时候是在BaseController里面进行绘制;

public abstract class BaseController {    private MySearchView mySearchView;    public static final int STATE_ANIM_NONE = 0;    public static final int STATE_ANIM_START = 1;    public static final int STATE_ANIM_STOP = 2;    public static final int DEFAULT_ANIM_TIME = 5000;    public static final float DEFAULT_ANIM_STARTF = 0;    public static final float DEFAULT_ANIM_ENDF = 1;    public int mState = STATE_ANIM_NONE;    private AnimatorListenter animatorListenter;    /**     * 开始动画     */    public void startAnim(){    }    /**     * 重置动画     */    public void resetAnim(){    }    /**     * 绘制     * @param canvas     * @param paint     */    public abstract void draw(Canvas canvas, Paint paint);    public void setSearchView(MySearchView mySearchView){        this.mySearchView=mySearchView;    }    /**     * 获取宽度     * @return  返回MySearchView的宽度     */    public int getWidth(){        return mySearchView.getWidth();    }    /**     * 获取高度     * @return 返回MySearchView的高度     */    public int getHeight(){        return mySearchView.getHeight();    }    public float mpro=-1;    /**     * 设置动画效果     * @return  设置好的ValueAnimator     */    public ValueAnimator startViewAnimation(){        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);        valueAnimator.setDuration(800l);        //设置动画插值器        valueAnimator.setInterpolator(new LinearInterpolator());        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                mpro = (float) animation.getAnimatedValue();                mySearchView.invalidate();            }        });        //监听动画完成        valueAnimator.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                super.onAnimationEnd(animation);                if(animatorListenter!=null){                    animatorListenter.animatorListenter();                }            }        });        valueAnimator.start();        mpro=0;        return valueAnimator;    }    public void addAnimatorFishListener(AnimatorListenter listenter){        this.animatorListenter=listenter;    }}

这里的BaseController是一个抽象类,onDraw方法也是抽象方法,子类必须要实现,这里主要对ValueAnimator进行设置已经监听回调;真正的绘制动作还是在BaseController子类中完成;

public class SearchController extends BaseController{    private RectF mRectF;    private String mColor="#4CAF50";    private int cx,cy,cr;    private int j=15;    public SearchController(){        mRectF=new RectF();    }    @Override    public void draw(Canvas canvas, Paint paint) {        canvas.drawColor(Color.parseColor(mColor));        switch (mState){            case STATE_ANIM_NONE:                drawNormalView(canvas,paint);                break;            case STATE_ANIM_START:                drawStartAnimView(canvas,paint);                break;            case STATE_ANIM_STOP:                drawStopAnimView(canvas,paint);                break;        }    }    /**     * 绘制停止动画view     * @param canvas     * @param paint     */    private void drawStopAnimView(Canvas canvas, Paint paint) {    }    /**     * 绘制开启动画的view     * @param canvas     * @param paint     */    private void drawStartAnimView(Canvas canvas, Paint paint) {        canvas.save();        if(mpro<=0.5f){            /**             * -360 ~ 0 需要变换的范围             *   0  ~ 0.5 mpro实际的变化范围             * 转换公式:360*(mpro*2-1),             */            //绘制圆和把手            canvas.drawArc(                    mRectF,                    45,                    360*(mpro*2-1),                    false,                    paint            );            canvas.drawLine(                    mRectF.right - j,                    mRectF.bottom - j,                    mRectF.right+cr-j,                    mRectF.bottom+cr-j,                    paint            );        }else{            /**             *   0    ~ 1 需要变换的范围             *   0.5  ~ 1 mpro实际的变化范围             * 转换公式:(mpro*2-1),             */            //绘制把手            canvas.drawLine(                    mRectF.right - j + cr*(mpro*2-1),                    mRectF.bottom - j + cr*(mpro*2-1),                    mRectF.right - j + cr,                    mRectF.bottom+cr-j,                    paint);        }        //绘制下面的横线        canvas.drawLine(                (mRectF.right - j + cr)*(1-mpro*0.8f),                mRectF.bottom+cr-j,                mRectF.right - j + cr,                mRectF.bottom+cr-j,                paint);        canvas.restore();        mRectF.left = cx -cr + mpro*250;        mRectF.right = cx + cr +mpro*250;        mRectF.top = cy - cr;        mRectF.bottom = cy + cr;    }    /**     * 绘制普通view     * @param canvas     * @param paint     */    private void drawNormalView(Canvas canvas, Paint paint) {        cr=getWidth()/20;        cx=getWidth()/2;        cy=getHeight()/2;        mRectF.left=cx-cr;        mRectF.right=cx+cr;        mRectF.top=cy-cr;        mRectF.bottom=cy+cr;        //保存画布        canvas.save();        //重置画笔        paint.reset();        //设置抗锯齿        paint.setAntiAlias(true);        paint.setColor(Color.RED);        paint.setStrokeWidth(5);        paint.setStyle(Paint.Style.STROKE);        //将画布选择45度        canvas.rotate(45,cx,cy);        //绘制线条        canvas.drawLine(cx+cr,cy,cx+cr*2,cy,paint);        canvas.drawArc(                mRectF,                0,                360,                false,                paint        );        canvas.restore();    }    @Override    public void startAnim() {        super.startAnim();        mState = STATE_ANIM_START;        startViewAnimation();    }    @Override    public void resetAnim() {        super.resetAnim();        mState = STATE_ANIM_STOP;        startViewAnimation();    }    @Override    public void addAnimatorFishListener(AnimatorListenter listenter) {        super.addAnimatorFishListener(listenter);    }}

SearchController是BaseController的子类,在SearchController的onDraw方法中进行绘制,如果需要不同的效果,直接写一个新的类 extends BaseController,调用就可以了,并不需要去修改SearchController里面的代码,具体的代码中都有注释;
2、使用

public class MainActivity extends AppCompatActivity {    private MySearchView sv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        sv = (MySearchView) findViewById(R.id.sv);        SearchController searchController=new SearchController();        sv.setController(searchController);        searchController.addAnimatorFishListener(new AnimatorListenter() {            @Override            public void animatorListenter() {                Toast.makeText(MainActivity.this,"执行完毕",Toast.LENGTH_LONG).show();            }        });    }    public void start(View v){        sv.startAnimation();    }}

找到MySearchView,调用它的setController方法,将创建好的SearchController对象传入就可以了。

源码地址:
http://download.csdn.net/download/wangwo1991/9974198

阅读全文
0 0
原创粉丝点击