精华内容
下载资源
问答
  • 图库源码
    2021-06-04 02:21:48

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

    1

    2 android:configChanges="keyboardHidden|orientation|screenSize">

    3

    4

    5

    6

    7

    8

    找到GalleryActivity,它继承自AbstractGalleryActivity,实现OnCancelListener,OnCancelListener暂时不用考虑,它只是处理dialog防止内存泄漏,我们首先查看onCreate方法

    1 @Override2 protected voidonCreate(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

    2 android:id="@+id/gallery_root"

    3 android:orientation="vertical"

    4 android:layout_width="match_parent"

    5 android:layout_height="match_parent">

    6

    7

    8 android:visibility="gone"

    9 android:layout_alignParentTop="true"

    10 android:layout_width="match_parent"

    11 android:layout_height="wrap_content"/>

    12

    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

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

    1

    2

    4 android:layout_width="match_parent"

    5 android:layout_height="match_parent"/>

    6

    7 android:layout_width="match_parent"

    8 android:layout_height="match_parent"

    9 android:background="@android:color/black"/>

    10

    它有两个布局。第一个是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 it2 //after the first draw. This prevents the SurfaceView being transparent3 //before the first draw.

    4 if(mFirstDraw) {5 mFirstDraw = false;6 post(newRunnable() {7 @Override8 public voidrun() {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 extendsGLSurfaceView2 implementsGLSurfaceView.Renderer, GLRoot {3 @Override4 public voidonSurfaceCreated(GL10 gl1, EGLConfig config) {5 //Suface创建好会回调此方法,一般这个方法都是做些绘制界面的准备工作

    6 }7

    8 @Override9 public void onSurfaceChanged(GL10 gl1, int width, intheight) {10 //Suface改变时回调此方法,比如横竖屏转换等,这里面一般是重新设置界面size等

    11 }12

    13 @Override14 public voidonDrawFrame(GL10 gl) {15 //每绘制一帧都会回调此方法,也就是说你想绘制三角形还是纹理贴图等都是在这方法里面实现。

    16

    17 try{18 //这个方法是实际绘制界面的

    19 onDrawFrameLocked(gl);20 } finally{21 mRenderLock.unlock();22 }23 }24 }

    我们接着查看onDrawFrameLocked方法

    1 private voidonDrawFrameLocked(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的细节后面再详解。

    更多相关内容
  • 数码图库源码例程程序结合易语言扩展界面支持库,可以查看、更换、删除图片,还可以图片改名。图片翻页支持键盘左右光标键,主窗口右键菜单修改密码及备份管理,初始密码:8888。本易语言源码例程属于易语言初级教程...
  • android系统图库源码
  • 数码图库源码例程程序结合易语言扩展界面支持库,可以查看、更换、删除图片,还可以图片改名。图片翻页支持键盘左右光标键,主窗口右键菜单修改密码及备份管理,初始密码:8888。本易语言源码例程属于易语言初级教程...
  • Android系统软件图库源码-0积分下载 个人代码空间:http://download.csdn.net/user/chillax_li
  • 数码图库源码例程程序结合易语言扩展界面支持库,可以查看、更换、删除图片,还可以图片改名。图片翻页支持键盘左右光标键,主窗口右键菜单修改密码及备份管理,初始密码:8888。本易语言源码例程属于易语言初级教程...
  • 1、载入效果非常漂亮 2、支持幻灯片播放 3、超炫的动画效果 4、图片自动分类 5.界面美观。
  • 首发好看的响应式高端网站模板源码图库素材 资源下载平台源码(可运营)可用于做娱乐网资源网,功能非常的齐全无任何加密也无任何后门!响应式高端网站模板源码图库素材 资源下载平台源码 页面很美观,堪比大型网站...
  • android4.3图库源码

    2014-08-28 14:27:06
    资源为android4.3的图库源码,架包已配置好,直接导入Eclipse(需要JNI环境,否则有序功能可能报错)即可运行。
  • 简单图库源码

    2014-08-08 10:47:28
    简单实现图库功能,宝库图片文件夹展示,图片流展示,图片单个显示左右滑动切换
  • //根据PATH的前缀获取mSourceMap对应的MediaSource,mSourceMap初始化在源码分析2中讲过,这里返回的就是ComboSource MediaSource source = mSourceMap. get (path.getPrefix()); ...... try { //走到这里...

    转载请注明出处: http://blog.csdn.net/lb377463323/article/details/69569133

    前面分析Gallery启动流程时,说了传给DataManager的data的key是AlbumSetPage.KEY_MEDIA_PATH,value值,是”/combo/{/local/all,/picasa/all}”,下面分析具体怎么加载数据的。

    数据加载的准备阶段

    数据初始化是在AlbumSetPage的initializeData方法中。

    private void initializeData(Bundle data) {
            //mediaPath即为"/combo/{/local/all,/picasa/all}"
            String mediaPath = data.getString(AlbumSetPage.KEY_MEDIA_PATH);
            //获取MediaSet来管理一组媒体数据
            mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath);
            /mSelectionManager用于管理选择事件
            mSelectionManager.setSourceMediaSet(mMediaSet);
            //mAlbumSetDataAdapter类似于桥梁来连接页面和数据源
            mAlbumSetDataAdapter = new AlbumSetDataLoader(
                    mActivity, mMediaSet, DATA_CACHE_SIZE);
            //设置数据加载的监听接口
            mAlbumSetDataAdapter.setLoadingListener(new MyLoadingListener());
            mAlbumSetView.setModel(mAlbumSetDataAdapter);
        }

    mActivity.getDataManager()就是获取Application(GalleryAppImpl)的DataManager,我们接着看getMediaSet方法,

    //根据路径获取MediaObject,s为"/combo/{/local/all,/picasa/all}"
    public MediaSet getMediaSet(String s) {
            return (MediaSet) getMediaObject(s);
        }
    
    public MediaObject getMediaObject(String s) {
            return getMediaObject(Path.fromString(s));
        }
    
    //进到PATH类中
    private WeakReference<MediaObject> mObject;
    private IdentityCache<String, Path> mChildren;
    
    public static Path fromString(String s) {
            synchronized (Path.class) {
                String[] segments = split(s);
                //segments为["combo", "{/local/all,/picasa/all}"]
                Path current = sRoot;
                for (int i = 0; i < segments.length; i++) {
                    current = current.getChild(segments[i]);
                }
                //经过for循环,current会持有两条路径,"combo"为父PATH,"{/local/all,/picasa/all}"为子PATH
                return current;
            }
        }
    
    //获取PATH对应得MediaObject
    public MediaObject getMediaObject(Path path) {
            synchronized (LOCK) {
                //根据PATH获取MediaObject,不为空直接返回
                MediaObject obj = path.getObject();
                if (obj != null) return obj;
    
                //根据PATH的前缀获取mSourceMap对应的MediaSource,mSourceMap初始化在源码分析2中讲过,这里返回的就是ComboSource
                MediaSource source = mSourceMap.get(path.getPrefix());
                ......
    
                try {
                    //走到这里说明MediaObject为空,所以需要创建MediaObject
                    MediaObject object = source.createMediaObject(path);
                    return object;
                ......
            }
        }

    我们接着看下ComboSource的createMediaObject方法

    public MediaObject createMediaObject(Path path) {
            //segments为["combo", "{/local/all,/picasa/all}"]
            String[] segments = path.split();
            ......
            //match结果为COMBO_ALBUMSET
            switch (mMatcher.match(path)) {
                //创建一个ComboAlbumSet并返回,dataManager.getMediaSetsFromString(segments[1])这个方法就是根据"{/local/all,/picasa/all}"创建LocalSource实例和PicasaSource实例以及对应的LocalAlbumSet实例和EmptyAlbumSet实例,这个过程就是重复上述步骤
                case COMBO_ALBUMSET:
                    return new ComboAlbumSet(path, mApplication,
                            dataManager.getMediaSetsFromString(segments[1]));
            ......
        }

    创建好后,最终返回给AlbumSetPage的initializeData方法中的mMediaSet

    private void initializeData(Bundle data) {
            ......
            //mMediaSet就是ComboAlbumSet,也就是数据源,它管理着LocalAlbumSetEmptyAlbumSet
            mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath);
    
            mSelectionManager.setSourceMediaSet(mMediaSet);
            //mAlbumSetDataAdapter类似于桥梁来连接页面和数据源
            mAlbumSetDataAdapter = new AlbumSetDataLoader(
                    mActivity, mMediaSet, DATA_CACHE_SIZE);
            mAlbumSetDataAdapter.setLoadingListener(new MyLoadingListener());
            将mAlbumSetDataAdapter传给界面显示的渲染器
            mAlbumSetView.setModel(mAlbumSetDataAdapter);
        }

    setModel这个方法挺重要的,它在AlbumSetSlotRenderer中,我们具体看一下

        public void setModel(AlbumSetDataLoader model) {
            ......
            if (model != null) {
                //根据model创建AlbumSetSlidingWindow,它是负责滑动显示图片的,比如解码专辑缩略图等
                mDataWindow = new AlbumSetSlidingWindow(
                        mActivity, model, mLabelSpec, CACHE_SIZE);
                //设置监听接口,处理尺寸改变或内容改变的事件
                mDataWindow.setListener(new MyCacheListener());
                mSlotView.setSlotCount(mDataWindow.size());
            }
        }

    到这里数据源和数据源适配器都创建好了,并且也传给了AlbumSetPage页面,这样数据加载的准备工作就做好了,也就是onCreate方法执行结束,下面分析onResume方法,这里完成数据的实际加载过程。

    数据加载过程

    首先查看GalleryActivity的OnResume方法,

    protected void onResume() {
            //调用其父类的OnResume方法
            super.onResume();
            }
        }

    我们接着查看AbstractGalleryActivity的的OnResume方法

    protected void onResume() {
            ......
            try {
                //数据加载的核心在这里
                getStateManager().resume(); 
                //这个方法只有LocalSource获取ContentProvider,别的都是什么操作都没有
                getDataManager().resume();
            } 
            mGLRootView.onResume();
            mOrientationManager.resume();
        }

    StateManager().resume的方法如下:

        public void resume() {
            //我们是从桌面图标进的应用,所以getTopState获取的是AlbumSetPage
            if (!mStack.isEmpty()) getTopState().resume();
        }

    我们看一下AlbumSetPage的resume方法,AlbumSetPage没有重写resume方法,所以调用的是其父类ActivityState的resume方法,我们先看一下

    void resume() {
            ......
            //这里就是调用AlbumSetPage的onResume方法
            onResume();
            ......
        }
    
        public void onResume() {
            ......
            //数据加载就是这一步完成的
            mAlbumSetDataAdapter.resume();
            ......

    前面讲了mAlbumSetDataAdapter是一个AlbumSetDataLoader类,所以我们去看AlbumSetDataLoader的resume方法

        public void resume() {
            //这个接口是数据变化的监听接口,当完成数据加载时会回调mSourceListener的onContentDirty方法
            mSource.addContentListener(mSourceListener);
            //ReloadTask就是完成数据加载任务的子线程
            mReloadTask = new ReloadTask();
            mReloadTask.start();
        }

    我们看一下ReloadTask的run方法

    public void run() {
        ......
        //这里执行数据加载
        long version = mSource.reload();
        ......
    }
    
    mSource是new AlbumSetDataLoader(
                    mActivity, mMediaSet, DATA_CACHE_SIZE)传入的mMediaSet,前面讲了mMediaSet就是ComboAlbumSet,它包含一个LocalAlbumSet和EmptyAlbumSet

    我们去ComboAlbumSet类中查看它的reload方法

        public long reload() {
            //mSets即为ComboAlbumSet所包含的LocalAlbumSet和EmptyAlbumSet,这里也就是分别调用LocalAlbumSet和EmptyAlbumSet的reload方法
            for (int i = 0, n = mSets.length; i < n; ++i) {
                long version = mSets[i].reload();
        ......

    因为EmptyAlbumSet的reload方法就是返回数据版本,所以暂且不管它。下面只分析LocalAlbumSet的reload方法。

    public synchronized long reload() {
            ......
            //通过ThreadPool线程池执行专辑数据的加载,AlbumsLoader方法看下面讲述
            mLoadTask = mApplication.getThreadPool().submit(new AlbumsLoader(), this);
            //这里就是对每个专辑进行数据加载,这之后的就不讲了
            for (MediaSet album : mAlbums) {
                    album.reload();
            }

    submit方法就是把job和listener封装成一个Worker,然后传给ThreadPoolExecutor执行

    public <T> Future<T> submit(Job<T> job, FutureListener<T> listener) {
            Worker<T> w = new Worker<T>(job, listener);
            mExecutor.execute(w);
            return w;
        }

    ThreadPoolExecutor的execute方法最终也是执行Worker的run方法,现在看下Worker的run方法

    public void run() {
        ......
        //mJob就是submit传进来的new AlbumsLoader()        
        result = mJob.run(this);
        ......
        //mListener是FutureListener接口,这里也就是LocalAlbumSet自身
        if (mListener != null) mListener.onFutureDone(this);
    }

    接着看下AlbumsLoader的run方法,这里主要是获取专辑的信息

    private class AlbumsLoader implements ThreadPool.Job<ArrayList<MediaSet>> {
    
            @Override
            @SuppressWarnings("unchecked")
            public ArrayList<MediaSet> run(JobContext jc) {
                ......
                //通过BucketHelper获取所有的专辑信息
                BucketEntry[] entries = BucketHelper.loadBucketEntries(
                        jc, mApplication.getContentResolver(), mType);
            ......
            for (BucketEntry entry : entries) {
                    //获取LocalAlbum并保存到ArrayList(albums)中,albums对应于每个专辑
                    MediaSet album = getLocalAlbum(dataManager,
                            mType, mPath, entry.bucketId, entry.bucketName);
                    albums.add(album);
                }

    当AlbumsLoader的run方法执行完后,接着执行mListener.onFutureDone回调接口,通过这个接口通知MediaSet内容有变化。最终会走到AlbumSetDataLoader的onContentDirty方法

        public void onContentDirty() {
                //这个方法会唤醒所以wait的线程
                mReloadTask.notifyDirty();
            }

    现在我们回到AlbumSetDataLoader的ReloadTask中,reload方法执行之后会通过updateLoading发送MSG_LOAD_FINISH消息

    while (mActive) {
        ......
        //这一块很重要,用来更新界面的
        //获取需要更新的数据信息,包括专辑数量等,这里我不细讲了,自己看代码
        UpdateInfo info = executeAndWait(new GetUpdateInfo(version));
        ......
        //根据数据信息更新界面,这个方法最终会执行UpdateContent的call方法
        executeAndWait(new UpdateContent(info));
    }
    
    //这个方法发送 MSG_LOAD_FINISH消息通知数据加载完成,这里不细讲了
    updateLoading(false);

    更新界面

    private class UpdateContent implements Callable<Void> {
        public Void call() {
            //这里是更新Slot数目
            if (mDataListener != null) mDataListener.onSizeChanged(mSize);
            ......
            //更新内容
            mDataListener.onContentChanged(info.index);
        }
    }

    mDataListener是实例化AlbumSetSlidingWindow是设置的,也就是AlbumSetSlidingWindow自身

    source.setModelListener(this);

    接着看AlbumSetSlidingWindow的onSizeChanged和onContentChanged方法

        public void onSizeChanged(int size) {
            if (mIsActive && mSize != size) {
                mSize = size;
                //mListener是AlbumSetSlotRenderer的,MyCacheListener,onSizeChanged就是执行mSlotView.setSlotCount(size)
                if (mListener != null) mListener.onSizeChanged(mSize);
                if (mContentEnd > mSize) mContentEnd = mSize;
                if (mActiveEnd > mSize) mActiveEnd = mSize;
            }
        }
    
        public void onContentChanged(int index) {
            //更新图像
            AlbumSetEntry entry = mData[index % mData.length];
            updateAlbumSetEntry(entry, index);
            updateAllImageRequests();
            updateTextureUploadQueue();
            //onContentChanged方法就是执行mSlotView.invalidate()刷新界面
            if (mListener != null && isActiveSlot(index)) {
                mListener.onContentChanged();
            }
        }

    到这里就完成了SlotView的渲染准备工作,至于怎么渲染到屏幕上见Gallery图库源码分析6

    展开全文
  • 2021精仿站长素材源码交易网站平台源码 带安装教程+PC+WAP+10套模板+全套数据 安装教程+效果演示:http://www.songzifc.cn/post/7819.html 全面SEO布局优化,特别有利于搜索引擎抓取,想要的童鞋们快下手吧
  • android自带图库源码

    2012-12-18 16:08:47
    android自带的图库源码,喜欢研究源码的童鞋不要错过哦
  • Android2.3 3D系统图库源码,有需要的可以慢慢研究下
  • ASP源码,压缩包解压密码:www.cqlsoft.com
  • Android系统图库源码

    热门讨论 2011-12-09 21:48:04
    Android系统图库源码、Android系统图库源码、Android系统图库源码
  • Android系统自带的图库源码

    热门讨论 2012-03-03 10:33:19
    Android系统自带的图库源码 适用于android2.3以上的系统
  • Android 4.0图库源码 Gallery3D 2 可运行

    热门讨论 2013-07-01 17:02:24
    Android 4.0图库源码 Gallery3D 2 可运行
  • 最先发行漂亮的回应式高档网站模板源码图库素材 资源下载平台源码(可运营)适用于做娱乐网资源网功能非常的完全无任何+密也无任何后门!回应式高档网站模板源码图库素材 资源下载平台源码页面很漂亮大方,堪比大型...
  • 上篇文章讲了初始化View时会实例化一个SlotView并监听其事件,至于它是怎么实现的,用的是Android自带的GestureDetector。 GestureDetector是Android自带的用来监听各种用户手势的的一个类,比如监听单击、双击和...

    上篇文章讲了初始化View时会实例化一个SlotView并监听其事件,至于它是怎么实现的,用的是Android自带的GestureDetector。

    GestureDetector是Android自带的用来监听各种用户手势的的一个类,比如监听单击、双击和长按等操作。关于GestureDetector的详解可以参考此文章用户手势检测-GestureDetector使用详解

    SlotView中定义了一个GestureDetector。

    1 private final GestureDetector mGestureDetector;
    2 
    3 public SlotView(AbstractGalleryActivity activity, Spec spec) {
    4         //给GestureDetector传入我们自定义的Listener接口
    5         mGestureDetector = new GestureDetector(activity, new MyGestureListener());
    6         ......
    7     }

    然后在onTouch中拦截SlotView的触摸事件并交给GestureDetector处理

    1    @Override
    2     protected boolean onTouch(MotionEvent event) {
    3         ......
    4         mGestureDetector.onTouchEvent(event);
    5         ......
    6         //必须返回true,不然监听不到完整事件
    7         return true;
    8     }

    至于GestureDetector的监听事件怎么和SlotView的Listener绑定到一起的?我们看一下自定义的MyGestureListener接口,它就是实现了GestureDetector的OnGestureListener接口。

     1 private class MyGestureListener implements GestureDetector.OnGestureListener {
     2         ......
     3         //点击一次
     4         @Override
     5         public boolean onSingleTapUp(MotionEvent e) {
     6             ......
     7             //获取点击的相册索引
     8             int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
     9             //处理点击事件
    10             if (index != INDEX_NONE) mListener.onSingleTapUp(index);
    11             return true;
    12         }
    13 }

    从上述代码可以看出当GestureDetector监测到点击事件时会回调onSingleTapUp方法,在这个方法里我们对点击事件进行处理。上面的mListener就是SlotView中的Listener接口,这样就将GestureDetector的监听事件和SlotView的Listener绑定到一起了。所以每次接收到触摸事件时最终都会传给SlotView的Listener处理,至于SlotView的Listener具体怎么实现每个ActivityState页面都不一样,比如AlbumSetPage中就是如下实现的,最后会调用AlbumSetPage对应的方法来处理触摸事件

     1 private void initializeViews() {
     2     mSlotView.setListener(new SlotView.SimpleListener() {
     3             @Override
     4             public void onDown(int index) {
     5                 AlbumSetPage.this.onDown(index);
     6             }
     7 
     8             @Override
     9             public void onUp(boolean followedByLongPress) {
    10                 AlbumSetPage.this.onUp(followedByLongPress);
    11             }
    12 
    13             @Override
    14             public void onSingleTapUp(int slotIndex) {
    15                 AlbumSetPage.this.onSingleTapUp(slotIndex);
    16             }
    17 
    18             @Override
    19             public void onLongTap(int slotIndex) {
    20                 AlbumSetPage.this.onLongTap(slotIndex);
    21             }
    22         });
    23 }

    现在手势监听流程已经讲解完了,下面讲一下界面的跳转,我们找到AlbumSetPage的onSingleTapUp方法

     1 public void onSingleTapUp(int slotIndex) {
     2         if (mSelectionManager.inSelectionMode()) {
     3             ......
     4         } else {
     5             //显示动画
     6             mAlbumSetView.setPressedIndex(slotIndex);
     7             mAlbumSetView.setPressedUp();
     8             //通过Handler发送消息,msg.arg1是slotIndex,也就是点击的相册索引
     9             mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_ALBUM, slotIndex, 0),
    10                     FadeTexture.DURATION);
    11         }
    12     }

    Handler的handleMessage方法在AlbumSetPage的onCreate方法中

     1 mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
     2             @Override
     3             public void handleMessage(Message message) {
     4                 switch (message.what) {
     5                     case MSG_PICK_ALBUM: {
     6                         //跳转到相册
     7                         pickAlbum(message.arg1);
     8                         break;
     9                     }
    10                     default: throw new AssertionError(message.what);
    11                 }
    12             }
    13         };

    我们看一下pickAlbum的代码,

     1 private void pickAlbum(int slotIndex) {
     2     ......
     3     if (mGetAlbum && targetSet.isLeafAlbum()) {
     4             ......
     5         } else if (targetSet.getSubMediaSetCount() > 0) {
     6             ......
     7         } else {
     8             ......
     9             data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath);
    10 
    11             // We only show cluster menu in the first AlbumPage in stack
    12             boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class);
    13             data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum);
    14             //通过StateManager跳转到AlbumPage类中,跟应用的启动流程差不多
    15             mActivity.getStateManager().startStateForResult(
    16                     AlbumPage.class, REQUEST_DO_ANIMATION, data);
    17         }
    18 }

    通过上述代码可以看出页面Gallery的页面跳转都是通过StateManager来管理的。如果从相册点击进入某一张图片,跳转逻辑也跟着一样,看下AlbumPage的handleMessage方法就知道了。

    转载于:https://www.cnblogs.com/zhao-shan/p/9838417.html

    展开全文
  • 这里接着Gallery图库源码分析3的SlotView渲染准备完成后讲解,前面讲了当数据准备完成后,通过mListener.onContentChanged()通知界面更新。

    转载请注明出处: http://blog.csdn.net/lb377463323/article/details/70275971

    这里接着Gallery图库源码分析3的SlotView渲染准备完成后讲解,前面讲了当数据准备完成后,通过mListener.onContentChanged()通知界面更新。mListener就是AlbumSetSlotRenderer的MyCacheListener。

        //也就是SlotView刷新界面
        public void onContentChanged() {
                mSlotView.invalidate();
        }
    
        //root即为GLRootView,它是继承自GLSurfaceView
        public void invalidate() {
            GLRoot root = getGLRoot();
            if (root != null) root.requestRender();
        }

    root.rerequestRender就是请求渲染一帧数据,之后走到Renderer的onDrawFrame方法

        public void onDrawFrame(GL10 gl) {
           //每绘制一帧都会回调此方法,也就是说你想绘制三角形还是纹理贴图等都是在这方法里面实现。
            try {
                //这个方法是实际绘制界面的
                onDrawFrameLocked(gl);
            } finally {
                mRenderLock.unlock();
            }
        }

    接着看下onDrawFrameLocked方法

        private void onDrawFrameLocked(GL10 gl) {
            ......
            //mContentView就是AlbumSetPage
            if (mContentView != null) {
               mContentView.render(mCanvas);
            } else {
            ......
        }

    AlbumSetPage的render方法调用其父类GLView的render方法

        protected void render(GLCanvas canvas) {
                ......
                super.render(canvas);
                canvas.restore();
            }

    GLView的render方法主要是对其自控件进行渲染

        protected void render(GLCanvas canvas) {
            ......
            for (int i = 0, n = getComponentCount(); i < n; ++i) {
                renderChild(canvas, getComponent(i));
            }
    
        protected void renderChild(GLCanvas canvas, GLView component) {
            ......
            //这里component就是SlotView,用于绘制每个专辑
            component.render(canvas);
            ......
        }

    接着看SlotView的render方法

        protected void render(GLCanvas canvas) {
            ......
            for (int i = mLayout.mVisibleEnd - 1; i >= mLayout.mVisibleStart; --i) {
                    //renderItem就是对每一个专辑进行绘制
                    int r = renderItem(canvas, i, 0, paperActive);
                    if ((r & RENDER_MORE_FRAME) != 0) more = true;
                    if ((r & RENDER_MORE_PASS) != 0) requestedSlot[requestCount++] = i;
                }
            ......
        }
    
        private int renderItem(
                GLCanvas canvas, int index, int pass, boolean paperActive) {
            ......
            //mRenderer就是AlbumSetSlotRenderer
            int result = mRenderer.renderSlot(
                    canvas, index, pass, rect.right - rect.left, rect.bottom - rect.top);
            ......
        }

    查看AlbumSetSlotRenderer到额renderSlot方法,这里就是绘制每个专辑的具体实现

        public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) {
            AlbumSetEntry entry = mDataWindow.get(index);
            int renderRequestFlags = 0;
            //绘制专辑显示的缩略图
            renderRequestFlags |= renderContent(canvas, entry, width, height);
            //绘制显示文件夹名称、数目、文件夹icon的Label
            renderRequestFlags |= renderLabel(canvas, entry, width, height);
            //绘制长按选择专辑时的蓝色图层
            renderRequestFlags |= renderOverlay(canvas, index, entry, width, height);
            return renderRequestFlags;
        }

    最终所有专辑都通过canvas绘制出来,canvas是通过OpenGL ES的GLES20.glDrawArrays(type, 0, count)来绘制的,具体自行查看GLES20Canvas类。

    展开全文
  • png图片开源库源码

    2016-12-25 22:39:12
    png图片开源库源码, 包括zlib开源库源码
  • 最新Laravel框架壁纸网图库源码下载+支持图片上传下载,安装环境推荐Linux系统,Apache,php7.1,MySQL 5.6。 特点:Laravel框架,收藏系统,实时通知,图片搜索,按颜色与相机搜索,会可以无限制上传,修改名称、...
  • Menu的显示是通过Activity的onCreateOptionsMenu方法管理的,Gallery项目的Menu管理是在AbstractGalleryActivity类中,Gallery的启动Activity是GalleryActivity,它继承自AbstractGalleryActivity。
  • 系列文章:Android图片加载框架:Glide的常用用法|SquirrelNoteAndroid图片加载框架:Glide源码解析|SquirrelNote前言本篇将从源码角度分析Glide图片加载框架。如下内容:如何阅读源码Glide源码解析如何阅读源码那么...
  • 响应式高端网站模板源码图库素材资源下载平台源码 首发好看的响应式高端网站模板源码图库素材 资源下载平台源码(可运营)可用于做娱乐网资源网 功能非常的齐全无任何加密也无任何后门!响应式高端网站模板源码图库...
  • 网页素材文档图库下载类网站源码+织梦CMS内核,本程序采用一库两站简洁方便管理后台,一个后台管理两网站,电脑版+手机版 程序特点: 1、网站手工DIV+css,代码精简,首页排版整洁大方、布局合理、利于SEO、...
  • 介绍: 之前新浪外链全部加入防盗链 ...api图片开源了 你们喜欢的可以自己搭建 如果感觉维护麻烦的 你也可以用我的接口 每周维护 ...直接上传即可,打开sinetxt.txt添加你想添加的图片 新浪图床后链 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,177
精华内容 2,470
关键字:

图库源码

友情链接: jquerytablehover.rar