mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1041026 - Move search bar logic into custom view. r=eedens
This commit is contained in:
parent
131ef1ed4e
commit
c8e8a04188
@ -13,6 +13,7 @@ import android.view.View;
|
||||
|
||||
import org.mozilla.gecko.db.BrowserContract.SearchHistory;
|
||||
import org.mozilla.search.autocomplete.AcceptsSearchQuery;
|
||||
import org.mozilla.search.autocomplete.SearchFragment;
|
||||
|
||||
/**
|
||||
* The main entrance for the Android search intent.
|
||||
@ -58,8 +59,12 @@ public class MainActivity extends FragmentActivity implements AcceptsSearchQuery
|
||||
public void onSearch(String query) {
|
||||
startPostsearch();
|
||||
storeQuery(query);
|
||||
|
||||
((PostSearchFragment) getSupportFragmentManager().findFragmentById(R.id.postsearch))
|
||||
.setUrl("https://search.yahoo.com/search?p=" + Uri.encode(query));
|
||||
|
||||
((SearchFragment) getSupportFragmentManager().findFragmentById(R.id.search_fragment))
|
||||
.setSearchTerm(query);
|
||||
}
|
||||
|
||||
private void startPresearch() {
|
||||
|
@ -0,0 +1,123 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.search.autocomplete;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mozilla.search.R;
|
||||
|
||||
public class ClearableEditText extends FrameLayout {
|
||||
|
||||
private EditText editText;
|
||||
private Button clearButton;
|
||||
private InputMethodManager inputMethodManager;
|
||||
|
||||
private TextListener listener;
|
||||
|
||||
private boolean active;
|
||||
|
||||
public interface TextListener {
|
||||
public void onChange(String text);
|
||||
public void onSubmit(String text);
|
||||
}
|
||||
|
||||
public ClearableEditText(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.clearable_edit_text, this);
|
||||
|
||||
editText = (EditText) findViewById(R.id.edit_text);
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (listener != null) {
|
||||
listener.onChange(s.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Attach a listener for the "search" key on the keyboard.
|
||||
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (listener != null && actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
listener.onSubmit(v.getText().toString());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
clearButton = (Button) findViewById(R.id.clear_button);
|
||||
clearButton.setOnClickListener(new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
editText.setText("");
|
||||
}
|
||||
});
|
||||
|
||||
inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
editText.setText(text);
|
||||
|
||||
// Move cursor to end of search input.
|
||||
editText.setSelection(text.length());
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
if (this.active == active) {
|
||||
return;
|
||||
}
|
||||
this.active = active;
|
||||
|
||||
clearButton.setVisibility(active ? View.VISIBLE : View.GONE);
|
||||
|
||||
editText.setFocusable(active);
|
||||
editText.setFocusableInTouchMode(active);
|
||||
|
||||
if (active) {
|
||||
editText.requestFocus();
|
||||
inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
|
||||
} else {
|
||||
editText.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextListener(TextListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent e) {
|
||||
// When the view is active, pass touch events to child views.
|
||||
// Otherwise, intercept touch events to allow click listeners on the view to
|
||||
// fire no matter where the user clicks.
|
||||
return !active;
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
|
||||
package org.mozilla.search.autocomplete;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
@ -12,21 +11,13 @@ import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.text.Editable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mozilla.search.R;
|
||||
|
||||
@ -39,8 +30,7 @@ import java.util.List;
|
||||
* <p/>
|
||||
* TODO: Add more search providers (other than the dictionary)
|
||||
*/
|
||||
public class SearchFragment extends Fragment
|
||||
implements TextView.OnEditorActionListener, AcceptsJumpTaps {
|
||||
public class SearchFragment extends Fragment implements AcceptsJumpTaps {
|
||||
|
||||
private static final int LOADER_ID_SUGGESTION = 0;
|
||||
private static final String KEY_SEARCH_TERM = "search_term";
|
||||
@ -54,16 +44,14 @@ public class SearchFragment extends Fragment
|
||||
// Color of search term match in search suggestion
|
||||
private static final int SUGGESTION_HIGHLIGHT_COLOR = 0xFF999999;
|
||||
|
||||
private AcceptsSearchQuery searchListener;
|
||||
private SuggestClient suggestClient;
|
||||
private SuggestionLoaderCallbacks suggestionLoaderCallbacks;
|
||||
|
||||
private InputMethodManager inputMethodManager;
|
||||
private AutoCompleteAdapter autoCompleteAdapter;
|
||||
|
||||
private View mainView;
|
||||
private View searchBar;
|
||||
private EditText editText;
|
||||
private Button clearButton;
|
||||
private ClearableEditText editText;
|
||||
private ListView suggestionDropdown;
|
||||
|
||||
private State state = State.WAITING;
|
||||
@ -81,6 +69,12 @@ public class SearchFragment extends Fragment
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
if (activity instanceof AcceptsSearchQuery) {
|
||||
searchListener = (AcceptsSearchQuery) activity;
|
||||
} else {
|
||||
throw new ClassCastException(activity.toString() + " must implement AcceptsSearchQuery.");
|
||||
}
|
||||
|
||||
// TODO: Don't hard-code this template string (bug 1039758)
|
||||
final String template = "https://search.yahoo.com/sugg/ff?" +
|
||||
"output=fxjson&appid=ffm&command=__searchTerms__&nresults=" + SUGGESTION_MAX;
|
||||
@ -88,7 +82,6 @@ public class SearchFragment extends Fragment
|
||||
suggestClient = new SuggestClient(activity, template, SUGGESTION_TIMEOUT, SUGGESTION_MAX);
|
||||
suggestionLoaderCallbacks = new SuggestionLoaderCallbacks();
|
||||
|
||||
inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
autoCompleteAdapter = new AutoCompleteAdapter(activity, this);
|
||||
}
|
||||
|
||||
@ -96,9 +89,9 @@ public class SearchFragment extends Fragment
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
|
||||
searchListener = null;
|
||||
suggestClient = null;
|
||||
suggestionLoaderCallbacks = null;
|
||||
inputMethodManager = null;
|
||||
autoCompleteAdapter = null;
|
||||
}
|
||||
|
||||
@ -115,42 +108,28 @@ public class SearchFragment extends Fragment
|
||||
}
|
||||
});
|
||||
|
||||
searchBar = mainView.findViewById(R.id.search_bar);
|
||||
editText = (EditText) mainView.findViewById(R.id.search_bar_edit_text);
|
||||
|
||||
final View.OnClickListener transitionToRunningListener = new View.OnClickListener() {
|
||||
editText = (ClearableEditText) mainView.findViewById(R.id.auto_complete_edit_text);
|
||||
editText.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
transitionToRunning();
|
||||
}
|
||||
};
|
||||
searchBar.setOnClickListener(transitionToRunningListener);
|
||||
editText.setOnClickListener(transitionToRunningListener);
|
||||
|
||||
// Attach a listener for the "search" key on the keyboard.
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(KEY_SEARCH_TERM, s.toString());
|
||||
getLoaderManager().restartLoader(LOADER_ID_SUGGESTION, args, suggestionLoaderCallbacks);
|
||||
}
|
||||
});
|
||||
editText.setOnEditorActionListener(this);
|
||||
|
||||
clearButton = (Button) mainView.findViewById(R.id.search_bar_clear_button);
|
||||
clearButton.setOnClickListener(new View.OnClickListener(){
|
||||
editText.setTextListener(new ClearableEditText.TextListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
editText.setText("");
|
||||
public void onChange(String text) {
|
||||
if (state == State.RUNNING) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(KEY_SEARCH_TERM, text);
|
||||
getLoaderManager().restartLoader(LOADER_ID_SUGGESTION, args, suggestionLoaderCallbacks);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubmit(String text) {
|
||||
transitionToWaiting();
|
||||
searchListener.onSearch(text);
|
||||
}
|
||||
});
|
||||
|
||||
@ -162,7 +141,9 @@ public class SearchFragment extends Fragment
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final Suggestion suggestion = (Suggestion) suggestionDropdown.getItemAtPosition(position);
|
||||
startSearch(suggestion.value);
|
||||
|
||||
transitionToWaiting();
|
||||
searchListener.onSearch(suggestion.value);
|
||||
}
|
||||
});
|
||||
|
||||
@ -173,9 +154,7 @@ public class SearchFragment extends Fragment
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
searchBar = null;
|
||||
editText = null;
|
||||
clearButton = null;
|
||||
|
||||
if (null != suggestionDropdown) {
|
||||
suggestionDropdown.setOnItemClickListener(null);
|
||||
@ -184,78 +163,41 @@ public class SearchFragment extends Fragment
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for the "search" button on the keyboard.
|
||||
*/
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
startSearch(v.getText().toString());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
public void onJumpTap(String suggestion) {
|
||||
setSearchTerm(suggestion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a search intent and put the widget into waiting.
|
||||
* Sets the search term in the search bar. If the SearchFragment is
|
||||
* in State.RUNNING, this will also update the search suggestions.
|
||||
*
|
||||
* @param searchTerm
|
||||
*/
|
||||
private void startSearch(String queryString) {
|
||||
if (getActivity() instanceof AcceptsSearchQuery) {
|
||||
editText.setText(queryString);
|
||||
editText.setSelection(queryString.length());
|
||||
transitionToWaiting();
|
||||
((AcceptsSearchQuery) getActivity()).onSearch(queryString);
|
||||
} else {
|
||||
throw new RuntimeException("Parent activity does not implement AcceptsSearchQuery.");
|
||||
}
|
||||
public void setSearchTerm(String searchTerm) {
|
||||
editText.setText(searchTerm);
|
||||
}
|
||||
|
||||
private void transitionToWaiting() {
|
||||
if (state == State.WAITING) {
|
||||
return;
|
||||
}
|
||||
|
||||
setEditTextFocusable(false);
|
||||
mainView.setClickable(false);
|
||||
|
||||
suggestionDropdown.setVisibility(View.GONE);
|
||||
clearButton.setVisibility(View.GONE);
|
||||
|
||||
state = State.WAITING;
|
||||
|
||||
mainView.setClickable(false);
|
||||
editText.setActive(false);
|
||||
suggestionDropdown.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void transitionToRunning() {
|
||||
if (state == State.RUNNING) {
|
||||
return;
|
||||
}
|
||||
|
||||
setEditTextFocusable(true);
|
||||
mainView.setClickable(true);
|
||||
|
||||
suggestionDropdown.setVisibility(View.VISIBLE);
|
||||
clearButton.setVisibility(View.VISIBLE);
|
||||
|
||||
state = State.RUNNING;
|
||||
}
|
||||
|
||||
private void setEditTextFocusable(boolean focusable) {
|
||||
editText.setFocusable(focusable);
|
||||
editText.setFocusableInTouchMode(focusable);
|
||||
|
||||
if (focusable) {
|
||||
editText.requestFocus();
|
||||
inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
|
||||
} else {
|
||||
editText.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJumpTap(String suggestion) {
|
||||
editText.setText(suggestion);
|
||||
// Move cursor to end of search input.
|
||||
editText.setSelection(suggestion.length());
|
||||
mainView.setClickable(true);
|
||||
editText.setActive(true);
|
||||
suggestionDropdown.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public static class Suggestion {
|
||||
|
28
mobile/android/search/res/layout/clearable_edit_text.xml
Normal file
28
mobile/android/search/res/layout/clearable_edit_text.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionSearch"
|
||||
android:inputType="textNoSuggestions|textVisiblePassword"
|
||||
android:drawableLeft="@drawable/search_icon"
|
||||
android:drawablePadding="10dp"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:hint="@string/search_bar_hint"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/clear_button"
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="@drawable/search_clear"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</merge>
|
@ -11,34 +11,11 @@
|
||||
android:clickable="false"
|
||||
tools:context=".autocomplete.AutoCompleteFragment">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/search_bar"
|
||||
<org.mozilla.search.autocomplete.ClearableEditText
|
||||
android:id="@+id/auto_complete_edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/search_bar_edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionSearch"
|
||||
android:inputType="textNoSuggestions|textVisiblePassword"
|
||||
android:drawableLeft="@drawable/search_icon"
|
||||
android:drawablePadding="10dp"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:hint="@string/search_bar_hint"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/search_bar_clear_button"
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="@drawable/search_clear"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</FrameLayout>
|
||||
android:padding="10dp"/>
|
||||
|
||||
<ListView
|
||||
android:id="@+id/auto_complete_dropdown"
|
||||
|
@ -8,6 +8,7 @@ search_activity_sources = [
|
||||
'java/org/mozilla/search/autocomplete/AcceptsJumpTaps.java',
|
||||
'java/org/mozilla/search/autocomplete/AcceptsSearchQuery.java',
|
||||
'java/org/mozilla/search/autocomplete/AutoCompleteAdapter.java',
|
||||
'java/org/mozilla/search/autocomplete/ClearableEditText.java',
|
||||
'java/org/mozilla/search/autocomplete/SearchFragment.java',
|
||||
'java/org/mozilla/search/autocomplete/SuggestClient.java',
|
||||
'java/org/mozilla/search/Constants.java',
|
||||
|
Loading…
Reference in New Issue
Block a user