zoukankan      html  css  js  c++  java
  • Android 7.0 Gallery图库源码分析1

    分析一个项目的源代码时,第一件事就是查看清单文件,找到程序入口,我们从Gallery2源码的清单文件中可以看到GalleryActivity是此应用的启动Activity。

    1 <activity android:name="com.android.gallery3d.app.GalleryActivity" android:label="@string/app_name"
    2                 android:configChanges="keyboardHidden|orientation|screenSize">
    3             <intent-filter>
    4                 <action android:name="android.intent.action.MAIN" />
    5                 <category android:name="android.intent.category.DEFAULT" />
    6                 <category android:name="android.intent.category.LAUNCHER" />
    7                 <category android:name="android.intent.category.APP_GALLERY" />
    8             </intent-filter>
    找到GalleryActivity,它继承自AbstractGalleryActivity,实现OnCancelListener,OnCancelListener暂时不用考虑,它只是处理dialog防止内存泄漏,我们首先查看onCreate方法
     1 @Override
     2     protected void onCreate(Bundle savedInstanceState) {
     3         super.onCreate(savedInstanceState);
     4         requestWindowFeature(Window.FEATURE_ACTION_BAR);
     5         //使用ActionBar的覆盖模式
     6         requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
     7 
     8         if (getIntent().getBooleanExtra(KEY_DISMISS_KEYGUARD, false)) {
     9             //加载布局之前解除锁屏
    10             getWindow().addFlags(
    11                     WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
    12         }
    13         //加载布局
    14         setContentView(R.layout.main);
    15 
    16         if (savedInstanceState != null) {
    17             getStateManager().restoreFromState(savedInstanceState);
    18         } else {
    19             //根据Intent类型初始化
    20             initializeByIntent();
    21         }
    22     }

    我们首先分析布局,找到R.layout.main

     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2         android:id="@+id/gallery_root"
     3         android:orientation="vertical"
     4         android:layout_width="match_parent"
     5         android:layout_height="match_parent">
     6     <include layout="@layout/gl_root_group"/>
     7     <FrameLayout android:id="@+id/header"
     8             android:visibility="gone"
     9             android:layout_alignParentTop="true"
    10             android:layout_width="match_parent"
    11             android:layout_height="wrap_content"/>
    12     <FrameLayout android:id="@+id/footer"
    13             android:visibility="gone"
    14             android:layout_alignParentBottom="true"
    15             android:layout_alignParentLeft="true"
    16             android:layout_alignParentRight="true"
    17             android:layout_width="match_parent"
    18             android:layout_height="wrap_content"/>
    19 </RelativeLayout>



    根据id我们可以判断layout/gl_root_group这个布局应该是最主要的,用来显示主要内容,header和footer暂且不管。gl_root_group是通过include标签来引用的,我们找到此布局。

     1 <merge xmlns:android="http://schemas.android.com/apk/res/android">
     2     <com.android.gallery3d.ui.GLRootView
     3             android:id="@+id/gl_root_view"
     4             android:layout_width="match_parent"
     5             android:layout_height="match_parent"/>
     6     <View android:id="@+id/gl_root_cover"
     7             android:layout_width="match_parent"
     8             android:layout_height="match_parent"
     9             android:background="@android:color/black"/>
    10 </merge>


    它有两个布局。第一个是GLRootView,它继承自GLSurfaceView,也就是说它是使用OpenGL ES来绘制界面,它也是整个界面的核心;第二个是View,根据它的id可以看出它是覆盖在GLRootView上的,至于它的作用我们在GLRootView的onDrawFrame方法中可以发现下面这段代码,它是应用第一次绘制界面时覆盖在SurfaceView上面,防止第一次绘制时SurfaceView变透明,影响美观,之后都会隐藏此View。

     1 // We put a black cover View in front of the SurfaceView and hide it
     2 // after the first draw. This prevents the SurfaceView being transparent
     3 // before the first draw.
     4 if (mFirstDraw) {
     5             mFirstDraw = false;
     6             post(new Runnable() {
     7                     @Override
     8                     public void run() {
     9                         View root = getRootView();
    10                         View cover = root.findViewById(R.id.gl_root_cover);
    11                         cover.setVisibility(GONE);
    12                     }
    13                 });
    14         }



    我们接着看GLRootView,它继承自GLSurfaceView,所以它绘制界面核心就是下面三个方法。

     1 public class GLRootView extends GLSurfaceView
     2         implements GLSurfaceView.Renderer, GLRoot {
     3     @Override
     4     public void onSurfaceCreated(GL10 gl1, EGLConfig config) {
     5         //Suface创建好会回调此方法,一般这个方法都是做些绘制界面的准备工作
     6     }
     7 
     8     @Override
     9     public void onSurfaceChanged(GL10 gl1, int width, int height) {
    10         //Suface改变时回调此方法,比如横竖屏转换等,这里面一般是重新设置界面size等
    11     }
    12 
    13     @Override
    14     public void onDrawFrame(GL10 gl) {
    15        //每绘制一帧都会回调此方法,也就是说你想绘制三角形还是纹理贴图等都是在这方法里面实现。
    16 
    17         try {
    18             //这个方法是实际绘制界面的
    19             onDrawFrameLocked(gl);
    20         } finally {
    21             mRenderLock.unlock();
    22         }
    23     }
    24 }


    我们接着查看onDrawFrameLocked方法

     1 private void onDrawFrameLocked(GL10 gl) {
     2         ......
     3         //mContentView是GLView类型,mCanvas是GLCanvas类型,这是绘制界面的主要工具
     4         if (mContentView != null) {
     5            mContentView.render(mCanvas);
     6         } else {
     7             // Make sure we always draw something to prevent displaying garbage
     8             mCanvas.clearBuffer();
     9         }
    10         ......
    11     }



    现在讲讲GLView和GLCanvas这两个类,GLView是界面显示的UI组件,图库界面是有很多个小控件组成的,GLView就是这些小控件的基类,它可以渲染到GLCanvas上,并且接受触摸事件。GLCanvas就是一个画布,GLView的size等定义好了怎么显示到界面上呢?其实就是通过GLCanvas来实现,GLCanvas是一个接口,它最终是使用OpenGL ES的GLES20.glDrawArrays(type, 0, count)来绘制每个GLView,它可以绘制直线、矩形等形状,没学过OpenGL ES的可以参考我之前的文章,对OpenGL ES有个大概了解。

    GLView的子类在com.android.gallery3d.ui目录里,以view.java结尾的都是它的子类,像EdgeView、PhotoView、ScrollBarView、SlideshowView、SlotView、TileImageView、UndoBarView等,每个代表一种UI组件类型。

    GLCanvas有GLES11Canvas和GLES20Canvas两个子类,GLES11Canvas代表OpenGL ES 1.1之前的版本,使用固定管线绘图,这个版本太老可以不考虑了;GLES20Canvas代表OpenGL ES 2.0之后的版本,使用shader语言实现绘图,现在一般都是使用它。

    现在就将这些,至于GLView和GLCanvas的细节后面再详解。

  • 相关阅读:
    Unix UTC时间转化为本地时间的一个MFC实现
    不规则按钮Button修正版
    不规则按钮,支持普通Button,Radio Button, Check Button
    Kimi ga Suki da to Sakebitai
    将adb for visual studio 从26升级29版本
    直到世界的尽头
    Your Song
    Win32创建后台进程
    全金属外壳的歌词
    C#获取本机IP(排除IPV6,仅获取IPV4)的方法转载
  • 原文地址:https://www.cnblogs.com/zhao-shan/p/9838262.html
Copyright © 2011-2022 走看看