您的位置:首页 > 其它

【Launcher2源码解读】Launcher中的自定义控件

2015-03-30 16:53 344 查看
本文对Launcher2进行一个全面的了解,介绍Launcher2中的自定义控件

如图:



launcher.xml

<?xml version="1.0" encoding="utf-8"?>
<com.callmewill.launcher2.DragLayer xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.callmewill.launcher2"
android:id="@+id/drag_layer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/workspace_bg" >    //最外层的自定义布局继承FrameLayout,主要功能手指拖动时生成一个悬浮的view,以及各种位值计算

<include
android:id="@+id/dock_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="@dimen/button_bar_height"
layout="@layout/workspace_divider" />        //底部指示器的背景

<include
android:id="@+id/paged_view_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="@dimen/button_bar_height"
layout="@layout/scroll_indicator" />         //底部指示器

<!-- The workspace contains 5 screens of cells -->

<com.callmewill.launcher2.Workspace              //继承PagedView,SmoothPagedView,实现一个ViewGroup内部有多个View并且左右滑动
android:id="@+id/workspace"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/workspace_bottom_padding"
android:paddingLeft="@dimen/workspace_left_padding"
android:paddingRight="@dimen/workspace_right_padding"
android:paddingTop="@dimen/workspace_top_padding"
launcher:cellCountX="@integer/cell_count_x"
launcher:cellCountY="@integer/cell_count_y"
launcher:defaultScreen="2"
launcher:pageSpacing="@dimen/workspace_page_spacing"
launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right" >

<include
android:id="@+id/cell1"
layout="@layout/workspace_screen" />     //内部的子View,主要类是CellLayout,CellLayout是一个网格的自定义ViewGroup,用来装各种item

<include
android:id="@+id/cell2"
layout="@layout/workspace_screen" />

<include
android:id="@+id/cell3"
layout="@layout/workspace_screen" />

<include
android:id="@+id/cell4"
layout="@layout/workspace_screen" />

<include
android:id="@+id/cell5"
layout="@layout/workspace_screen" />
</com.callmewill.launcher2.Workspace>

<include                                         //底部的Dock栏
android:id="@+id/hotseat"
android:layout_width="match_parent"
android:layout_height="@dimen/button_bar_height_plus_padding"
android:layout_gravity="bottom"
layout="@layout/hotseat" />

<include
android:id="@+id/qsb_bar"                    //顶部的搜索和移目标控件
layout="@layout/qsb_bar" />

<com.callmewill.launcher2.DrawableStateProxyView  //app抽屉,同样继承PagedView
android:id="@+id/voice_button_proxy"
android:layout_width="80dp"
android:layout_height="@dimen/qsb_bar_height"
android:layout_gravity="top|right"
android:clickable="true"
android:onClick="onClickVoiceButton"
launcher:sourceViewId="@+id/voice_button" />

<include
android:id="@+id/apps_customize_pane"       //app抽屉,同样继承PagedView
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/apps_customize_pane"
android:visibility="invisible" />

<include
android:id="@+id/workspace_cling"           //用户引导
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/workspace_cling"
android:visibility="gone" />

<include
android:id="@+id/folder_cling"               //用户引导
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/folder_cling"
android:visibility="gone" />

</com.callmewill.launcher2.DragLayer>


从上往下说吧

搜索条:点击搜索条时调用的系统本身的SearchManager来完成相关逻辑,Launcher.java 中的startGlobleSearch方法:

public void startGlobalSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData, Rect sourceBounds) {
final SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity();
if (globalSearchActivity == null) {
Log.w(TAG, "No global search activity found.");
return;
}
Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setComponent(globalSearchActivity);
// Make sure that we have a Bundle to put source in
if (appSearchData == null) {
appSearchData = new Bundle();
} else {
appSearchData = new Bundle(appSearchData);
}
// Set source to package name of app that starts global search, if not
// set already.
if (!appSearchData.containsKey("source")) {
appSearchData.putString("source", getPackageName());
}
intent.putExtra(SearchManager.APP_DATA, appSearchData);
if (!TextUtils.isEmpty(initialQuery)) {
intent.putExtra(SearchManager.QUERY, initialQuery);
}
if (selectInitialQuery) {
intent.putExtra(SearchManager.EXTRA_SELECT_QUERY, selectInitialQuery);
}
intent.setSourceBounds(sourceBounds);
try {
startActivity(intent);
} catch (ActivityNotFoundException ex) {
Log.e(TAG, "Global search activity not found: " + globalSearchActivity);
}
}


DragLayer.java

——FrameLayout

Workspace.java 手指滑动,在多个屏幕之间切换
——ViewGroup

——PagedView 内部View跟随手指滑动

  ——SmoothPagedView 处理滑动时的速度

——Workspace 完成内容的展示

CellLayout.java 在Workspace中,和Hotseat中,是一个网格状的控件,可以设置行列,span,用来显示app,widget,shortcut,folder等

——ViewGroup

AppCustomsizeTabHost.java

——TabHos t抽屉内部的Tab标签

AppCustomsizePagedView

——ViewGroup

——PagedView

——DragItemPagedVIew 手提内拖拽app到Workspace

Folder.java 展示文件夹内部内容的View,内部包含一个CellLayout

——LinearLayout

FolderIcon.java 文件夹缩略图

——LinearLayout

BubbleTextView.java 用来显示app,shortcut

——TextView

textView.setCompoundDrawablesWithIntrinsicBounds(left,top,right,bottom)给TextView设置上下左右四个图片


PagedViewIcon.java 抽屉内部显示icon

——TextView

Hotseat.java 底部的Dock栏
—— FrameLayout

PagedViewWidget.java 抽屉内部显示Widget

——LinearLayout

AppWidgetResizeFrame.java 重置Widget大小时的指示框

——FrameLayout

LauncherAppWidgetHost.java 显示加载Widget有关

——AppWidgetHost

每个控件的代码量都很大,看起来也费时费力。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: