Merge "Introduce folder name type (auto vs manual)." into ub-launcher3-master

This commit is contained in:
Hyunyoung Song
2020-01-27 18:16:28 +00:00
committed by Android (Google) Code Review
6 changed files with 151 additions and 30 deletions
+1 -1
View File
@@ -41,7 +41,7 @@
android:paddingLeft="12dp"
android:paddingRight="12dp" >
<com.android.launcher3.ExtendedEditText
<com.android.launcher3.folder.FolderNameEditText
android:id="@+id/folder_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -21,15 +21,11 @@ import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import com.android.launcher3.folder.FolderNameProvider;
import com.android.launcher3.util.UiThreadHelper;
import java.util.List;
/**
* The edit text that reports back when the back key has been pressed.
@@ -105,25 +101,6 @@ public class ExtendedEditText extends EditText {
UiThreadHelper.hideKeyboardAsync(getContext(), getWindowToken());
}
@Override
public void onCommitCompletion(CompletionInfo text) {
setText(text.getText());
setSelection(text.getText().length());
}
/**
* Currently only used for folder name suggestion.
*/
public void displayCompletions(List<String> suggestList) {
int cnt = Math.min(suggestList.size(), FolderNameProvider.SUGGEST_MAX);
CompletionInfo[] cInfo = new CompletionInfo[cnt];
for (int i = 0; i < cnt; i++) {
cInfo[i] = new CompletionInfo(i, i, suggestList.get(i));
}
post(() -> getContext().getSystemService(InputMethodManager.class)
.displayCompletions(this, cInfo));
}
private boolean showSoftInput() {
return requestFocus() &&
getContext().getSystemService(InputMethodManager.class)
@@ -45,6 +45,8 @@ public class FolderInfo extends ItemInfo {
*/
public static final int FLAG_MULTI_PAGE_ANIMATION = 0x00000004;
public static final int FLAG_MANUAL_FOLDER_NAME = 0x00000008;
public int options;
/**
@@ -140,4 +142,10 @@ public class FolderInfo extends ItemInfo {
writer.updateItemInDatabase(this);
}
}
@Override
protected String dumpProperties() {
return super.dumpProperties()
+ " manuallyTypedTitle=" + hasOption(FLAG_MANUAL_FOLDER_NAME);
}
}
+18 -6
View File
@@ -96,7 +96,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
View.OnFocusChangeListener, DragListener, ExtendedEditText.OnBackKeyListener {
private static final String TAG = "Launcher.Folder";
private static final boolean DEBUG = false;
/**
* We avoid measuring {@link #mContent} with a 0 width or height, as this
* results in CellLayout being measured as UNSPECIFIED, which it does not support.
@@ -146,7 +146,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
@Thunk FolderIcon mFolderIcon;
@Thunk FolderPagedView mContent;
public ExtendedEditText mFolderName;
public FolderNameEditText mFolderName;
private PageIndicatorDots mPageIndicator;
protected View mFooter;
@@ -306,6 +306,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
mFolderName.setText(suggestedNames[0]);
mFolderName.displayCompletions(Arrays.asList(suggestedNames).subList(1,
suggestedNames.length));
mFolderName.setEnteredCompose(false);
}
}
mFolderName.setHint("");
@@ -318,7 +319,13 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
// Convert to a string here to ensure that no other state associated with the text field
// gets saved.
String newTitle = mFolderName.getText().toString();
if (DEBUG) {
Log.d(TAG, "onBackKey newTitle=" + newTitle);
}
mInfo.title = newTitle;
mInfo.setOption(FolderInfo.FLAG_MANUAL_FOLDER_NAME, mFolderName.isEnteredCompose(),
mLauncher.getModelWriter());
mFolderIcon.onTitleChanged(newTitle);
mLauncher.getModelWriter().updateItemInDatabase(mInfo);
@@ -350,6 +357,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
}
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (DEBUG) {
Log.d(TAG, "onEditorAction actionId=" + actionId + " key="
+ (event != null ? event.getKeyCode() : "null event"));
}
if (actionId == EditorInfo.IME_ACTION_DONE) {
mFolderName.dispatchBackKey();
return true;
@@ -436,7 +447,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
*/
public void showSuggestedTitle(String[] suggestName) {
if (FeatureFlags.FOLDER_NAME_SUGGEST.get()
&& TextUtils.isEmpty(mFolderName.getText().toString())) {
&& TextUtils.isEmpty(mFolderName.getText().toString())
&& !mInfo.hasOption(FolderInfo.FLAG_MANUAL_FOLDER_NAME)) {
if (suggestName.length > 0 && !TextUtils.isEmpty(suggestName[0])) {
mFolderName.setHint("");
mFolderName.setText(suggestName[0]);
@@ -552,9 +564,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
openFolder.close(true);
}
if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
mLauncher.getFolderNameProvider().load(getContext());
}
mContent.bindItems(items);
centerAboutIcon();
mItemsInvalidated = true;
@@ -1495,6 +1504,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
return ContainerType.FOLDER;
}
/**
* Navigation bar back key or hardware input back key has been issued.
*/
@Override
public boolean onBackPressed() {
if (isEditingName()) {
@@ -0,0 +1,121 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.folder;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
import android.view.inputmethod.InputMethodManager;
import com.android.launcher3.ExtendedEditText;
import java.util.List;
/**
* Handles additional edit text functionality to better support folder name suggestion.
* First, makes suggestion to the InputMethodManager via {@link #displayCompletions(List)}
* Second, intercepts whether user accepted the suggestion or manually edited their
* folder names.
*/
public class FolderNameEditText extends ExtendedEditText {
private static final String TAG = "FolderNameEditText";
private static final boolean DEBUG = false;
private boolean mEnteredCompose = false;
public FolderNameEditText(Context context) {
super(context);
}
public FolderNameEditText(Context context, AttributeSet attrs) {
// ctor chaining breaks the touch handling
super(context, attrs);
}
public FolderNameEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
InputConnection con = super.onCreateInputConnection(outAttrs);
FolderNameEditTextInputConnection connectionWrapper =
new FolderNameEditTextInputConnection(con, true);
return connectionWrapper;
}
public void displayCompletions(List<String> suggestList) {
int cnt = Math.min(suggestList.size(), FolderNameProvider.SUGGEST_MAX);
CompletionInfo[] cInfo = new CompletionInfo[cnt];
for (int i = 0; i < cnt; i++) {
cInfo[i] = new CompletionInfo(i, i, suggestList.get(i));
}
post(() -> getContext().getSystemService(InputMethodManager.class)
.displayCompletions(this, cInfo));
}
/**
* Within 's', the 'count' characters beginning at 'start' have just replaced
* old text 'before'
*/
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String reason = "unknown";
if (start == 0 && count == 0 && before > 0) {
reason = "suggestion was rejected";
mEnteredCompose = true;
}
if (DEBUG) {
Log.d(TAG, "onTextChanged " + start + "," + before + "," + count
+ ", " + reason);
}
}
@Override
public void onCommitCompletion(CompletionInfo text) {
setText(text.getText());
setSelection(text.getText().length());
mEnteredCompose = false;
}
protected void setEnteredCompose(boolean value) {
mEnteredCompose = value;
}
protected boolean isEnteredCompose() {
if (DEBUG) {
Log.d(TAG, "isEnteredCompose " + mEnteredCompose);
}
return mEnteredCompose;
}
private class FolderNameEditTextInputConnection extends InputConnectionWrapper {
FolderNameEditTextInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
@Override
public boolean setComposingText(CharSequence cs, int newCursorPos) {
mEnteredCompose = true;
return super.setComposingText(cs, newCursorPos);
}
}
}
@@ -109,11 +109,14 @@ public class FolderNameProvider {
if (contains(candidatesOut, candidate)) {
return;
}
for (int i = 0; i < candidate.length(); i++) {
if (TextUtils.isEmpty(candidatesOut[i])) {
candidatesOut[i] = candidate;
return;
}
}
candidatesOut[candidate.length() - 1] = candidate;
}
private boolean contains(CharSequence[] list, CharSequence key) {