// This method keeps track of the last item in the folder for the purposes // of keyboard focus private void updateTextViewFocus() { View lastChild = getItemAt(getItemCount() - 1); getItemAt(getItemCount() - 1); if (lastChild != null) { mFolderName.setNextFocusDownId(lastChild.getId()); mFolderName.setNextFocusRightId(lastChild.getId()); mFolderName.setNextFocusLeftId(lastChild.getId()); mFolderName.setNextFocusUpId(lastChild.getId()); } }
@Override protected void onFinishInflate() { super.onFinishInflate(); mContent = (CellLayout) findViewById(R.id.folder_content); mContent.setGridSize(0, 0); mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false); mFolderName = (FolderEditText) findViewById(R.id.folder_name); mFolderName.setFolder(this); mFolderName.setOnFocusChangeListener(this); // 算出TextView最终需要多大,以便可以给它腾出适合大小的地方 int measureSpec = MeasureSpec.UNSPECIFIED; mFolderName.measure(measureSpec, measureSpec); mFolderNameHeight = mFolderName.getMeasuredHeight(); // We disable action mode for now since it messes up the view on phones // 暂时禁止action mode,因为它有可能会情致view混乱 mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback); mFolderName.setOnEditorActionListener(this); mFolderName.setSelectAllOnFocus(true); mFolderName.setInputType( mFolderName.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS); }
@Override protected void onFinishInflate() { super.onFinishInflate(); mContent = (CellLayout) findViewById(R.id.folder_content); mContent.setGridSize(0, 0); mContent.getChildrenLayout().setMotionEventSplittingEnabled(false); mFolderName = (FolderEditText) findViewById(R.id.folder_name); mFolderName.setFolder(this); mFolderName.setOnFocusChangeListener(this); // We find out how tall the text view wants to be (it is set to wrap_content), so that // we can allocate the appropriate amount of space for it. int measureSpec = MeasureSpec.UNSPECIFIED; mFolderName.measure(measureSpec, measureSpec); mFolderNameHeight = mFolderName.getMeasuredHeight(); // We disable action mode for now since it messes up the view on phones mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback); mFolderName.setOnEditorActionListener(this); mFolderName.setSelectAllOnFocus(true); mFolderName.setInputType( mFolderName.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS); }
void bind(FolderInfo info) { mInfo = info; ArrayList<ShortcutInfo> children = info.contents; ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>(); setupContentForNumItems(children.size()); placeInReadingOrder(children); int count = 0; for (int i = 0; i < children.size(); i++) { ShortcutInfo child = (ShortcutInfo) children.get(i); if (createAndAddShortcut(child) == null) { 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(""); } updateItemLocationsInDatabase(); // In case any children didn't come across during loading, clean up the folder accordingly mFolderIcon.post( new Runnable() { public void run() { if (getItemCount() <= 1) { replaceFolderWithFinalItem(); } } }); }
void bind(FolderInfo info) { mInfo = info; ArrayList<ShortcutInfo> children = info.contents; ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>(); // 超出数量的item setupContentForNumItems(children.size()); placeInReadingOrder(children); 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++; } } // 重新排序以防止有空的间隔。应该是防止万一数据有不对。 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. // 如果文件夹里面有太多项目的话,我们把他们从list里面删掉。 // 因为从以前版本的数据库升级的时候有可能会出现许许多多的item(以前没有限制?) 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(""); } updateItemLocationsInDatabase(); // 更新数据库里面的位置,万一以前里面的有错误(也太小心了……) }
public void doneEditingFolderName(boolean commit) { mFolderName.setHint(sHintText); // Convert to a string here to ensure that no other state associated with the text field // gets saved. String newTitle = mFolderName.getText().toString(); mInfo.setTitle(newTitle); LauncherModel.updateItemInDatabase(mLauncher, mInfo); if (commit) { sendCustomAccessibilityEvent( AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, String.format(getContext().getString(R.string.folder_renamed), newTitle)); } // In order to clear the focus from the text field, we set the focus on ourself. This // ensures that every time the field is clicked, focus is gained, giving reliable behavior. requestFocus(); Selection.setSelection((Spannable) mFolderName.getText(), 0, 0); mIsEditingName = false; }
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight() + mFolderNameHeight; int contentWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(), MeasureSpec.EXACTLY); int contentHeightSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredHeight(), MeasureSpec.EXACTLY); mContent.measure(contentWidthSpec, contentHeightSpec); mFolderName.measure( contentWidthSpec, MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY)); setMeasuredDimension(width, height); }
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; updateStyledTextFooFocus(); mInfo.addListener(this); if (!sDefaultFolderName.contentEquals(mInfo.title)) { mFolderName.setText(mInfo.title); } else { mFolderName.setText(""); } }
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); int height = getFolderHeight(); int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(getContentAreaWidth(), MeasureSpec.EXACTLY); int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(getContentAreaHeight(), MeasureSpec.EXACTLY); if (LauncherAppState.isDisableAllApps() || mScrollingFolders) { // Don't cap the height of the content to allow scrolling. mContent.setFixedSize(getContentAreaWidth(), mContent.getDesiredHeight()); } else { mContent.setFixedSize(getContentAreaWidth(), getContentAreaHeight()); } mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec); mFolderName.measure( contentAreaWidthSpec, MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY)); setMeasuredDimension(width, height); }
public void animateOpen() { if (!(getParent() instanceof DragLayer)) return; Animator openFolderAnim = null; final Runnable onCompleteRunnable; if (!Utilities.isLmpOrAbove()) { positionAndSizeAsIcon(); centerAboutIcon(); PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1); PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f); PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f); final ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY); oa.setDuration(mExpandDuration); openFolderAnim = oa; setLayerType(LAYER_TYPE_HARDWARE, null); onCompleteRunnable = new Runnable() { @Override public void run() { setLayerType(LAYER_TYPE_NONE, null); } }; } else { prepareReveal(); centerAboutIcon(); int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); int height = getFolderHeight(); float transX = -0.075f * (width / 2 - getPivotX()); float transY = -0.075f * (height / 2 - getPivotY()); setTranslationX(transX); setTranslationY(transY); PropertyValuesHolder tx = PropertyValuesHolder.ofFloat("translationX", transX, 0); PropertyValuesHolder ty = PropertyValuesHolder.ofFloat("translationY", transY, 0); int rx = (int) Math.max(Math.max(width - getPivotX(), 0), getPivotX()); int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY()); float radius = (float) Math.sqrt(rx * rx + ry * ry); AnimatorSet anim = LauncherAnimUtils.createAnimatorSet(); Animator reveal = LauncherAnimUtils.createCircularReveal( this, (int) getPivotX(), (int) getPivotY(), 0, radius); reveal.setDuration(mMaterialExpandDuration); reveal.setInterpolator(new LogDecelerateInterpolator(100, 0)); mContent.setAlpha(0f); Animator iconsAlpha = LauncherAnimUtils.ofFloat(mContent, "alpha", 0f, 1f); iconsAlpha.setDuration(mMaterialExpandDuration); iconsAlpha.setStartDelay(mMaterialExpandStagger); iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); mFolderName.setAlpha(0f); Animator textAlpha = LauncherAnimUtils.ofFloat(mFolderName, "alpha", 0f, 1f); textAlpha.setDuration(mMaterialExpandDuration); textAlpha.setStartDelay(mMaterialExpandStagger); textAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); Animator drift = LauncherAnimUtils.ofPropertyValuesHolder(this, tx, ty); drift.setDuration(mMaterialExpandDuration); drift.setStartDelay(mMaterialExpandStagger); drift.setInterpolator(new LogDecelerateInterpolator(60, 0)); anim.play(drift); anim.play(iconsAlpha); anim.play(textAlpha); anim.play(reveal); openFolderAnim = anim; mContent.setLayerType(LAYER_TYPE_HARDWARE, null); onCompleteRunnable = new Runnable() { @Override public void run() { mContent.setLayerType(LAYER_TYPE_NONE, null); } }; } openFolderAnim.addListener( new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { sendCustomAccessibilityEvent( AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, String.format( getContext().getString(R.string.folder_opened), mContent.getCountX(), mContent.getCountY())); mState = STATE_ANIMATING; } @Override public void onAnimationEnd(Animator animation) { mState = STATE_OPEN; if (onCompleteRunnable != null) { onCompleteRunnable.run(); } setFocusOnFirstChild(); } }); openFolderAnim.start(); // Make sure the folder picks up the last drag move even if the finger doesn't move. if (mDragController.isDragging()) { mDragController.forceTouchMove(); } }
public void startEditingFolderName() { mFolderName.setHint(""); mIsEditingName = true; }
@Override protected void onFinishInflate() { super.onFinishInflate(); mScrollView = (ScrollView) findViewById(R.id.scroll_view); mContent = (CellLayout) findViewById(R.id.folder_content); mFocusIndicatorHandler = new FocusIndicatorView(getContext()); mContent.addView(mFocusIndicatorHandler, 0); mFocusIndicatorHandler.getLayoutParams().height = FocusIndicatorView.DEFAULT_LAYOUT_SIZE; mFocusIndicatorHandler.getLayoutParams().width = FocusIndicatorView.DEFAULT_LAYOUT_SIZE; LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); mContent.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx); mContent.setGridSize(0, 0); mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false); mContent.setInvertIfRtl(true); mFolderName = (FolderEditText) findViewById(R.id.folder_name); mFolderName.setFolder(this); if (mLauncher.getLockWorkspace()) { mFolderName.setKeyListener(null); mFolderName.setFocusable(false); } else { mFolderName.setOnFocusChangeListener(this); } // We find out how tall the text view wants to be (it is set to wrap_content), so that // we can allocate the appropriate amount of space for it. int measureSpec = MeasureSpec.UNSPECIFIED; mFolderName.measure(measureSpec, measureSpec); mFolderNameHeight = mFolderName.getMeasuredHeight(); // We disable action mode for now since it messes up the view on phones mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback); mFolderName.setOnEditorActionListener(this); mFolderName.setSelectAllOnFocus(true); mFolderName.setInputType( mFolderName.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS); mAutoScrollHelper = new FolderAutoScrollHelper(mScrollView); boolean hideFolderName = SettingsProvider.getBoolean(mLauncher, SettingsProvider.HIDE_FOLDER_NAME, false); if (hideFolderName) { mFolderName.setVisibility(View.GONE); mFolderNameHeight = 0; } }