1.首先查看AndroidManifest.xml查看清单文件,查找程序的入口:
<activity android:name="com.android.gallery3d.app.GalleryActivity"
android:label="@string/app_name"
android:exported="true"
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.APP_GALLERY" />
</intent-filter>
...
</activity>
2.找到com.android.gallery3d.app.GalleryActivity,继承AbstractGalleryActivity 并实现了OnCancelListener,OnCancelListener为dialog的取消事件。首先进入onCreate()方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_ACTION_BAR);
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
if (getIntent().getBooleanExtra(KEY_DISMISS_KEYGUARD, false)) {
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
setContentView(R.layout.main);
if (savedInstanceState != null) {
getStateManager().restoreFromState(savedInstanceState);
} else {
if (CheckPermissionActivity.hasUnauthorizedPermission(this)) {
requestPermissions(CheckPermissionActivity.REQUEST_PERMISSIONS,
CheckPermissionActivity.REQUEST_CODE_ASK_PERMISSIONS);
mUnInit = true;
} else {
initializeByIntent();
}
}
}
我们首先查找布局 R.layout.main
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gallery_root"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1a1a1a">
<include layout="@layout/gl_root_group"/>
<FrameLayout android:id="@+id/header"
android:visibility="gone"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout android:id="@+id/footer"
android:visibility="gone"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
布局很简单,由三部分组成,gl_root_group、header、footer,根据名字和布局 可知,header、footer仅为上层的一些自定义布局,Gallery显示功能的布局为
查找布局:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<com.android.gallery3d.ui.GLRootView
android:id="@+id/gl_root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<View android:id="@+id/gl_root_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"/>
</merge>
它有两个布局。第一个是GLRootView,它继承自GLSurfaceView,也就是说它是使用OpenGL ES来绘制界面,它也是整个界面的核心;第二个是View,根据它的id可以看出它是覆盖在GLRootView上的,至于它的作用我们在GLRootView的onDrawFrame方法中可以发现下面这段代码,它是应用第一次绘制界面时覆盖在SurfaceView上面,防止第一次绘制时SurfaceView变透明,影响美观,之后都会隐藏此View。
// We put a black cover View in front of the SurfaceView and hide it
// after the first draw. This prevents the SurfaceView being transparent
// before the first draw.
if (mFirstDraw) {
mFirstDraw = false;
post(new Runnable() {
@Override
public void run() {
View root = getRootView();
View cover = root.findViewById(R.id.gl_root_cover);
cover.setVisibility(GONE);
}
});
}
GLRootView 继承自 GlSurfaceView,实现了GlSurfaceView.Renderer接口,其中的三个方法为核心方法:
@Override
public void onSurfaceCreated(GL10 gl1, EGLConfig config) {//surfaceview创建好调用,绘制工作准备阶段处理一些数据设置相关的工作
GL11 gl = (GL11) gl1;
if (mGL != null) {
// The GL Object has changed
Log.i(TAG, "GLObject has changed from " + mGL + " to " + gl);
}
mRenderLock.lock();
try {
mGL = gl;
mCanvas = ApiHelper.HAS_GLES20_REQUIRED ? new GLES20Canvas() : new GLES11Canvas(gl);
BasicTexture.invalidateAllTextures();
} finally {
mRenderLock.unlock();
}
if (DEBUG_FPS || DEBUG_PROFILE) {
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
} else {
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
}
/**
* Called when the OpenGL surface is recreated without destroying the
* context.
*/
// This is a GLSurfaceView.Renderer callback
@Override
public void onSurfaceChanged(GL10 gl1, int width, int height) {//surfaceview改变时回调此方法,比如横竖屏转换等,这里面一般是重新设置界面size等
Log.i(TAG, "onSurfaceChanged: " + width + "x" + height
+ ", gl10: " + gl1.toString());
Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
GalleryUtils.setRenderThread();
if (DEBUG_PROFILE) {
Log.d(TAG, "Start profiling");
Profile.enable(20); // take a sample every 20ms
}
GL11 gl = (GL11) gl1;
Utils.assertTrue(mGL == gl);
mCanvas.setSize(width, height);
}
@Override
public void onDrawFrame(GL10 gl) {///每绘制一帧都会回调此方法,也就是说你想绘制三角形还是纹理贴图等都是在这方法里面实现
AnimationTime.update();
long t0;
if (DEBUG_PROFILE_SLOW_ONLY) {
Profile.hold();
t0 = System.nanoTime();
}
mRenderLock.lock();
while (mFreeze) {
mFreezeCondition.awaitUninterruptibly();
}
try {//绘制方法
onDrawFrameLocked(gl);
}
catch (NullPointerException e){
//e.printStackTrace();
}
finally {
mRenderLock.unlock();
}
// We put a black cover View in front of the SurfaceView and hide it
// after the first draw. This prevents the SurfaceView being transparent
// before the first draw.
if (mFirstDraw) {
mFirstDraw = false;
post(new Runnable() {
@Override
public void run() {
View root = getRootView();
View cover = root.findViewById(R.id.gl_root_cover);
cover.setVisibility(GONE);
}
});
}
if (DEBUG_PROFILE_SLOW_ONLY) {
long t = System.nanoTime();
long durationInMs = (t - mLastDrawFinishTime) / 1000000;
long durationDrawInMs = (t - t0) / 1000000;
mLastDrawFinishTime = t;
if (durationInMs > 34) { // 34ms -> we skipped at least 2 frames
Log.v(TAG, "----- SLOW (" + durationDrawInMs + "/" +
durationInMs + ") -----");
Profile.commit();
} else {
Profile.drop();
}
}
}
查看onDrawFrameLocked绘制方法
private void onDrawFrameLocked(GL10 gl) {
if (DEBUG_FPS) outputFps();
// release the unbound textures and deleted buffers.
mCanvas.deleteRecycledResources();
// reset texture upload limit
UploadedTexture.resetUploadLimit();
mRenderRequested = false;
/*if ((mOrientationSource != null
&& mDisplayRotation != mOrientationSource.getDisplayRotation())
|| (mFlags & FLAG_NEED_LAYOUT) != 0) {
layoutContentPane();
}*/
if ((mFlags & FLAG_NEED_LAYOUT) != 0) layoutContentPane();
mCanvas.save(GLCanvas.SAVE_FLAG_ALL);
rotateCanvas(-mCompensation);
if (mContentView != null) {
mContentView.render(mCanvas);//mContentView通过canvas渲染定义的view
} else {
// Make sure we always draw something to prevent displaying garbage
mCanvas.clearBuffer();
}
mCanvas.restore();
if (!mAnimations.isEmpty()) {
long now = AnimationTime.get();
for (int i = 0, n = mAnimations.size(); i < n; i++) {
mAnimations.get(i).setStartTime(now);
}
mAnimations.clear();
}
if (UploadedTexture.uploadLimitReached()) {
requestRender();
}
synchronized (mIdleListeners) {
if (!mIdleListeners.isEmpty()) mIdleRunner.enable();
}
if (DEBUG_INVALIDATE) {
mCanvas.fillRect(10, 10, 5, 5, mInvalidateColor);
mInvalidateColor = ~mInvalidateColor;
}
if (DEBUG_DRAWING_STAT) {
mCanvas.dumpStatisticsAndClear();
}
}
GLView是界面显示的UI组件,图库界面是有很多个控件组成的,GLView就是这些控件的基类,它可以渲染到GLCanvas上,并且接受触摸事件。
内部通过 protected void render(GLCanvas canvas) 方法 以及protected void renderChild(GLCanvas canvas, GLView component) 方法实现当前view组件以及子view
组件 在GLCanvas上绘制。
GLCanvas就是一个画布,GLCanvas是一个接口,它最终是使用OpenGL ES的GLES20.glDrawArrays(type, 0, count)来绘制每个GLView,它可以绘制直线、矩形等形状。