Fixed regression with search not reacting properly to on touch events.
There are a few interesting UX niceties that we support in search:
1) When in regular search with an empty query, close the UI if the user
touches the blank space.
2) When in regular search with a non-empty query, hide the keyboard if the
user touches the the list so they can see all results.
2) When in dialpad search with an empty query, close the UI if the user
touches the blank space.
3) When in dialpad search with a non-empty query, hide the dialpad so the user
can see the full list of results.
This change also adds logic to transfer the dialpad query to the search bar.
Bug: 64655802
Test: MainActivityIntegrationTest
PiperOrigin-RevId: 182434126
Change-Id: Iabb73b0018fa20e2811010a73a35d3aa3b35343b
diff --git a/java/com/android/dialer/dialpadview/DialpadFragment.java b/java/com/android/dialer/dialpadview/DialpadFragment.java
index 2796fca..9cee7bc 100644
--- a/java/com/android/dialer/dialpadview/DialpadFragment.java
+++ b/java/com/android/dialer/dialpadview/DialpadFragment.java
@@ -59,7 +59,6 @@
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
@@ -415,7 +414,7 @@
.setOnTouchListener(
(v, event) -> {
if (isDigitsEmpty()) {
- if (getActivity() != null && event.getAction() == MotionEvent.ACTION_UP) {
+ if (getActivity() != null) {
LogUtil.i("DialpadFragment.onCreateView", "dialpad spacer touched");
return ((HostInterface) getActivity()).onDialpadSpacerTouchWithEmptyQuery();
}
diff --git a/java/com/android/dialer/main/impl/MainActivity.java b/java/com/android/dialer/main/impl/MainActivity.java
index 35597f9..7aae8cb 100644
--- a/java/com/android/dialer/main/impl/MainActivity.java
+++ b/java/com/android/dialer/main/impl/MainActivity.java
@@ -157,13 +157,13 @@
@Override // DialpadFragment.HostInterface
public boolean onDialpadSpacerTouchWithEmptyQuery() {
- searchController.onBackPressed();
- return true;
+ // No-op, just let the clicks fall through to the search list
+ return false;
}
@Override // SearchFragmentListener
public void onSearchListTouch() {
- searchController.onBackPressed();
+ searchController.onSearchListTouch();
}
@Override // SearchFragmentListener
diff --git a/java/com/android/dialer/main/impl/MainSearchController.java b/java/com/android/dialer/main/impl/MainSearchController.java
index 4cccbf4..76c93bb 100644
--- a/java/com/android/dialer/main/impl/MainSearchController.java
+++ b/java/com/android/dialer/main/impl/MainSearchController.java
@@ -16,6 +16,7 @@
package com.android.dialer.main.impl;
+import android.app.FragmentTransaction;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.text.TextUtils;
@@ -24,12 +25,14 @@
import android.view.animation.Animation.AnimationListener;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
import com.android.dialer.dialpadview.DialpadFragment;
import com.android.dialer.dialpadview.DialpadFragment.DialpadListener;
import com.android.dialer.dialpadview.DialpadFragment.OnDialpadQueryChangedListener;
import com.android.dialer.main.impl.toolbar.MainToolbar;
import com.android.dialer.main.impl.toolbar.SearchBarListener;
import com.android.dialer.searchfragment.list.NewSearchFragment;
+import com.android.dialer.searchfragment.list.NewSearchFragment.SearchFragmentListener;
import com.android.dialer.util.ViewUtil;
import com.google.common.base.Optional;
@@ -77,8 +80,7 @@
toolbar.expand(animate, Optional.absent());
mainActivity.setTitle(R.string.dialpad_activity_title);
- android.app.FragmentTransaction transaction =
- mainActivity.getFragmentManager().beginTransaction();
+ FragmentTransaction transaction = mainActivity.getFragmentManager().beginTransaction();
// Show Search
if (getSearchFragment() == null) {
@@ -105,6 +107,7 @@
fab.show();
toolbar.slideDown(animate);
+ toolbar.transferQueryFromDialpad(getDialpadFragment().getQuery());
mainActivity.setTitle(R.string.main_activity_label);
DialpadFragment dialpadFragment = getDialpadFragment();
@@ -155,15 +158,43 @@
}
/**
+ * @see SearchFragmentListener#onSearchListTouch()
+ * <p>There are 4 scenarios we support to provide a nice UX experience:
+ * <ol>
+ * <li>When the dialpad is visible with an empty query, close the search UI.
+ * <li>When the dialpad is visible with a non-empty query, hide the dialpad.
+ * <li>When the regular search UI is visible with an empty query, close the search UI.
+ * <li>When the regular search UI is visible with a non-empty query, hide the keyboard.
+ * </ol>
+ */
+ public void onSearchListTouch() {
+ if (isDialpadVisible()) {
+ if (TextUtils.isEmpty(getDialpadFragment().getQuery())) {
+ closeSearch(true);
+ } else {
+ hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false);
+ }
+ } else if (isSearchVisible()) {
+ if (TextUtils.isEmpty(toolbar.getQuery())) {
+ closeSearch(true);
+ } else {
+ toolbar.hideKeyboard();
+ }
+ }
+ }
+
+ /**
* Should be called when the user presses the back button.
*
* @return true if #onBackPressed() handled to action.
*/
public boolean onBackPressed() {
if (isDialpadVisible() && !TextUtils.isEmpty(getDialpadFragment().getQuery())) {
+ LogUtil.i("MainSearchController#onBackPressed", "Dialpad visible with query");
hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false);
return true;
} else if (isSearchVisible()) {
+ LogUtil.i("MainSearchController#onBackPressed", "Search is visible");
closeSearch(true);
return true;
} else {
@@ -218,9 +249,10 @@
public void onSearchBarClicked() {
fab.hide();
toolbar.expand(/* animate=*/ true, Optional.absent());
+ toolbar.showKeyboard();
+ hideBottomNav();
- android.app.FragmentTransaction transaction =
- mainActivity.getFragmentManager().beginTransaction();
+ FragmentTransaction transaction = mainActivity.getFragmentManager().beginTransaction();
// Show Search
if (getSearchFragment() == null) {
diff --git a/java/com/android/dialer/main/impl/toolbar/MainToolbar.java b/java/com/android/dialer/main/impl/toolbar/MainToolbar.java
index 388815a..6e38d2e 100644
--- a/java/com/android/dialer/main/impl/toolbar/MainToolbar.java
+++ b/java/com/android/dialer/main/impl/toolbar/MainToolbar.java
@@ -111,4 +111,20 @@
public boolean isSlideUp() {
return isSlideUp;
}
+
+ public String getQuery() {
+ return searchBar.getQuery();
+ }
+
+ public void transferQueryFromDialpad(String query) {
+ searchBar.setQueryWithoutUpdate(query);
+ }
+
+ public void hideKeyboard() {
+ searchBar.hideKeyboard();
+ }
+
+ public void showKeyboard() {
+ searchBar.showKeyboard();
+ }
}
diff --git a/java/com/android/dialer/main/impl/toolbar/SearchBarView.java b/java/com/android/dialer/main/impl/toolbar/SearchBarView.java
index 306a5bb..6b9f39d 100644
--- a/java/com/android/dialer/main/impl/toolbar/SearchBarView.java
+++ b/java/com/android/dialer/main/impl/toolbar/SearchBarView.java
@@ -30,6 +30,7 @@
import android.widget.EditText;
import android.widget.FrameLayout;
import com.android.dialer.animation.AnimUtils;
+import com.android.dialer.common.UiUtil;
import com.android.dialer.util.DialerUtils;
import com.google.common.base.Optional;
@@ -44,6 +45,9 @@
private SearchBarListener listener;
private EditText searchBox;
+ // This useful for when the query didn't actually change. We want to avoid making excessive calls
+ // where we can since IPCs can take a long time on slow networks.
+ private boolean skipLatestTextChange;
private int initialHeight;
private boolean isExpanded;
@@ -177,6 +181,24 @@
this.listener = listener;
}
+ public String getQuery() {
+ return searchBox.getText().toString();
+ }
+
+ public void setQueryWithoutUpdate(String query) {
+ skipLatestTextChange = true;
+ searchBox.setText(query);
+ searchBox.setSelection(searchBox.getText().length());
+ }
+
+ public void hideKeyboard() {
+ UiUtil.hideKeyboardFrom(getContext(), searchBox);
+ }
+
+ public void showKeyboard() {
+ UiUtil.openKeyboardFrom(getContext(), searchBox);
+ }
+
/** Handles logic for text changes in the search box. */
private class SearchBoxTextWatcher implements TextWatcher {
@@ -189,6 +211,11 @@
@Override
public void afterTextChanged(Editable s) {
clearButton.setVisibility(TextUtils.isEmpty(s) ? GONE : VISIBLE);
+ if (skipLatestTextChange) {
+ skipLatestTextChange = false;
+ return;
+ }
+
listener.onSearchQueryUpdated(s.toString());
}
}
diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
index e8a8a4e..30949d3 100644
--- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
+++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
@@ -490,8 +490,8 @@
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
v.performClick();
- FragmentUtils.getParentUnsafe(this, SearchFragmentListener.class).onSearchListTouch();
}
+ FragmentUtils.getParentUnsafe(this, SearchFragmentListener.class).onSearchListTouch();
return false;
}