Launcher3 壁纸分析

来源:互联网 发布:淘宝定价策略案例 编辑:程序博客网 时间:2024/04/27 23:01

Launcher3 壁纸分析

  • Launcher3 壁纸分析
    • WallpaperPickerActivity结构
      • 1 父类WallpaperCropActivity
      • 2 布局文件wallpaper_pickerxml
    • 初始化流程
      • 1 加载壁纸列表
        • 11 系统壁纸
        • 12 图库壁纸
        • 13 动态壁纸
      • 2 加载图库壁纸按键
      • 3 Actionbar的初始化和响应
      • 4 点击事件

1. WallpaperPickerActivity结构

1.1 父类WallpaperCropActivity

WallpaperPickerActivity是WallpaperCropActivity的派生类。当前者执行onCreate()时,它会调用父类的onCreate(),在父类执行onCreate()时又会调用init(),而WallpaperPickerActivity复写了init()方法,故又回到自己的init()中。
图1

1.2 布局文件wallpaper_picker.xml

在init()方法中,对布局文件wallpaper_picker.xml中的许多控件进行了初始化。以下是wallpaper_picker.xml的部分代码。

<com.android.launcher3.WallpaperRootView    android:id="@+id/wallpaper_root">    <com.android.launcher3.CropView        android:id="@+id/cropView"/>    <ProgressBar        android:id="@+id/loading"/>    <LinearLayout        android:id="@+id/wallpaper_strip">        <View            android:layout_width="match_parent"            android:layout_height="2dp"            android:background="@drawable/tile_shadow_top" />        <HorizontalScrollView            android:id="@+id/wallpaper_scroll_container">            <LinearLayout android:id="@+id/master_wallpaper_list">                <LinearLayout android:id="@+id/wallpaper_list"/>                <LinearLayout android:id="@+id/live_wallpaper_list"/>                <LinearLayout android:id="@+id/third_party_wallpaper_list"/>            </LinearLayout>        </HorizontalScrollView>        <View            android:layout_width="match_parent"            android:layout_height="2dp"            android:background="@drawable/tile_shadow_bottom" />    </LinearLayout></com.android.launcher3.WallpaperRootView>

com.android.launcher3.CropView是一个自定义View,用于显示壁纸大图。
HorizontalScrollView下面有一个LinearLayout,master_wallpaper_list,它又有两个子Layout,wallpaper_list和live_wallpaper_list,third_party_wallpaper_list节点已经被移除。

布局中各节点的位置如下图所示:

图2

在图 2中,壁纸大图对应的是CropView,常规壁纸对应wallpaper_list的LinearLayout,而动态壁纸则是live_wallpaper_list。

2. 初始化流程

2.1 加载壁纸列表

在init()方法中,系统壁纸和用户从图库中选择过的壁纸会被加载到视图中,下列三小节会描述这三种壁纸的加载过程。

2.1.1 系统壁纸

在init()中,先从findBundledWallpapers()中获取一个WallpaperTileInfo类型的ArrayList。在findBundledWallpapers()中,需要从资源中获取壁纸。根据/WallpaperPicker/res/values-nodpi/wallpapers.xml中的wallpapers数组,把壁纸资源生成WallpaperTileInfo对象加入到ArrayList中。

2.1.2 图库壁纸

用户如果在图库中选择过壁纸,那么在init过程中,我们还要读取那些用户选择的壁纸,并把它们加入到壁纸图块列表中。

mSavedImages是一个SavedWallpaperImages对象,该类时BaseAdapter的派生类,在loadThumbnailsAndImageIdList()方法中,把壁纸从数据库中加载到Adapter中,然后再通过。populateWallpapersFromAdapter()方法把图片列表加入到父布局中。

mSavedImages = new SavedWallpaperImages(this);mSavedImages.loadThumbnailsAndImageIdList();populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true);

2.1.3 动态壁纸

动态壁纸的加载方式与前两种壁纸稍有区别。因为加载动态壁纸所需要的时间更长,所以对LiveWallpaperListAdapter对象注册了DataSetObserver。在动态壁纸列表的数据加载完成时会调用DataSetObserver的onChanged()回调方法,把壁纸图块加入LinearLayout中。

2.2 加载图库壁纸按键

在上述几种类型的壁纸加载完成后,列表中还要加载一个从图库中选择壁纸的按键,这个按键是动态加入到LinearLayout中的,所以在wallpaper_picker不会出现。
该按键的初始化代码如下:

LinearLayout masterWallpaperList = (LinearLayout)findViewById(R.id.master_wallpaper_list);FrameLayout pickImageTile = (FrameLayout) getLayoutInflater().inflate(R.layout.wallpaper_picker_image_picker_item, masterWallpaperList, false);mPickImageTile = pickImageTile;setWallpaperItemPaddingToZero(pickImageTile);masterWallpaperList.addView(pickImageTile, 0);

可以看到,该按键是以一个FrameLayout的形式加入到壁纸列表中的,与populateWallpapersFromAdapter()方法中的形式相同。
该按键是一个CheckableFrameLayout,顾名思义,这种Layout是可以被点击。它包含了一张图片和一个TextView,具体的布局文件是WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml。上面的代码是把该布局inflate进来作为一个按键并加入到壁纸列表中。

2.3 Actionbar的初始化和响应

在壁纸的初始化过程中,ActionBar的样式被改变了。通过调用actionBar.setCustomView(R.layout.actionbar_set_wallpaper),可以把自定义的布局设置为ActionBar的视图。该布局中是一个AlphaDisableableButton,它重写了View.setEnabled()方法。
ActionBar的点击事件是用于确认当前选择壁纸的。在点击ActionBar后,获取当前选定的图块Info,尝试将其设为壁纸,并finish当前Activity,把结果传回上一个Activity。

2.4 点击事件

在描述点击事件之前,首先看看一个抽象类,WallpaperTileInfo。这个类中有一个View,一个Drawable以及onClick(),onSave()等方法。WallpaperTileInfo有几个派生类,如下图所示:
图3

这些派生类在加载不同类别的壁纸时会有不同的实现。比如PickImageInfo,它代表上文中说到的加载图库壁纸按键的类型。它的onClick()方法中的实现是发一个Intent去打开DocumentsUI,挑选一张壁纸。其他派生类,如果是壁纸的话,onClick()方法中则会根据自己的壁纸信息,计算宽高和坐标,把缩略图对应的大图设为背景,这样用户就可以预览壁纸效果。
在初始化过程中,有一个专门用于壁纸列表的监听器,mThumbnailOnClickListener。它的onClick()方法实现中有如下语句:

WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();if (info == null) {    return;}if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {    selectTile(v);}info.onClick(WallpaperPickerActivity.this);

在前文中提到的populateWallpapersFromAdapter()方法中,所有壁纸图块,包括mPickImageTile,都将此listener作为监听器。这样当他们被点击时,会拥有自己的行为。

0 0
原创粉丝点击