zoukankan      html  css  js  c++  java
  • wing带你玩转自定义view系列(2) 简单模仿qq未读消息去除效果

    上一篇介绍了贝塞尔曲线的简单应用 仿360内存清理效果


    这一篇带来一个  两条贝塞尔曲线的应用 : 仿qq未读消息去除效果。


    转载请注明出处:http://blog.csdn.net/wingichoy/article/details/50503630


    老规矩,先上效果图:





    qq的未读消息去除很炫酷,其实就是用了两条贝塞尔曲线,我们按思路来,先来画两个圆,及两条贝塞尔曲线,辅助点为圆心y坐标的一半。我们把下面移动的圆,叫做mMoveCircle.



    这样一画,就很简单明了了对不对。只要在拖动的时候 去改变辅助点的Y,和固定圆的半径, 就可以出来如效果图的效果。

    那么重写onTouchEvent

     @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    mMoveCircleY = event.getY();
    
    //                mSupY = mCircleY;
                    if (mMoveCircleY < lastY) {
                        isUp = false;
                    } else {
                        isUp = true;
                    }
                    lastY = mMoveCircleY;
                    invalidate();
                    break;
    
                case MotionEvent.ACTION_UP:
                    if((mMoveCircleY-mCircleY)>mMoveCircleRadius*3){
    
                        Log.e("wing","超过");
                        isCanDraw = false;
                        invalidate();
    
                    }else {
    
                        Log.e("wing","没超过");
                    }
            }
    
            return true;
        }


    这里Action_move记录了最后一次移动和这次移动的值,来代表是往上滑还是往下滑,改变一个标记为,并且让mMoveCircleY改变为触摸的y坐标。

    ACTION_UP主要记录 圆点离开的范围,如果超过这个范围,则代表消息提醒去除掉。


    在ondraw里绘制贝塞尔曲线

      //左边的线
                    path.moveTo(mCircleX - mCircleRadius + mPaintStrokeWidth / 2, mCircleY);
                    path.quadTo(mCircleX , mSupY, mCircleX - mMoveCircleRadius + mPaintStrokeWidth / 2, mMoveCircleY);
                    canvas.drawPath(path, p);
    
                    //右边的线
                    path.moveTo(mCircleX + mCircleRadius - mPaintStrokeWidth / 2, mCircleY);
                    path.quadTo(mCircleX, mSupY, mCircleX + mMoveCircleRadius - mPaintStrokeWidth / 2, mMoveCircleY);
                    canvas.drawPath(path, p);


    这样可以画成两条贝塞尔曲线,但是是空心的


    那么我们想象办法,如何才能让他封闭呢。还记得绘制多边形的办法吗。。直接在两条贝塞尔曲线之间lineto就可以了,然后close;

     path.moveTo(mCircleX - mCircleRadius + mPaintStrokeWidth / 2, mCircleY);
                    path.quadTo(mCircleX , mSupY, mCircleX - mMoveCircleRadius + mPaintStrokeWidth / 2, mMoveCircleY);
                    path.lineTo(mCircleX + mMoveCircleRadius, mMoveCircleY);
                    path.quadTo(mCircleX, mSupY, mCircleX + mCircleRadius, mCircleY);
                    path.lineTo(mCircleX - mCircleRadius, mCircleY);
                    path.close();
                    canvas.drawPath(path, p);

    其实我们绘制的是这个效果,然后在把两个实心圆画上去,画笔style设置为fill 即可、

    封闭画笔,动态改变半径,绘制圆。

            p.setStyle(Paint.Style.FILL);

                    if (isUp) {
    
                        canvas.drawCircle(mCircleX, mCircleY, mCircleRadius--, p);
                        canvas.drawCircle(mCircleX, mMoveCircleY, mMoveCircleRadius, p);
                    } else {
    
                        canvas.drawCircle(mCircleX, mCircleY, mCircleRadius++, p);
                        canvas.drawCircle(mCircleX, mMoveCircleY, mMoveCircleRadius, p);
                    }
    得到如下效果。

    最后,来判断是否超过一定下拉区域,如果超过 则圆点跟着手一起走 然后在手松开的时候消失。

     if ((mMoveCircleY-mCircleY)<mMoveCircleRadius*3) {
                    Log.e("wing",mSupY-mCircleY+"");
                    Path path = new Path();
                    //左边的线
                    path.moveTo(mCircleX - mCircleRadius + mPaintStrokeWidth / 2, mCircleY);
                    path.quadTo(mCircleX , mSupY, mCircleX - mMoveCircleRadius + mPaintStrokeWidth / 2, mMoveCircleY);
                    path.lineTo(mCircleX + mMoveCircleRadius, mMoveCircleY);
                    path.quadTo(mCircleX, mSupY, mCircleX + mCircleRadius, mCircleY);
                    path.lineTo(mCircleX - mCircleRadius, mCircleY);
                    path.close();
                    canvas.drawPath(path, p);
    
                    //右边的线
    //                path.moveTo(mCircleX + mCircleRadius - mPaintStrokeWidth / 2, mCircleY);
    //                path.quadTo(mCircleX, mSupY, mCircleX + mMoveCircleRadius - mPaintStrokeWidth / 2, mMoveCircleY);
    //                canvas.drawPath(path, p);
    
                    p.setStyle(Paint.Style.FILL);
    //                canvas.drawCircle(mCircleX, mCircleY, mCircleRadius, p);
    
                    if (isUp) {
    
                        canvas.drawCircle(mCircleX, mCircleY, mCircleRadius--, p);
                        canvas.drawCircle(mCircleX, mMoveCircleY, mMoveCircleRadius, p);
                    } else {
    
                        canvas.drawCircle(mCircleX, mCircleY, mCircleRadius++, p);
                        canvas.drawCircle(mCircleX, mMoveCircleY, mMoveCircleRadius, p);
                    }
    //                canvas.drawPoint(mSupX, mSupY, p);
                } else {
    
                    p.setStyle(Paint.Style.FILL);
                    canvas.drawCircle(mCircleX, mMoveCircleY, mMoveCircleRadius, p);
    //                canvas.drawCircle(mCircleX, mMoveCircleY, mMoveCircleRadius, p);
                }

    最后遗留一个复杂的问题, 用户可以360度拖动,这时候要根据圆 来计算切点的坐标,再来重新计算辅助点的坐标。比较繁琐,这里就不算了。 #其实我是不会#本篇的目的,了解贝塞尔曲线的应用我想已经达到了,读者若感兴趣,可以自行实现。#其实我是不会#


    ------------------------------------------------------------------------------解决篇-----------------------------------------------------------------------------------------------------

    回到家又研究了一下360度动态转变的,终于想通怎么算了。如下图(无视那么丑 还有想吐槽下中性笔的油):



    其实我们要面临的问题就是计算出 圆的切点坐标。  换言之就是求 ∠1 的角度。

    由图可知 ∠1 = ∠2     ∠2  = ∠3  由于等价代换可得 ∠3 = ∠1


    由图得:tan∠3 = (mCirlceY - mMoveCircleY)/(mMoveCircleX-mCircleX)  即∠1 = arctan (mCirlceY - mMoveCircleY)/(mMoveCircleX-mCircleX


    则可计算右上点的坐标为:

    x: mMoveCircleX - mMoveCircleRadius * sin∠1

    y: mMoveCircleY - mMoveCircleRadius * cos∠1


    其他三个切线点的坐标计算方法如上。得到四个点的坐标,只需要改变path的起终点 和 辅助点的坐标即可。由于过于繁杂,就不用代码给各位实现了。大家如果感兴趣,可以自行实现。#其实就是懒# 







    下一篇:wing带你玩转自定义view系列(3)模仿微信下拉眼睛

    本项目地址:点击打开链接   求关注 求评论  求star

  • 相关阅读:
    [原创]K8Cscan插件之Mysql密码爆破(内网渗透/支持批量/可跨网段)
    [原创]K8Cscan插件之FTP弱口令扫描(内网渗透/支持批量/可跨网段)
    [原创]K8Cscan插件之Web主机扫描(存活主机、机器名、Banner、标题)(内网渗透/支持批量/可跨网段)
    [原创]K8Cscan插件之存活主机扫描(内网渗透/支持批量/可跨网段)
    [原创]K8 Jboss jmx-console getshell exploit
    [原创]K8Cscan插件之C段旁站扫描子域名扫描
    [原创]K8mysqlCmd数据库免驱连接工具
    [原创]k8exe2bat任意文件转Bat工具(WebShell无法上传EXE解决方案)
    Tensorflow 笔记:第一讲
    数据结构的C语言基础
  • 原文地址:https://www.cnblogs.com/muyuge/p/6333549.html
Copyright © 2011-2022 走看看