第一部分:Launcher APP 组成分析(二)
来源:互联网 发布:黄金白银套利软件 编辑:程序博客网 时间:2024/06/05 07:13
上一章节介绍到Launcher的四大组件组成、Launcher layout xml的组成及使用到的数据库表 favorites | screens
本章简介:
DragLayer组成分析
Workspace及ScreenView组成分析
CellLayout及CellScreen组成分析
Shortcut组成分析
Hotseats组成分析
DeleteZone组成分析
第一部分:Launcher APP组成分析(二)
从Launcher.xml 中看到Launcher的布局由最外层的DragLayer包裹着,中间由Workspace、Hotseats及DeleteZone几个主要组成部件构成。先抛开桌面上的数据如何读取,如果读者希望在自己写代码的过程中有一个直观的显示感受,可以不妨放写图片或者文字来临时填放用于调试运行。
图(1)
1.DragLayer 组成分析:
从组成来讲,DragLayer最重要的部分是用于显示壁纸背景,关于拖动的部分,等到分析到触摸再拿来分析。
壁纸,MIUI系统中将壁纸显示的方式使用SharedPreferences的方式存储。
/** *功能: 桌面背景显示, 从配置表中读取壁纸的显示方式 *调用: 使用于Launcher.java */public void updateWallpaper() {String wallpaperScrollType = PreferenceManager.getDefaultSharedPreferences(mContext).getString("pref_key_wallpaper_scroll_type", "byTheme"); if (wallpaperScrollType.equals("byTheme")){ wallpaperScrollType = getResources().getString(R.string.wallpaper_scrolling); } mWpScrolling = false; if (wallpaperScrollType.equals("left")) { mWpOffsetX = 0F; } else if (wallpaperScrollType.equals("center")) { mWpOffsetX = 0.5F; } else if (wallpaperScrollType.equals("right")) { mWpOffsetX = 1F; } else { mWpScrolling = true; } mLauncher.getWindow().setFormat(PixelFormat.TRANSPARENT);mWallpaper = null;updateWallpaperOffset();}/** *功能: 壁纸显示起点 */public void updateWallpaperOffset() {if (mWallpaper == null) {mWallpaperManager.setWallpaperOffsetSteps(mWpStepX, mWpStepY);if (getWindowToken() == null) {removeCallbacks(OffsetUpdater);postDelayed(OffsetUpdater, 50L);}else {try {WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(getWindowToken(), mWpOffsetX, mWpOffsetY, mWpStepX, mWpStepY);} catch (RemoteException e) { }}}else {int offsetX = (int)((float)(mWpWidth - mScreenSize.x) * mWpOffsetX);if (mOldOffsetX != offsetX) {mOffsetChanged = true;}mOldOffsetX = offsetX;}}public void updateWallpaperOffset(float xStep, float yStep, float xOffset, float yOffset) {if (mWpScrolling && mWpOffsetX != xOffset) {mWpStepX = xStep;mWpStepY = yStep;mWpOffsetX = xOffset;mWpOffsetY = yOffset;updateWallpaperOffset();}}public void updateWallpaperOffsetAnimate(final float xStep, final float yStep, final float xOffset, final float yOffset) {final float xStepDelta = xStep - mWpStepX;final float yStepDelta = yStep - mWpStepY;final float mWpOffsetXDelta = xOffset - mWpOffsetX; final float mWpOffsetYDelta = yOffset - mWpOffsetY; ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f, 0.0f); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float f = ((Float)animation.getAnimatedValue()).floatValue();updateWallpaperOffset(xStep - f * xStepDelta, yStep - f * yStepDelta, xOffset - f * mWpOffsetXDelta, yOffset - f * mWpOffsetYDelta);}}); valueAnimator.start();}
可以看到,Wallpaper在DragLayer中分三种类型“left”, "right", "center" 来显示,根据壁纸的大小来计算X,Y的偏移量,updateWallpaperOffsetAnimate主要是用于拖动时动画显示滑动到指定位置。
2.Workspace及ScreenView组成分析
从代码中可以看到Workspace继承与DragableScreenView,DragableScreenView再继承与ScreenView,由于DragableScreenView主要是用于处理触摸动作,这里暂时不做分析,直接看ScreenView。ScreenView是一个ViewGroup,Workspace如果构成的ViewGroup呢?这里必须要涉及到CellLayout及CellScreen,因为这两个组件才是组成Workspace的Viewgroup的元素。实例图如下:
图(二)
CellScreen.xml的layout:
<cn.minking.launcher.CellScreen android:animationCache="false" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <FrameLayout android:id="@id/background_container" android:visibility="invisible" android:animationCache="false" android:layout_width="fill_parent" android:layout_height="fill_parent"> ...... ...... </FrameLayout> <cn.minking.launcher.CellLayout android:id="@id/cell_layout" android:paddingBottom="@dimen/workspace_cell_padding_bottom" android:animationCache="false" android:layout_width="fill_parent" android:layout_height="fill_parent" /></cn.minking.launcher.CellScreen>
在Launcher的Model将数据读取给CellScreen,然后将每个CellScreen使用addView的方式添加至ViewGroup, 使用 onLayout显示出来,至于详细的步骤会在后续详细的分析。
3. CellScreen | CellLayout组成分析
CellLayout被分割成Horizontal*Vetical个单元格,下图中示为4x4的CellLayout,此处可以根据屏幕的分辨率不同设置不同的大小,比如MIUI现在使用的则是4x5的布局;
图(三)
// 横向及纵向的单元格个数 mHCells = ResConfig.getCellCountX(); mVCells = ResConfig.getCellCountY();
每个单元格的大小及边界距离:
Resources resources = context.getResources(); mCellWidth = resources.getDimensionPixelSize(R.dimen.workspace_cell_width); mCellHeight = resources.getDimensionPixelSize(R.dimen.workspace_cell_height); mWidgetCellPaddingTop = resources.getDimensionPixelSize(R.dimen.workspace_widget_padding_top); mWidgetCellPaddingBottom = resources.getDimensionPixelSize(R.dimen.workspace_widget_padding_bottom); mPaddingTop = resources.getDimensionPixelSize(R.dimen.workspace_padding_top); mPaddingLeft = resources.getDimensionPixelSize(R.dimen.workspace_padding_side); mPaddingRight = mPaddingLeft;
一个View控件可以占有单个单元格,比如APP图标或者Shortcut快捷方式,也可以一个View控件占有多个单元格,比如2x2的时钟,或者4x4的时钟。
// 标识单元格视图的二维数组 int ai[] = new int[]{mHCells, mVCells}; int aiBak[] = new int[]{mHCells, mVCells}; mOccupiedCell = (View[][])Array.newInstance(View.class, ai); mOccupiedCellBak = (View[][])Array.newInstance(View.class, aiBak);
此部分和原生的Android的launcher是类似的,原生的launcher使用的pagedview,同样是继承与ViewGroup,同样也使用了CellLayout,区别是MIUI多了CellScreen,为何这么做?由于MIUI是单界面操作,所以在桌面需要更多的操作,比如进入Widget编辑模式。
4. ShortCut组成分析:
这部分本应该是需要和Widget一起分析,但是MIUI中增加了Gadget,涉及到主题资源的引入,所以在此我们先不分析Widget。
Launcher.java中创建Shortcut布局的接口,看到调用的是application layout
Launcher.java /** * 功能: 以Layout application为样式创建快捷方式的布局 * @param viewgroup * @param shortcutinfo * @return */ private ShortcutIcon createShortcutIcon(ViewGroup viewgroup, ShortcutInfo shortcutinfo){ return ShortcutIcon.fromXml(R.layout.application, this, viewgroup, shortcutinfo); } ShortcutIcon.java /** * 功能: 从XML中的得到快捷图标的布局 * @param layout * @param launcher * @param viewgroup * @param shortcutinfo * @return */static ShortcutIcon fromXml(int layout, Launcher launcher, ViewGroup viewgroup, ShortcutInfo shortcutinfo){ShortcutIcon shortcutIcon = (ShortcutIcon)LayoutInflater.from(launcher).inflate(layout, viewgroup, false);shortcutIcon.updateInfo(launcher, shortcutinfo); return shortcutIcon;}
application.xml
<cn.minking.launcher.ShortcutIcon android:background="@drawable/shortcut_selector" android:focusable="true" android:animationCache="false" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 图标阴影 --> <include layout="@layout/icon_shadow" /> <!-- 创建文件夹时显示的背景 --> <ImageView android:layout_gravity="top|center" android:id="@id/icon_folder_creation_bg" android:visibility="invisible" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/icon_side_margin" android:layout_marginRight="@dimen/icon_side_margin" android:src="@drawable/icon_folder" android:scaleType="centerInside" /> <!-- 图标 --> <include layout="@layout/icon_icon" /> <!-- 标题 --> <include layout="@layout/icon_title" /> <!-- 消息个数 --> <include layout="@layout/icon_message" /></cn.minking.launcher.ShortcutIcon>
5. Hotseats组成分析
Hotseats采用的是线性布局LinearLayout, 根据MAX SEAT的个数,依次布局
图(四)
Hotseats.java @Override protected void onFinishInflate() {super.onFinishInflate();for (int i = 0; i < MAX_SEATS; i++) {LayoutInflater.from(mContext).inflate(R.layout.hotseat_button, this, true);} }
HotseatButton.java public void bind(ItemIcon itemicon, DragController dragcontroller){ mIcon = itemicon; // 构建一个FrameLayout, 将HOT Seat中的各个ItemIcon加人到Layout中 addView(itemicon); if (itemicon instanceof DropTarget) { dragcontroller.addDropTarget((DropTarget)itemicon);} }
6. DeleteZone组成分析
DeleteZone默认是隐藏的,等有Item被拖动时才会出现在屏幕的顶部。布局很简单,就以launcher.xml中布局显示。此布局绑定了几个动画及拖动的操作,等后续分析拖动时再详细讲解。
@Override protected void onFinishInflate() { super.onFinishInflate(); // 垃圾箱图标 mTrashIcon = (ImageView)findViewById(R.id.trash); // 提示信息 mEditingTips = (TextView)findViewById(R.id.editing_tips); mEditingTips.setDrawingCacheEnabled(true); // 显示及消失的动画, 淡入淡出及伸缩的效果 mFadeIn = AnimationUtils.loadAnimation(getContext(), R.anim.fade_in); mFadeOut = AnimationUtils.loadAnimation(getContext(), R.anim.fade_out); mShrinkToTop = AnimationUtils.loadAnimation(getContext(), R.anim.shrink_to_top); mShrinkToTop.setAnimationListener(this); mStretchFromTop = AnimationUtils.loadAnimation(getContext(), R.anim.stretch_from_top); mTransition = (TransitionDrawable)mTrashIcon.getBackground(); }
- 第一部分:Launcher APP 组成分析(二)
- 第一部分:Launcher APP 组成分析(一)
- 第一部分 Binder的组成
- Android Launcher源码分析(二)
- 第一部分:Java语言的基础组成
- IOS学习总结分析之二:10.13-10.31第一部分
- AppWidget启动流程部分 Launcher分析
- Android4.0 Launcher 源码分析系列(二)
- Activity启动流程源码分析之Launcher启动(二)
- Google Analytics分析教程(第一部分)
- dedecms源码分析(第一部分)
- 数据分析系统Hive(第一部分)
- 分析一下Portal的部分页面组成
- iOS Crash 分析(文二)-崩溃日志组成
- iOS Crash 分析(文二)-崩溃日志组成
- iOS Crash 分析(文二)-崩溃日志组成
- launcher app
- Android 4.0 Launcher源码分析系列(二)
- 一定要玩坏这个blog^-^
- 第三周作业——冒泡排序和归并排序
- 2014多益网络笔试题
- 启动Hadoop HDFS时的“Incompatible clusterIDs”错误原因分析
- Python快速学习07:文本文件的操作
- 第一部分:Launcher APP 组成分析(二)
- 交互设计学习day1 之一 概念入门
- web开发中怎么样使css书写规范?
- Hadoop集群环境搭建(win7下vmware虚拟ubuntu)
- 《算法导论》笔记 第11章 11.5 完全散列
- fatal error C1083: 无法打开包括文件:"dxtrans.h": No such file or directory
- Cracking the coding interview--Q19.10
- package.json
- Leetcode: Search a 2D Matrix 理解分析