diff --git a/res/drawable-hdpi/ic_find_next_mtrl_alpha.png b/res/drawable-hdpi/ic_find_next_mtrl_alpha.png
new file mode 100644
index 00000000..6d5edac4
Binary files /dev/null and b/res/drawable-hdpi/ic_find_next_mtrl_alpha.png differ
diff --git a/res/drawable-hdpi/ic_find_previous_mtrl_alpha.png b/res/drawable-hdpi/ic_find_previous_mtrl_alpha.png
new file mode 100644
index 00000000..a5921afe
Binary files /dev/null and b/res/drawable-hdpi/ic_find_previous_mtrl_alpha.png differ
diff --git a/res/drawable-mdpi/ic_find_next_mtrl_alpha.png b/res/drawable-mdpi/ic_find_next_mtrl_alpha.png
new file mode 100644
index 00000000..1cfdb3fe
Binary files /dev/null and b/res/drawable-mdpi/ic_find_next_mtrl_alpha.png differ
diff --git a/res/drawable-mdpi/ic_find_previous_mtrl_alpha.png b/res/drawable-mdpi/ic_find_previous_mtrl_alpha.png
new file mode 100644
index 00000000..0d3c009d
Binary files /dev/null and b/res/drawable-mdpi/ic_find_previous_mtrl_alpha.png differ
diff --git a/res/drawable-xhdpi/ic_find_next_mtrl_alpha.png b/res/drawable-xhdpi/ic_find_next_mtrl_alpha.png
new file mode 100644
index 00000000..9038282d
Binary files /dev/null and b/res/drawable-xhdpi/ic_find_next_mtrl_alpha.png differ
diff --git a/res/drawable-xhdpi/ic_find_previous_mtrl_alpha.png b/res/drawable-xhdpi/ic_find_previous_mtrl_alpha.png
new file mode 100644
index 00000000..579347f2
Binary files /dev/null and b/res/drawable-xhdpi/ic_find_previous_mtrl_alpha.png differ
diff --git a/res/drawable-xxhdpi/ic_find_next_mtrl_alpha.png b/res/drawable-xxhdpi/ic_find_next_mtrl_alpha.png
new file mode 100644
index 00000000..e3a7e9e6
Binary files /dev/null and b/res/drawable-xxhdpi/ic_find_next_mtrl_alpha.png differ
diff --git a/res/drawable-xxhdpi/ic_find_previous_mtrl_alpha.png b/res/drawable-xxhdpi/ic_find_previous_mtrl_alpha.png
new file mode 100644
index 00000000..f9cf16cf
Binary files /dev/null and b/res/drawable-xxhdpi/ic_find_previous_mtrl_alpha.png differ
diff --git a/res/drawable/ic_find_next_material.xml b/res/drawable/ic_find_next_material.xml
new file mode 100644
index 00000000..c6674ebf
--- /dev/null
+++ b/res/drawable/ic_find_next_material.xml
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/res/drawable/ic_find_previous_material.xml b/res/drawable/ic_find_previous_material.xml
new file mode 100644
index 00000000..32fcb315
--- /dev/null
+++ b/res/drawable/ic_find_previous_material.xml
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/res/layout/webview_find.xml b/res/layout/webview_find.xml
new file mode 100644
index 00000000..5cdf67af
--- /dev/null
+++ b/res/layout/webview_find.xml
@@ -0,0 +1,20 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/menu/webview_find.xml b/res/menu/webview_find.xml
new file mode 100644
index 00000000..41bb36e6
--- /dev/null
+++ b/res/menu/webview_find.xml
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 5ffdd9fc..01ba596d 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -96,4 +96,5 @@
Lade externen Inhalt
Vollbild
Lautstärketasten für die Navigation verwenden
+ Suche in Seite
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 324f8518..8684130e 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -102,5 +102,8 @@
Pantalla completa
Usar botones de volumen para navegación
Acceso de archivo denegado, saliendo...
+ Buscar en la página
+ Siguiente
+ Anterior"
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 69a46428..cf08c998 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -102,5 +102,8 @@
Auto
Plein écran
Utiliser les boutons du volume +/- pour haut/bas
+ Rechercher sur la page
+ Suivant
+ Précédent
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 2b268ee8..9ef9a51c 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -94,7 +94,10 @@ is missing a quantity used in that language, otherwise the app will crash
Stile interfaccia utente
Chiaro
Scuro
- Carica contenuto remoto
- Schermo intero
- Usare i tasti del volume per la navigazione
+Carica contenuto remoto
+Schermo intero
+Usare i tasti del volume per la navigazione
+Trova nella pagina
+Successivo
+Precedente
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 86a30a11..cb0069d2 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -87,4 +87,5 @@
Загрузить удалённый контент
Весь экран
Использовать кнопки громкости для навигации
+ Поиск на странице
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d8b041cf..83b24b17 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -109,4 +109,7 @@
Full Screen
Use volume buttons for navigation
File access was not allowed, quitting...
+ Find in page
+ Next
+ Previous
diff --git a/src/itkach/aard2/ArticleFragment.java b/src/itkach/aard2/ArticleFragment.java
index 7341aeef..751e053d 100644
--- a/src/itkach/aard2/ArticleFragment.java
+++ b/src/itkach/aard2/ArticleFragment.java
@@ -73,7 +73,6 @@ private void displayBookmarked(boolean value) {
}
}
- @SuppressWarnings("deprecation")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
diff --git a/src/itkach/aard2/ArticleWebView.java b/src/itkach/aard2/ArticleWebView.java
index 378f801a..c47ad693 100644
--- a/src/itkach/aard2/ArticleWebView.java
+++ b/src/itkach/aard2/ArticleWebView.java
@@ -33,7 +33,7 @@
import java.util.TimerTask;
import java.util.TreeSet;
-public class ArticleWebView extends WebView {
+public class ArticleWebView extends SearchableWebView {
public static final String LOCALHOST = Application.LOCALHOST;
private final String styleSwitcherJs;
diff --git a/src/itkach/aard2/FindActionModeCallback.java b/src/itkach/aard2/FindActionModeCallback.java
new file mode 100644
index 00000000..a962ae7f
--- /dev/null
+++ b/src/itkach/aard2/FindActionModeCallback.java
@@ -0,0 +1,150 @@
+/*
+* This file is heavily inspired by the Android Open Source Project
+* licensed under the Apache License, Version 2.0
+*/
+
+package itkach.aard2;
+
+import android.content.Context;
+import android.os.Build;
+import android.text.Editable;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.TextWatcher;
+import android.view.ActionMode;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+
+class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
+ View.OnLongClickListener, View.OnClickListener {
+
+ private View searchView;
+ private EditText editText;
+ private SearchableWebView webview;
+ private InputMethodManager imManager;
+
+ FindActionModeCallback(Context context, SearchableWebView webview) {
+ this.webview = webview;
+ searchView = LayoutInflater.from(context).inflate(R.layout.webview_find, null);
+
+ editText = searchView.findViewById(R.id.edit);
+ editText.setOnLongClickListener(this);
+ editText.setOnClickListener(this);
+ editText.addTextChangedListener(this);
+
+ imManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ }
+
+ /* Place text in the text field so it can be searched for. */
+ void setText(String text) {
+ editText.setText(text);
+ Spannable span = (Spannable) editText.getText();
+ int length = span.length();
+ // Ideally, we would like to set the selection to the whole field,
+ // but this brings up the Text selection CAB, which dismisses this
+ // one.
+ Selection.setSelection(span, length, length);
+ // Necessary each time we set the text, so that this will watch
+ // changes to it.
+ span.setSpan(this, 0, length, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ }
+
+ /*
+ * Move the highlight to the next match.
+ * @param next If true, find the next match further down in the document.
+ * If false, find the previous match, up in the document.
+ */
+ private void findNext(boolean next) {
+ webview.findNext(next);
+ }
+
+ /*
+ * Highlight all the instances of the string from editText in webview.
+ */
+ void findAll() {
+ String find = editText.getText().toString();
+
+ if (Build.VERSION.SDK_INT < 16)
+ webview.findAll(find);
+ else
+ webview.findAllAsync(find);
+ }
+
+ void showSoftInput() {
+ // imManager.showSoftInputMethod doesn't work
+ imManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+ }
+
+ // OnLongClickListener implementation
+ @Override
+ public boolean onLongClick(View v) {
+ // Override long click so that select ActionMode is not opened, which
+ // would exit find ActionMode.
+ return true;
+ }
+
+ // OnClickListener implementation
+ @Override
+ public void onClick(View v) {
+ findNext(true);
+ }
+
+ // ActionMode.Callback implementation
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ mode.setCustomView(searchView);
+ mode.getMenuInflater().inflate(R.menu.webview_find, menu);
+
+ Editable edit = editText.getText();
+ Selection.setSelection(edit, edit.length());
+ editText.requestFocus();
+ return true;
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ webview.clearMatches();
+ imManager.hideSoftInputFromWindow(webview.getWindowToken(), 0);
+ webview.setLastFind(editText.getText().toString());
+ }
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ imManager.hideSoftInputFromWindow(webview.getWindowToken(), 0);
+ switch(item.getItemId()) {
+ case R.id.find_prev:
+ findNext(false);
+ break;
+ case R.id.find_next:
+ findNext(true);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ // TextWatcher implementation
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // Does nothing. Needed to implement TextWatcher.
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ findAll();
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ // Does nothing. Needed to implement TextWatcher.
+ }
+}
\ No newline at end of file
diff --git a/src/itkach/aard2/SearchableWebView.java b/src/itkach/aard2/SearchableWebView.java
new file mode 100644
index 00000000..f112a271
--- /dev/null
+++ b/src/itkach/aard2/SearchableWebView.java
@@ -0,0 +1,63 @@
+/*
+ * This file is heavily inspired by the Android Open Source Project
+ * licensed under the Apache License, Version 2.0
+ */
+
+package itkach.aard2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.webkit.WebView;
+
+class SearchableWebView extends WebView {
+
+ private String mLastFind = null;
+
+ public void setLastFind(String find) {
+ mLastFind = find;
+ }
+
+ public SearchableWebView(Context context) {
+ this(context, null);
+ }
+
+ public SearchableWebView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ /**
+ * Start an ActionMode for finding text in this WebView. Only works if this
+ * WebView is attached to the view system.
+ *
+ * @param text If non-null, will be the initial text to search for.
+ * Otherwise, the last String searched for in this WebView will
+ * be used to start.
+ * @param showIme If true, show the IME, assuming the user will begin typing.
+ * If false and text is non-null, perform a find all.
+ * @return boolean True if the find dialog is shown, false otherwise.
+ */
+ @Override
+ public boolean showFindDialog(String text, boolean showIme) {
+ FindActionModeCallback callback = new FindActionModeCallback(getContext(), this);
+ if (getParent() == null || startActionMode(callback) == null) {
+ // Could not start the action mode, so end Find on page
+ return false;
+ }
+
+ if (showIme) {
+ callback.showSoftInput();
+ } else if (text != null) {
+ callback.setText(text);
+ callback.findAll();
+ return true;
+ }
+ if (text == null) {
+ text = mLastFind;
+ }
+ if (text != null) {
+ callback.setText(text);
+ callback.findAll();
+ }
+ return true;
+ }
+}