1.桌面的显示会调用:showWorkspace(true)
void showWorkspace(boolean animated) { Resources res = getResources(); int stagger = res.getInteger(R.integer.config_appsCustomizeWorkspaceAnimationStagger); mWorkspace.changeState(Workspace.State.NORMAL, animated, stagger); if (mState == State.APPS_CUSTOMIZE) { closeAllApps(animated); } // Change the state *after* we've called all the transition code mState = State.WORKSPACE; // Resume the auto-advance of widgets mUserPresent = true; updateRunning(); // send an accessibility event to announce the context change getWindow().getDecorView().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); }
2.以上代码分析得到,调用了Workspace类中的changeState函数,从字面上看,貌似是状态的改变,进入此类找方法。
public void changeState(State shrinkState) { changeState(shrinkState, true); } void changeState(final State state, boolean animated) { changeState(state, animated, 0); } void changeState(final State state, boolean animated, int delay) { if (mFirstLayout) { // (mFirstLayout == "first layout has not happened yet") // cancel any pending shrinks that were set earlier mSwitchStateAfterFirstLayout = false; mStateAfterFirstLayout = state; return; } if (mAnimator != null) { mAnimator.cancel(); } // Stop any scrolling, move to the current page right away setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage); float finalScaleFactor = 1.0f; float finalBackgroundAlpha = (state == State.SPRING_LOADED) ? 1.0f : 0f; boolean normalState = false; State oldState = mState; mState = state; boolean zoomIn = true; if (state != State.NORMAL) { finalScaleFactor = mSpringLoadedShrinkFactor - (state == State.SMALL ? 0.1f : 0); if (oldState == State.NORMAL && state == State.SMALL) { zoomIn = false; if (animated) { hideScrollingIndicator(true); } setLayoutScale(finalScaleFactor); updateChildrenLayersEnabled(); } else { finalBackgroundAlpha = 1.0f; setLayoutScale(finalScaleFactor); } } else { setLayoutScale(1.0f); normalState = true; } float translationX = 0; float translationY = 0; mAnimator = new AnimatorSet(); final int screenCount = getChildCount(); initAnimationArrays(); final int duration = zoomIn ? getResources().getInteger(R.integer.config_workspaceUnshrinkTime) : getResources().getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime); for (int i = 0; i < screenCount; i++) { final CellLayout cl = (CellLayout)getChildAt(i); float finalAlphaValue = 0f; float rotation = 0f; // Set the final alpha depending on whether we are fading side pages. On phone ui, // we don't do any of the rotation, or the fading alpha in portrait. See the // ctor and screenScrolled(). if (mFadeInAdjacentScreens && normalState) { finalAlphaValue = (i == mCurrentPage) ? 1f : 0f; } else { finalAlphaValue = 1f; } if (LauncherApplication.isScreenLarge()) { if (i < mCurrentPage) { rotation = WORKSPACE_ROTATION; } else if (i > mCurrentPage) { rotation = -WORKSPACE_ROTATION; } } float finalAlphaMultiplierValue = 1f; // If the screen is not xlarge, then don't rotate the CellLayouts // NOTE: If we don't update the side pages alpha, then we should not hide the side // pages. see unshrink(). if (LauncherApplication.isScreenLarge()) { translationX = getOffsetXForRotation(rotation, cl.getWidth(), cl.getHeight()); } mOldAlphas[i] = cl.getAlpha(); mNewAlphas[i] = finalAlphaValue; if (animated) { mOldTranslationXs[i] = cl.getTranslationX(); mOldTranslationYs[i] = cl.getTranslationY(); mOldScaleXs[i] = cl.getScaleX(); mOldScaleYs[i] = cl.getScaleY(); mOldBackgroundAlphas[i] = cl.getBackgroundAlpha(); mOldBackgroundAlphaMultipliers[i] = cl.getBackgroundAlphaMultiplier(); mOldRotationYs[i] = cl.getRotationY(); mNewTranslationXs[i] = translationX; mNewTranslationYs[i] = translationY; mNewScaleXs[i] = finalScaleFactor; mNewScaleYs[i] = finalScaleFactor; mNewBackgroundAlphas[i] = finalBackgroundAlpha; mNewBackgroundAlphaMultipliers[i] = finalAlphaMultiplierValue; mNewRotationYs[i] = rotation; } else { cl.setTranslationX(translationX); cl.setTranslationY(translationY); cl.setScaleX(finalScaleFactor); cl.setScaleY(finalScaleFactor); cl.setBackgroundAlpha(0.0f); cl.setBackgroundAlphaMultiplier(finalAlphaMultiplierValue); cl.setAlpha(finalAlphaValue); cl.setRotationY(rotation); mChangeStateAnimationListener.onAnimationEnd(null); } } if (animated) { ValueAnimator animWithInterpolator = ValueAnimator.ofFloat(0f, 1f).setDuration(duration); if (zoomIn) { animWithInterpolator.setInterpolator(mZoomInInterpolator); } animWithInterpolator.addUpdateListener(new LauncherAnimatorUpdateListener() { public void onAnimationUpdate(float a, float b) { mTransitionProgress = b; if (b == 0f) { // an optimization, but not required return; } invalidate(); for (int i = 0; i < screenCount; i++) { final CellLayout cl = (CellLayout) getChildAt(i); cl.fastInvalidate(); cl.setFastTranslationX(a * mOldTranslationXs[i] + b * mNewTranslationXs[i]); cl.setFastTranslationY(a * mOldTranslationYs[i] + b * mNewTranslationYs[i]); cl.setFastScaleX(a * mOldScaleXs[i] + b * mNewScaleXs[i]); cl.setFastScaleY(a * mOldScaleYs[i] + b * mNewScaleYs[i]); cl.setFastBackgroundAlpha( a * mOldBackgroundAlphas[i] + b * mNewBackgroundAlphas[i]); cl.setBackgroundAlphaMultiplier(a * mOldBackgroundAlphaMultipliers[i] + b * mNewBackgroundAlphaMultipliers[i]); cl.setFastAlpha(a * mOldAlphas[i] + b * mNewAlphas[i]); } } }); ValueAnimator rotationAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration); rotationAnim.setInterpolator(new DecelerateInterpolator(2.0f)); rotationAnim.addUpdateListener(new LauncherAnimatorUpdateListener() { public void onAnimationUpdate(float a, float b) { if (b == 0f) { // an optimization, but not required return; } for (int i = 0; i < screenCount; i++) { final CellLayout cl = (CellLayout) getChildAt(i); cl.setFastRotationY(a * mOldRotationYs[i] + b * mNewRotationYs[i]); } } }); mAnimator.playTogether(animWithInterpolator, rotationAnim); mAnimator.setStartDelay(delay); // If we call this when we're not animated, onAnimationEnd is never called on // the listener; make sure we only use the listener when we're actually animating mAnimator.addListener(mChangeStateAnimationListener); mAnimator.start(); } if (state == State.SPRING_LOADED) { // Right now we're covered by Apps Customize // Show the background gradient immediately, so the gradient will // be showing once AppsCustomize disappears animateBackgroundGradient(getResources().getInteger( R.integer.config_appsCustomizeSpringLoadedBgAlpha) / 100f, false); } else { // Fade the background gradient away animateBackgroundGradient(0f, true); } }
3.从以上代码分析得到这个只是得到了动画的显示,那么说明数据的填充已经在前面完成了,再到回去分析。
4.进入Launcher类看到setupViews() ,找到 mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);我就猜想一下,是不是找到元素后,对其子元素就进行了填充呢?
5.查找到这里
View createShortcut(ShortcutInfo info) { return createShortcut(R.layout.application, (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info); }
就能猜测到数据应该就是在这里添加的。
6.查找此方法就发现这个方法:
public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end) { setLoadOnResume(); final Workspace workspace = mWorkspace; for (int i=start; i<end; i++) { final ItemInfo item = shortcuts.get(i); // Short circuit if we are loading dock items for a configuration which has no dock if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { continue; } switch (item.itemType) { case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: View shortcut = createShortcut((ShortcutInfo)item); workspace.addInScreen(shortcut, item.container, item.screen, item.cellX, item.cellY, 1, 1, false); break; case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this, (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()), (FolderInfo) item, mIconCache); workspace.addInScreen(newFolder, item.container, item.screen, item.cellX, item.cellY, 1, 1, false); break; } } workspace.requestLayout(); }
7.原来这个binditem是一个launchermodel的回调函数,再添加数据到model的时候,会进行回调进行数据绑定。
8.基本上流程已经通顺了!