android launcher3方面的书籍,Android Launcher 3 简单分析

最近在学习Android Launcher的相关知识,在github上找到可以在Android studio上编译的Launcher 3代码,地址:https://github.com/rydanliu/Launcher3

Launcher 3的界面主要由SearchDropTargetBar、Workspace、CellLayout、PageIndicator、Hotseat组成。如下图:

80415402_1.png

Launcher 3 最主要的是一个Activity,基本上所有操作都集中在这个Activity上。这个Activity文件为Launcher.java,他的布局文件为launcher.xml。

下面为竖屏的布局文件,路径为res/layout-port/launcher.xml。

1 <?xml version="1.0" encoding="utf-8"?>

2

3

4

5 xmlns:launcher="http://schemas.android.com/apk/res-auto"

6 android:id="@+id/launcher"

7 android:layout_width="match_parent"

8 android:layout_height="match_parent"

9 android:fitsSystemWindows="true">

10

11

12 android:id="@+id/drag_layer"

13

14 android:layout_width="match_parent"

15 android:layout_height="match_parent">

16

17

18 android:id="@+id/focus_indicator"

19 android:layout_width="22dp"

20 android:layout_height="22dp" />

21

22

23

24

25 android:id="@+id/workspace"

26 android:layout_width="match_parent"

27 android:layout_height="match_parent"

28 launcher:defaultScreen="@integer/config_workspaceDefaultScreen"

29 launcher:pageIndicator="@+id/page_indicator">

30

31

32

33 android:id="@+id/hotseat"

34 layout="@layout/hotseat"

35

36 android:layout_width="match_parent"

37 android:layout_height="match_parent" />

38

39

40 android:id="@+id/overview_panel"

41 layout="@layout/overview_panel"

42 android:visibility="gone" />

43

44

46

47 android:id="@+id/page_indicator"

48 layout="@layout/page_indicator"

49 android:layout_width="wrap_content"

50 android:layout_height="wrap_content"

51 android:layout_gravity="center_horizontal" />

52

53

54 android:id="@+id/search_drop_target_bar"

55

56 layout="@layout/search_drop_target_bar" />

57

58

59 android:id="@+id/widgets_view"

60 layout="@layout/widgets_view"

61 android:layout_width="match_parent"

62 android:layout_height="match_parent"

63 android:visibility="invisible" />

64

65

66 android:id="@+id/apps_view"

67 layout="@layout/all_apps"

68 android:layout_width="match_parent"

69 android:layout_height="match_parent"

70 android:visibility="invisible" />

71

72

73

74 android:id="@+id/launcher_overlay_stub"

75 android:layout_width="match_parent"

76 android:layout_height="match_parent"

77 android:inflatedId="@+id/launcher_overlay"

78 android:layout="@layout/launcher_overlay" />

79

SearchDropTargetBar

屏幕最上方有个搜索框,在我们拖动图标的时候,搜索框会替换成“删除“

Workspace

就是屏幕上左右滑的好几屏幕的容器

CellLayout

Workspace里面可以滑动的单独一屏,CellLayout负责图标和小部件的显示和整齐摆放。

PageIndicator

滑动屏幕的时候看见下方的指示器

Hotseat

用来放置比较常用的应用,比如拨号,短信,相机等。

下面介绍几个类

CellLayout类

mCountX 和 mCountY   分别表示 “x方向icon的个数” 和 “y方向icon的个数”

mOccupied 二维数组用来标记每个cell是否被占用,内部类CellInfo为静态类,其对象用于存储cell的基本信息。

DeviceProfile 类

设置各元素布局的padding  。修改workspace的padding使用getWorkspacePadding方法。

1 /** Returns the workspace padding in the specified orientation */

