Android 7.0 Gallery图库源码分析1

摘要:
分析项目的源代码时,首先要查看列表文件并找到程序条目。我们可以从Gallery2源代码的列表文件中看到,GalleryActivity是此应用程序的启动活动=Null){17getStateManager().restoreFromState;18}否则{19//根据Intent类型初始化20initializeByIntent();21}22}我们首先分析布局并找到R.layout。main1671219http://schemas.android.com/apk/res/android“˃2610它有两个布局。

分析一个项目的源代码时,第一件事就是查看清单文件,找到程序入口,我们从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: 
 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: 
 8             android:visibility="gone"
 9             android:layout_alignParentTop="true"
10             android:layout_width="match_parent"
11             android:layout_height="wrap_content"/>
12     <FrameLayout android: 
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: 
 4             android:layout_width="match_parent"
 5             android:layout_height="match_parent"/>
 6     <View android: 
 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的细节后面再详解。

免责声明:文章转载自《Android 7.0 Gallery图库源码分析1》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇本体【Ontology】综述聊聊、Spring ServletContainerInitializer下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Akka源码分析-Remote-发消息

上一篇博客我们介绍了remote模式下Actor的创建,其实与local的创建并没有太大区别,一般情况下还是使用LocalActorRef创建了Actor。那么发消息是否意味着也是相同的呢? 既然actorOf还是委托给了LocalActorRef,那么在本地创建的Actor发消息还是跟以前一样的,那么如果如何给远程的Actor发消息呢?我们一般是通过act...

Hikaricp源码解读(2)——配置介绍及对应源码

2、配置介绍及对应源码 HikariCP的配置类HikariConfig对Properties有很好的兼容,可通过配置环境变量hikaricp.configurationFile设置配置文件路径。 String systemProp = System.getProperty("hikaricp.configurationFile"); if (system...

ubuntu上安装ffmpeg

引用:http://thierry-xing.iteye.com/blog/2017864 安装包和主要步骤: 1. 首先安装系统基础环境 RHEL & CentOS 系列:yum install -y automake autoconf libtool gcc gcc-c++ Debian & Ubuntu 系列:apt-get ins...

ViewPager留出边 显示左右两边的视图

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager_layout" android:layout_w...

Android DecorView浅析

摘要一、DecorView为整个Window界面的最顶层View。 二、DecorView只有一个子元素为LinearLayout。代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域。 三、LinearLayout里有两个FrameLayout子元素。 (20)为标题栏显示界面。只有一个TextView显示应用 (请发邮件到freege...

Android ImageView点击效果

ImageView设置点击效果需要注意两点,第一个设置android:clickable="true",第二个 <item android:drawable="@drawable/button_n"/>属性必须放到最后才能生效<?xml version="1.0" encoding="utf-8"?><!--发现大类列表项--...