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

这里写图片描述
上面效果是使用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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值