Add optional feedback button for settings search

Adds mechanism for adding a button in the search screen
and stubs to show and hide the button.

Fixes: 35164702
Test: make -j40 RunSettingsRoboTests
Change-Id: I34d245e84b62cedf2dc6e5de4ea336c5a99ffd31
This commit is contained in:
Matthew Fritze
2017-02-21 10:20:40 -08:00
parent a540a978bc
commit 2beb03f4b7
11 changed files with 237 additions and 22 deletions

View File

@@ -21,6 +21,7 @@ import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.WindowManager;
import com.android.settings.R;
public class SearchActivity extends Activity {
@@ -29,6 +30,8 @@ public class SearchActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_main);
// Keeps layouts in-place when keyboard opens.
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
FragmentManager fragmentManager = getFragmentManager();
Fragment fragment = fragmentManager.findFragmentById(R.id.main_content);

View File

@@ -19,6 +19,7 @@ import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.view.View;
import com.android.settings.dashboard.SiteMapManager;
/**
@@ -68,4 +69,25 @@ public interface SearchFeatureProvider {
* Updates the Settings indexes
*/
void updateIndex(Context context);
/**
* Initializes the feedback button in case it was dismissed.
*/
default void initFeedbackButton() {
}
/**
* Show a button users can click to submit feedback on the quality of the search results.
*/
default void showFeedbackButton(SearchFragment fragment, View view) {
}
/**
* Hide the feedback button shown by
* {@link #showFeedbackButton(SearchFragment fragment, View view) showFeedbackButton}
*/
default void hideFeedbackButton() {
}
}

View File

@@ -31,6 +31,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.SearchView;
@@ -71,7 +72,7 @@ public class SearchFragment extends InstrumentedFragment implements
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
static final String RESULT_CLICK_COUNT = "settings_search_result_click_count";
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
@VisibleForTesting
String mQuery;
private final SaveQueryRecorderCallback mSaveQueryRecorderCallback =
@@ -89,6 +90,7 @@ public class SearchFragment extends InstrumentedFragment implements
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
RecyclerView mResultsRecyclerView;
private SearchView mSearchView;
private LinearLayout mNoResultsView;
@VisibleForTesting
final RecyclerView.OnScrollListener mScrollListener =
@@ -118,6 +120,8 @@ public class SearchFragment extends InstrumentedFragment implements
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mSearchAdapter = new SearchResultsAdapter(this);
mSearchFeatureProvider.initFeedbackButton();
final LoaderManager loaderManager = getLoaderManager();
@@ -155,6 +159,8 @@ public class SearchFragment extends InstrumentedFragment implements
mResultsRecyclerView.setAdapter(mSearchAdapter);
mResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mResultsRecyclerView.addOnScrollListener(mScrollListener);
mNoResultsView = (LinearLayout) view.findViewById(R.id.no_results_layout);
return view;
}
@@ -184,16 +190,26 @@ public class SearchFragment extends InstrumentedFragment implements
if (TextUtils.equals(query, mQuery)) {
return true;
}
final boolean isEmptyQuery = TextUtils.isEmpty(query);
// Hide no-results-view when the new query is not a super-string of the previous
if ((mQuery != null) && (mNoResultsView.getVisibility() == View.VISIBLE)
&& (query.length() < mQuery.length())) {
mNoResultsView.setVisibility(View.GONE);
}
mResultClickCount = 0;
mNeverEnteredQuery = false;
mQuery = query;
mSearchAdapter.clearResults();
if (TextUtils.isEmpty(mQuery)) {
if (isEmptyQuery) {
final LoaderManager loaderManager = getLoaderManager();
loaderManager.destroyLoader(LOADER_ID_DATABASE);
loaderManager.destroyLoader(LOADER_ID_INSTALLED_APPS);
loaderManager.restartLoader(LOADER_ID_RECENTS, null /* args */, this /* callback */);
mSearchFeatureProvider.hideFeedbackButton();
} else {
restartLoaders();
}
@@ -232,7 +248,12 @@ public class SearchFragment extends InstrumentedFragment implements
mSearchAdapter.addResultsToMap(data, loader.getClass().getName());
if (mUnfinishedLoadersCount.decrementAndGet() == 0) {
mSearchAdapter.mergeResults();
final int resultCount = mSearchAdapter.mergeResults();
mSearchFeatureProvider.showFeedbackButton(this, getView());
if (resultCount == 0) {
mNoResultsView.setVisibility(View.VISIBLE);
}
}
}
@@ -257,6 +278,14 @@ public class SearchFragment extends InstrumentedFragment implements
loaderManager.restartLoader(LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
}
public String getQuery() {
return mQuery;
}
public List<SearchResult> getSearchResults() {
return mSearchAdapter.getSearchResults();
}
@VisibleForTesting (otherwise = VisibleForTesting.PRIVATE)
SearchView makeSearchView(ActionBar actionBar, String query) {
final SearchView searchView = new SearchView(actionBar.getThemedContext());
@@ -304,4 +333,4 @@ public class SearchFragment extends InstrumentedFragment implements
}
}
}
}

View File

@@ -106,8 +106,10 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
/**
* Merge the results from each of the loaders into one list for the adapter.
* Prioritizes results from the local database over installed apps.
*
* @return Number of matched results
*/
public void mergeResults() {
public int mergeResults() {
final List<? extends SearchResult> databaseResults = mResultsMap
.get(DatabaseResultLoader.class.getName());
final List<? extends SearchResult> installedAppResults = mResultsMap
@@ -139,6 +141,8 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
mSearchResults.addAll(results);
notifyDataSetChanged();
return mSearchResults.size();
}
public void clearResults() {