2 Rect getWorkspacePadding(boolean isLayoutRtl) {

3 Rect searchBarBounds = getSearchBarBounds(isLayoutRtl);

4 Rect padding = new Rect();

5 if (isLandscape && transposeLayoutWithOrientation) {

6 // Pad the left and right of the workspace with search/hotseat bar sizes

7 if (isLayoutRtl) {

8 padding.set(hotseatBarHeightPx, edgeMarginPx,

9 searchBarBounds.width(), edgeMarginPx);

10 } else {

11 padding.set(searchBarBounds.width(), edgeMarginPx,

12 hotseatBarHeightPx, edgeMarginPx);

13 }

14 } else {

15 if (isTablet) {

16 // Pad the left and right of the workspace to ensure consistent spacing

17 // between all icons

18 float gapScale = 1f + (dragViewScale - 1f) / 2f;

19 int width = getCurrentWidth();

20 int height = getCurrentHeight();

21 int paddingTop = searchBarBounds.bottom;

22 int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx;

23 int availableWidth = Math.max(0, width - (int) ((inv.numColumns * cellWidthPx) +

24 (inv.numColumns * gapScale * cellWidthPx)));

25 int availableHeight = Math.max(0, height - paddingTop - paddingBottom

26 - (int) (2 * inv.numRows * cellHeightPx));

27 padding.set(availableWidth / 2, paddingTop + availableHeight / 2,

28 availableWidth / 2, paddingBottom + availableHeight / 2);

29 } else {

30 // Pad the top and bottom of the workspace with search/hotseat bar sizes

31

32 padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,

33 searchBarBounds.bottom,

34 desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right,

35 hotseatBarHeightPx + pageIndicatorHeightPx);

36

37

38 }

39 }

40 return padding;

41 }

比如我要将workspace里图标顶部不留空隙,需要设置padding.set的第二个参数为0.

1 padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,

2 0,//searchBarBounds.bottom,

3 desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right,

4 hotseatBarHeightPx + pageIndicatorHeightPx);

InvariantDeviceProfile类

getPredefinedDeviceProfiles方法 负责加载在不同设备上不同的布局,和图标大小等。

1 ArrayList getPredefinedDeviceProfiles() {

2 ArrayList predefinedDeviceProfiles = new ArrayList<>();

3 // width, height, #rows, #columns, #folder rows, #folder columns,

4 // iconSize, iconTextSize, #hotseat, #hotseatIconSize, defaultLayoutId.

5 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Super Short Stubby",

6 255, 300, 2, 3, 2, 3, 3, 48, 13, 3, 48, R.xml.default_workspace_4x4));

7 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Shorter Stubby",

8 255, 400, 3, 3, 3, 3, 3, 48, 13, 3, 48, R.xml.default_workspace_4x4));

9 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Short Stubby",

10 275, 420, 3, 4, 3, 4, 4, 48, 13, 5, 48, R.xml.default_workspace_4x4));

11 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Stubby",

12 255, 450, 3, 4, 3, 4, 4, 48, 13, 5, 48, R.xml.default_workspace_4x4));

13 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus S",

14 296, 491.33f, 4, 4, 4, 4, 4, 48, 13, 5, 48, R.xml.default_workspace_4x4));

15 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 4",

16 335, 567, 4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 5, 56, R.xml.default_workspace_4x4));

17

18

19

20 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 5",

21 359, 567, 4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 5, 56, R.xml.default_workspace_4x4));

22 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Large Phone",

23 406, 694, 5, 5, 4, 4, 4, 64, 14.4f, 5, 56, R.xml.default_workspace_5x5));

24 // The tablet profile is odd in that the landscape orientation

25 // also includes the nav bar on the side

26 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 7",

27 575, 904, 5, 6, 4, 5, 4, 72, 14.4f, 7, 60, R.xml.default_workspace_5x6));

28 // Larger tablet profiles always have system bars on the top & bottom

29 predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 10",

30 727, 1207, 5, 6, 4, 5, 4, 76, 14.4f, 7, 64, R.xml.default_workspace_5x6));

31 predefinedDeviceProfiles.add(new InvariantDeviceProfile("20-inch Tablet",

32 1527, 2527, 7, 7, 6, 6, 4, 100, 20, 7, 72, R.xml.default_workspace_4x4));

33 return predefinedDeviceProfiles;

34 }

比如我在上面代码的17行加入下列代码,将Hotseat设置成3格,图标大小为72dp

1 predefinedDeviceProfiles.add(new InvariantDeviceProfile("MX 4",

2 359, 567, 4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 3, 72, R.xml.default_workspace_4x4));

由于launcher是有许多自定义控件构成的,这里涉及到onMesure,onLayout,onDraw方法的复写

onMesure方法顾名思义,主要是用来重新测量自定义控件的高度和宽度,就是设置它的dimesion,一般所有自定义VIEW都需要复写这个方法。

onLayout则主要是ViewGroup需要复写这个方法,其作用给这个ViewGroup下子View布局好显示的位置。

onDraw则是需要真真正正画出内容的控件需要复写的方法,比如textview,或者其子类,其最终利用一个很重要的类Canvas的对象来实现一系列的画图,比如canvas.drawcircle,canvas.drawline.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值