美文网首页自定义程序员Android知识
QQ上发送么么哒时候,弹出弹跳表情,是如何实现的?

QQ上发送么么哒时候,弹出弹跳表情,是如何实现的?

作者: 午时已到咯 | 来源:发表于2017-03-23 11:45 被阅读197次

显示

qq_emoji.gif

先分析

QQ_g.png

每次自由落体运动-过程a

从一个消息框到下一个消息框-过程b (由多个过程a组成)

获取屏幕上消息的的Y轴坐标,并不断更新数据结构-过程c

c+b就是整个动画

代码们

过程a: 一次自由落体

计算时间:


ex_time1.png ex_time.png

先求Y轴的初始速度X轴的速度

float singleTime= (float) ((-startVy+Math.sqrt(startVy*startVy+2*g*distanceY))/g);
startVx=distanceX/singleTime;

再算坐标

currentX= (int) (startX+currentVx*period1);
currentVy= (float) (startVy+g*period1);
currentY= (int) (startY+startVy*period1+g*period1*period1/2);

放在循环中形成动画

这里用surfaceview较好,用view的话会太卡顿

private void drawUI() {
    Canvas canvas=holder.lockCanvas();
    try{
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawPaint(paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
        canvas.drawBitmap(bitmap,currentX,currentY-bitmapHei,paint);
        if(points!=null){
            for(Point temp:points){
                canvas.drawCircle(temp.x,temp.y,10,paint);
            }
        }
    }catch (Exception e){
        Log.e(TAG,"出错了");
    }finally{
        holder.unlockCanvasAndPost(canvas);
    }
}

相信我,麻烦事慢慢做的时候最不麻烦!

过程b 用数据转换为动画

QQ_g.png

这里借用下图,一个过程b包含个过程a

多个过程a的组成

while(currentIndex<points.size()-1){
...

    if(Math.abs(currentVy)<MAX_VY){
        if(currentIndex==points.size()-2){
            //结束了
           resetBall();
            break;
        }
        currentIndex++;
        startVy=START_VY;//不断重置 v轴方向的速度
    }

}

需要的数据

public void setPoints(List<Point>points){
    this.points=points;
}

过程c:数据获取(然后把结果输入给过程b)

先获取

    private void initPoints() {
        map.clear();
        int first=manager.findFirstCompletelyVisibleItemPosition();
        int last=manager.findLastCompletelyVisibleItemPosition();//得到暂时可见的
        for(int i=first;i<=last;i++){
            View view=manager.findViewByPosition(i);
            float distance;
            if(i==first){
                distance=0;
            }else{
                View previous=manager.findViewByPosition(i-1);
                distance=view.getY()-previous.getY();
            }
            PointInfo pointInfo=new PointInfo(distance,infos.get(i).isMe);
            map.put(i,pointInfo);
        }
        float startY=manager.findViewByPosition(first).getY();
        entity=new LocationEntity(map,first,startY);//把距离差转换为坐标
        mainScroll.setLocation(entity);
    }

再更新

if(i>mainScroll.getLocationEntity().firstPosition&&
                    !mainScroll.getLocationEntity().getDistanceMap().containsKey(i)){//只往下获取
...
}

移动的偏移

这里用到的offsetTopAndBottom,在recyclerview的监听中

ballsurfaceView.offsetTopAndBottom(dy);

遇到的麻烦

view不断重画会很卡,用surfaceview替代

Canvas canvas=holder.lockCanvas();
try{
...
}catch (Exception e){
}finally{
    holder.unlockCanvasAndPost(canvas);
}

动画的显示可能会很长,这里用到了scrollview当做父容器。

禁止滑动

surfaceview直接添加的话高度为零,需要放到一个LinearLayout当中

surfaceview的高度不应该是固定值

因为可利用数据只是屏幕内能看到的内容,所以需要不断更新数据,加入新的坐标点。这里偷下懒,对象引用传递就好了。

大功告成!

下载

以上です。


v2-4437a6daf48e35b2be21ff68eb650810_b.jpg

相关文章

网友评论

    本文标题:QQ上发送么么哒时候,弹出弹跳表情,是如何实现的?

    本文链接:https://www.haomeiwen.com/subject/wdqanttx.html