分析一个项目的源代码时,第一件事就是查看清单文件,找到程序入口,咱们从Gallery2源码的清单文件中能够看到GalleryActivity是此应用的启动Activity。java
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.mainandroid
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标签来引用的,咱们找到此布局。app
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。ide
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有个大概了解。post
GLView的子类在com.android.gallery3d.ui目录里,以view.java结尾的都是它的子类,像EdgeView、PhotoView、ScrollBarView、SlideshowView、SlotView、TileImageView、UndoBarView等,每一个表明一种UI组件类型。ui
GLCanvas有GLES11Canvas和GLES20Canvas两个子类,GLES11Canvas表明OpenGL ES 1.1以前的版本,使用固定管线绘图,这个版本太老能够不考虑了;GLES20Canvas表明OpenGL ES 2.0以后的版本,使用shader语言实现绘图,如今通常都是使用它。spa
如今就将这些,至于GLView和GLCanvas的细节后面再详解。
3d