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.

可以一眼看出,指示器的滚动变化,文字的滚动是与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代码,来做出精细的东西.只能说打内心的佩服了.