AndroidICS4.0的文件夹和2.3的文件夹区别比较大,主要区别有:
一、android2.3的文件夹大小是固定的,4.0的文件夹大小是按照里面的元素大小决定的。
二、android2.3的文件夹图标是固定的文件夹的形式展示的,而4.0是从文件中取前3个的缩略图垂直展示在屏幕上的。估计谷歌怕侵犯苹果文件夹的知识产权,所以没有做成和苹果一样的效果。
三、android2.3的文件中可以放多于16的应用程序的快捷方式,而4.0最多只能放16个快捷方式。
四、android2.3的文件夹中的图标不可以交换位置,而4.0的文件夹中的图标可以相互交换位置。
转载请标明出处:http://blog.csdn.net/wdaming1986/article/details/7748738
对比图如下:
android2.3的文件夹 android4.0的文件夹
下面来看看4.0的代码怎么实现文件夹的:
Step 1:如果系统一开始有fold,一启动launcher的时候,在Launcher.java类中bindFolders回调方法中:
/**
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindFolders(HashMap<Long, FolderInfo> folders) {
setLoadOnResume();
sFolders.clear();
sFolders.putAll(folders);
}
绑定所有fold的对象交给sFolders,去处理。
private static HashMap<Long, FolderInfo> sFolders = new HashMap<Long, FolderInfo>();
Step 2:如果是把一个图标拖放到另一图标上面,也形成folder。具体流程如下:
1、首先在workspace中的onDrop()方法中会判断是否会形成一个fold。代码如下:
public void onDrop(DragObject d) {
... ...
// If the item being dropped is a shortcut and the nearest drop
// cell also contains a shortcut, then create a folder with the two shortcuts.
if (!mInScrollArea && createUserFolderIfNecessary(cell, container,
dropTargetLayout, mTargetCell, false, d.dragView, null)) {
return;
}
... ...
}
2、在Workspace.java类的createUserFolderIfNecessary()方法中来增加fold,具体代码如下:
boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,
int[] targetCell, boolean external, DragView dragView, Runnable postAnimationRunnable) {
。。。 。。。
FolderIcon fi =
mLauncher.addFolder(target, container, screen, targetCell[0], targetCell[1]);
destInfo.cellX = -1;
destInfo.cellY = -1;
sourceInfo.cellX = -1;
sourceInfo.cellY = -1;
。。。 。。。
}
通过mLauncher.addFolder来传递folder的信息,包含一些位置信息绑定哪个屏幕的。
3、在Launcher.java类的addFolder()这个方法是真正形成folder的,以及在launcher的数据库中插入一条信息,代码如下:
FolderIcon addFolder(CellLayout layout, long container, final int screen, int cellX,
int cellY) {
final FolderInfo folderInfo = new FolderInfo();
folderInfo.title = getText(R.string.folder_name);
// Update the model
LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container, screen, cellX, cellY,
false);
sFolders.put(folderInfo.id, folderInfo);
// Create the view
FolderIcon newFolder =
FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo, mIconCache);
mWorkspace.addInScreen(newFolder, container, screen, cellX, cellY, 1, 1,
isWorkspaceLocked());
return newFolder;
}
FolderIcon.fromXml()这个方法是从xml中形成folder,addInScreen(),把相应的信息插入数据库。
4、在FolderIcon.java中fromXml()方法中的代码如下:
static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
FolderInfo folderInfo, IconCache iconCache) {
if (INITIAL_ITEM_ANIMATION_DURATION >= DROP_IN_ANIMATION_DURATION) {
throw new IllegalStateException("DROP_IN_ANIMATION_DURATION must be greater than " +
"INITIAL_ITEM_ANIMATION_DURATION, as sequencing of adding first two items " +
"is dependent on this");
}
FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
icon.mFolderName = (BubbleTextView) icon.findViewById(R.id.folder_icon_name);
icon.mFolderName.setText(folderInfo.title);
icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background);
icon.setTag(folderInfo);
icon.setOnClickListener(launcher);
icon.mInfo = folderInfo;
icon.mLauncher = launcher;
icon.setContentDescription(String.format(launcher.getString(R.string.folder_name_format),
folderInfo.title));
Folder folder = Folder.fromXml(launcher);
folder.setDragController(launcher.getDragController());
folder.setFolderIcon(icon);
folder.bind(folderInfo);
icon.mFolder = folder;
icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon);
folderInfo.addListener(icon);
return icon;
}
Folder folder = Folder.fromXml(launcher);是真正产生了一个folder对象。代码如下:
/**
* Creates a new UserFolder, inflated from R.layout.user_folder.
*
* @param context The application's context.
*
* @return A new UserFolder.
*/
static Folder fromXml(Context context) {
return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
}
并且给folder设置拖拽的控制器,绑定folderInfo设置folderInfo.addListener(icon)图标改变的监听。
这个接口 interface FolderListener定义了一个方法---->如下:
interface FolderListener {
public void onAdd(ShortcutInfo item);
public void onRemove(ShortcutInfo item);
public void onTitleChanged(CharSequence title);
public void onItemsChanged();
}
在folder.bind(folderInfo);方法中的操作如下:
void bind(FolderInfo info) {
mInfo = info;
ArrayList<ShortcutInfo> children = info.contents;
ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>();
setupContentForNumItems(children.size());
int count = 0;
for (int i = 0; i < children.size(); i++) {
ShortcutInfo child = (ShortcutInfo) children.get(i);
if (!createAndAddShortcut(child)) {
overflow.add(child);
} else {
count++;
}
}
// We rearrange the items in case there are any empty gaps
setupContentForNumItems(count);
// If our folder has too many items we prune them from the list. This is an issue
// when upgrading from the old Folders implementation which could contain an unlimited
// number of items.
for (ShortcutInfo item: overflow) {
mInfo.remove(item);
LauncherModel.deleteItemFromDatabase(mLauncher, item);
}
mItemsInvalidated = true;
updateTextViewFocus();
mInfo.addListener(this);
if (!sDefaultFolderName.contentEquals(mInfo.title)) {
mFolderName.setText(mInfo.title);
} else {
mFolderName.setText("");
}
}
主要的操作是:给拖拽进来的快捷方式安排位置,判断Folder是否已经放满,设置监听,设置folder的Name;
5、folder桌面的缩略图怎么形成的,是在第2步Workspace.java的createUserFolderIfNecessary()方法中
// If the dragView is null, we can't animate
boolean animate = dragView != null;
if (animate) {
fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale,
postAnimationRunnable);
} else {
fi.addItem(destInfo);
fi.addItem(sourceInfo);
}
fi.performCreateAnimation()这个方法是给folder添加个动画。
6、在FolderIcon.java中的performCreateAnimation()方法中:
public void performCreateAnimation(final ShortcutInfo destInfo, final View destView,
final ShortcutInfo srcInfo, final View srcView, Rect dstRect,
float scaleRelativeToDragLayer, Runnable postAnimationRunnable) {
Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1];
computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(), destView.getMeasuredWidth());
// This will animate the dragView (srcView) into the new folder
onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable);
// This will animate the first item from it's position as an icon into its
// position as the first item in the preview
animateFirstItem(animateDrawable, INITIAL_ITEM_ANIMATION_DURATION);
postDelayed(new Runnable() {
public void run() {
addItem(destInfo);
}
}, INITIAL_ITEM_ANIMATION_DURATION);
}
computePreviewDrawingParams()这个方法是计算绘制folder图标的方法;
7、在FolderIcon.java类中的computePreviewItemDrawingParams()方法中:
private PreviewItemDrawingParams computePreviewItemDrawingParams(int index,
PreviewItemDrawingParams params) {
index = NUM_ITEMS_IN_PREVIEW - index - 1;
float r = (index * 1.0f) / (NUM_ITEMS_IN_PREVIEW - 1);
float scale = (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r));
float offset = (1 - r) * mMaxPerspectiveShift;
float scaledSize = scale * mBaselineIconSize;
float scaleOffsetCorrection = (1 - scale) * mBaselineIconSize;
// We want to imagine our coordinates from the bottom left, growing up and to the
// right. This is natural for the x-axis, but for the y-axis, we have to invert things.
float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection);
float transX = offset + scaleOffsetCorrection;
float totalScale = mBaselineIconScale * scale;
final int overlayAlpha = (int) (80 * (1 - r));
if (params == null) {
params = new PreviewItemDrawingParams(transX, transY, totalScale, overlayAlpha);
} else {
params.transX = transX;
params.transY = transY;
params.scale = totalScale;
params.overlayAlpha = overlayAlpha;
}
return params;
}
主要工作是:计算图标的排列,每一个相对上一个有点偏移的距离;效果图如下:
以上基本是把Step 2流程大致过了一遍。
Step 3:folder类中的长按事件的传递,以及Fold中长按交换位置的流程过一下:
1、先来说给Folder设置长按监听的地方,因为Folder.java类是继承了View.OnClickListener,
View.OnLongClickListener事件,所以,长按事件就交给自己的onLongClick()事件来处理。
2、所以Folder中的长按事件,被自己的public boolean onLongClick(View v) {}时间捕获,代码如下:
public boolean onLongClick(View v) {
... ...
mLauncher.getWorkspace().onDragStartedWithItem(v);
mLauncher.getWorkspace().beginDragShared(v, this);
mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
mCurrentDragInfo = item;
mEmptyCell[0] = item.cellX;
mEmptyCell[1] = item.cellY;
mCurrentDragView = v;
mContent.removeView(mCurrentDragView);
mInfo.remove(mCurrentDragInfo);
mDragInProgress = true;
mItemAddedBackToSelfViaIcon = false;
... ...
}
同样拖拽事件是交给Workspace来处理,最后也是统一交给DragController.java类处理和分发相应的事件。这个过程在
Android-->Launcher拖拽事件详解【androidICS4.0--Launcher系列二】中做了详细的介绍,这里就不做赘述了。
3、主要看Folder.java类中的onDragOver()这个方法,当在文件夹中拖拽到另一个快捷方式的上面的时候,发生交换,
来看代码如下:
public void onDragOver(DragObject d) {
float[] r = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, null);
mTargetCell = mContent.findNearestArea((int) r[0], (int) r[1], 1, 1, mTargetCell);
if (mTargetCell[0] != mPreviousTargetCell[0] || mTargetCell[1] != mPreviousTargetCell[1]) {
mReorderAlarm.cancelAlarm();
mReorderAlarm.setOnAlarmListener(mReorderAlarmListener);
mReorderAlarm.setAlarm(150);
mPreviousTargetCell[0] = mTargetCell[0];
mPreviousTargetCell[1] = mTargetCell[1];
}
}
这个方法主要做的操作是:判断拖拽的是哪个对象mContent.findNearestArea((int) r[0], (int) r[1], 1, 1, mTargetCell);判断在
哪个目标的附近,然后判断和是否是正在拖拽的对象的坐标,设置mReorderAlarmListener来进行交换,设置150毫秒用来处理动画的。
4、在ReorderAlarmListener内部类的代码如下:
OnAlarmListener mReorderAlarmListener = new OnAlarmListener() {
public void onAlarm(Alarm alarm) {
realTimeReorder(mEmptyCell, mTargetCell);
}
};
5、在realTimeReorder()方法中传递这个快捷方式在屏幕x轴,y轴上的为止,进行交换,代码如下:
private void realTimeReorder(int[] empty, int[] target) {
boolean wrap;
int startX;
int endX;
int startY;
int delay = 0;
float delayAmount = 30;
if (readingOrderGreaterThan(target, empty)) {
wrap = empty[0] >= mContent.getCountX() - 1;
startY = wrap ? empty[1] + 1 : empty[1];
for (int y = startY; y <= target[1]; y++) {
startX = y == empty[1] ? empty[0] + 1 : 0;
endX = y < target[1] ? mContent.getCountX() - 1 : target[0];
for (int x = startX; x <= endX; x++) {
View v = mContent.getChildAt(x,y);
if (mContent.animateChildToPosition(v, empty[0], empty[1],
REORDER_ANIMATION_DURATION, delay)) {
empty[0] = x;
empty[1] = y;
delay += delayAmount;
delayAmount *= 0.9;
}
}
}
} else {
wrap = empty[0] == 0;
startY = wrap ? empty[1] - 1 : empty[1];
for (int y = startY; y >= target[1]; y--) {
startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1;
endX = y > target[1] ? 0 : target[0];
for (int x = startX; x >= endX; x--) {
View v = mContent.getChildAt(x,y);
if (mContent.animateChildToPosition(v, empty[0], empty[1],
REORDER_ANIMATION_DURATION, delay)) {
empty[0] = x;
empty[1] = y;
delay += delayAmount;
delayAmount *= 0.9;
}
}
}
}
}
readingOrderGreaterThan()这个方法的作用是判断是从上往下拖动,还是从下往上拖动,这两种情况的交换方式不一样。循环也就不一样。交换的过程中通过animateChildToPosition();这个方法设置了一个动画。
6、在放下的时候会触发Folder.java的onDrop()方法,
public void onDrop(DragObject d) {
ShortcutInfo item;
。。。 。。。
if (d.dragView.hasDrawn()) {
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView);
} else {
mCurrentDragView.setVisibility(VISIBLE);
}
mInfo.add(item); 。。。 。。。
}
作用是设置放下的view可见,把当前的这个快捷方式添加到mInfo中。
7、当执行完onDrop()方法后会走onDropCompleted()方法:
public void onDropCompleted(View target, DragObject d, boolean success) {
... ...
// Reordering may have occured, and we need to save the new item locations. We do this once
// at the end to prevent unnecessary database operations.
updateItemLocationsInDatabase();
... ...
}
这个方法的作用是更新item的位置信息在数据库中。
private void updateItemLocationsInDatabase() {
ArrayList<View> list = getItemsInReadingOrder();
for (int i = 0; i < list.size(); i++) {
View v = list.get(i);
ItemInfo info = (ItemInfo) v.getTag();
LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0,
info.cellX, info.cellY);
}
}
好了,folder的大致流程就是这些,更详细的请参考launcher源代码。
写的仓促,欢迎大家指出里面的错误,如果有不解的欢迎留言!
分享到:
相关推荐
在Android 4.0(Ice Cream Sandwich,简称ICS)版本中,官方推出了改进版的Launcher——Launcher2,相较于早期版本,它在性能、用户体验以及可定制性方面都有所提升。本文将围绕"android4.0 Launcher2"这一主题,...
【Android 2.3 仿 4.0 Launcher】是一个针对Android 2.3 Gingerbread系统设计的桌面启动器,其目标是模仿Android 4.0 Ice Cream Sandwich的用户界面和功能。在Android 2.3系统上使用这个启动器,用户可以获得与...
在Android 4.0(Ice Cream Sandwich,简称ICS)时代,对Launcher的定制提供了更多可能性,让我们深入探讨一下如何理解和分析“android 定制 launcher 4.0源码”。 首先,我们需要理解Android Launcher的基本架构。...
【Android 4.0 Launcher2 源码 Eclipse版】是一个专门为Android 4.0 (Ice Cream Sandwich)系统设计的启动器源代码,适合开发者深入理解Android系统的桌面启动器工作原理,以及进行自定义开发。这个源代码版本是为...
《Android 4.0 Launcher深度解析》 在Android操作系统中,Launcher,即启动器,扮演着用户界面的核心角色,它是用户与设备交互的首要入口。本文将深入剖析Android 4.0版本的Launcher,理解其背后的运行机制和设计...
Android 4.0 Launcher系统源码是Android操作系统中桌面启动器的重要组成部分,它负责管理主屏幕、应用快捷方式、小部件以及桌面布局等用户界面。深入理解这部分源码对于开发者来说,有助于定制个性化启动器或者优化...
1. **下载源码**: 首先,你需要从官方仓库或者第三方资源下载到Android 4.0的Launcher2源代码,通常是以`.zip`或`.tar.gz`格式的压缩包。 2. **解压文件**: 解压缩下载的文件,得到`Launcher2`源代码目录。 3. **...
首先,Android 4.0(代号Ice Cream Sandwich,简称ICS)的Launcher是基于Launcher2实现的,这也是压缩包中的文件名。Launcher2是在Android 2.3(Gingerbread)基础上进行改进的,它在Android 4.0中被广泛采用,带来...
Android 4.0(Ice Cream Sandwich,简称ICS)是Google推出的一个重要版本,其Launcher作为用户与系统交互的主界面,扮演着至关重要的角色。Launcher2是该版本中默认的桌面启动器,它的源码提供了深入了解Android系统...
在Android 4.0(Ice Cream Sandwich,简称ICS)版本中,Launcher进行了诸多改进,旨在提供更流畅、更直观的用户体验。这个"Android 4.0 Launcher 可编译代码"是一个经过修改的源代码版本,允许开发者进行定制和调试...
"Android 4.0 Launcher2"是Android操作系统的一个核心组件,它是用户与设备交互的主界面,负责显示应用快捷方式、小部件以及桌面布局。在这个源代码中,我们可以深入理解Android系统的桌面启动器是如何实现其功能的...
Android 4.0(Ice Cream Sandwich,简称ICS)是Android系统的一个重要版本,其Launcher源码的解析对于我们理解Android系统的运行机制及定制化开发具有极高的价值。 首先,我们要了解的是如何将提供的压缩包文件导入...
通过对Android 4.0 ICS Launcher的源码进行深入研究,开发者可以学习到Android UI设计的最佳实践、性能优化技巧以及如何实现高级功能,这对于提升自己的Android开发技能大有裨益。同时,这也为自定义Launcher或者...
Android 4.0 的 Launcher2 是 Android 操作系统中的主屏幕应用,负责显示桌面图标、小部件和其他可启动的应用程序。源码分析可以帮助开发者深入理解其工作原理,从而进行自定义开发或性能优化。以下是对 Android 4.0...
在Android 4.0(Ice Cream Sandwich,简称ICS)这个版本中,Launcher进行了诸多改进和优化,提升了用户体验。下面将详细探讨Android 4.0原生Launcher的相关知识点。 1. **设计风格**:Android 4.0引入了全新的Holo...
Android 4.0 的 Launcher2 是 Android 桌面启动器的一个版本,它负责呈现用户在设备上看到的主屏幕、应用抽屉和其他界面。在这个源代码包中,我们可以深入理解 Android 应用程序框架、UI 设计以及系统级别的交互逻辑...
【Android 4.0 原生 Launcher 代码详解】 Android 4.0(冰淇淋三明治,Ice Cream Sandwich)的 Launcher 是用户界面的核心部分,它作为系统的启动器,负责展示应用图标、小部件和主屏幕。理解其源码对于开发者深入...
本资源提供了Android 4.0(Ice Cream Sandwich,简称ICS)的原生Launcher源码,让我们一起探索这个核心组件的奥秘。 首先,此项目基于Eclipse开发环境,源码已经修改了包名,避免与系统原有的Launcher包名冲突,这...
本代码是4.0 launcher 源码. 支持4.0 4.1 系统. 真机运行截图见 shoot.png. 如果您遇到麻烦请自己搭建android开发环境:linux系统,虚拟机,下载android源码 等.这将花费有经验的您几天时间. 迅速获得编译技术支持(如果...
4.0Launcher的源码,在项目中的library文件中包含了编译所需要的framework_intermediates,android-common_intermediates,core_intermediates的jar文件,项目还整合了android.support.v13.dreams.BasicDream.java这...