Telegram阅读心得---页面结构(2)

Telegram阅读心得---页面结构(2)

Telegram阅读心得---页面结构(1)
今天我看一看那个,打开telegram能够第一眼看到的那个欢迎页
先提出这次的问题

问题 我对页面的滑动动画感兴趣,我想想看看那个动画是怎么实现的?

首先我要找到这个页面


欢迎页

string.xml中搜索这段图中的这段文本

The world's fastest messaging app.It is free and secure.

就可以找到它在app中出现的相应位置IntroActivity
同样的,这个页面也是通过代码的方式加载的页面.
页面元素比较简单,结构也比较简单.根布局是一个scrollview,在scrollview中用frameLayout承载了viewPager,顶部的动画textureView,底部的开始按钮textView,以及中间的一个自定义的viewpager指示器BottomPagesView.

UTOOLS1554879470986.png

可以一眼看出,指示器的滚动变化,文字的滚动是与viewpager相关的.

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                //这里随着viewpager的滚动,通知指示器变化
                bottomPages.setPageOffset(position, positionOffset);
                //调用了一个native的方法
                Intro.setScrollOffset(offset);
                ......
            }
            ......
}

那顶部的图标的变化是怎么实现的呢?
首先顶部的动画是基于TextureView来实现的,来看一下这个textureview做了些什么

textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                if (eglThread == null && surface != null) {
                    eglThread = new EGLThread(surface);
                    eglThread.setSurfaceTextureSize(width, height);
                    //在这里启动了一个任务
                    eglThread.postRunnable(() -> eglThread.drawRunnable.run());
                }
            }

        ......

这里生成了一个EGLThread对象.
这个EGLThread是个什么东西呢
EGLThread继承自DispatchQueue,而DispatchQueue继承自Thread.
EGLThread中有一个EGL10,这个时候我想到,这个动画很有可能是native实现的.惊了~
接着往下看,确实是这个样子.

看线程中的这个任务eglThread.postRunnable(() -> eglThread.drawRunnable.run());做的内容

private Runnable drawRunnable = new Runnable() {
            @Override
            public void run() {
                ......
                float time = (System.currentTimeMillis() - currentDate) / 1000.0f;
                Intro.setPage(currentViewPagerPage);
                Intro.setDate(time);
                Intro.onDrawFrame();
              
                egl10.eglSwapBuffers(eglDisplay, eglSurface);
              //这里每16毫秒就执行这个任务,是不是能里面想到,Android上的要想达到60帧/s的流畅显示,那么每一帧的渲染时间不能高于16ms呢
                postRunnable(() -> drawRunnable.run(), 16);
            }
        };

那么这个动画的执行流程,就是这样子的


动画的执行流程

这样子就实现了稳定的60帧的动画绘制
我并没有认真看native层是如何做出如此精细的动画,将近3000行的c代码,来做出精细的东西.只能说打内心的佩服了.

你可能感兴趣的:(Telegram阅读心得---页面结构(2))