вторник, 11 марта 2014 г.

WebView локальный перехват кликов

Среди стандартных контролов ОС Андоид есть встраиваемый браузер - WebView, мощный компонент по отображению информации. Он обладает богатым функционалом по форматированию, в том числе и текста, по сравнению с элементом UI TextView. Яркий пример - табуляция абзацев, а так же он поддерживает HTML-теги, а не куций их набор. Однако, есть одна особенность - загрузили локально в него текст c помощью метода loadData, а в нём стоит ссылка,но прицепить обработчик клика на эту ссылку не удастся. Решение подкатом.

Найти решение гуглением не получилось:
http://stackoverflow.com/questions/5907439/get-the-click-event-from-webpage-in-my-android-application
http://stackoverflow.com/questions/5116909/how-i-can-get-onclick-event-on-webview-in-android
Все решения у меня не работали, подсказку нашел тут:
http://stackoverflow.com/questions/11527479/get-event-click-link-in-a-webview-android
Чувак Filipe Batista написал, замутите интерфейс для обработки javascript и дал ссылку на оф документацию по теме:
http://developer.android.com/guide/webapps/webview.html#BindingJavaScript
В общем я решил эту проблему с помощью встраивания javascript в html-код и "проброс" вызова функций в само приложение. Решение работает на API >=8 (android 2.2 и выше).
Первое, сделал класс, расширяющий WebView:
public class TextViewScroller extends WebView {

\\ конструкторы и всякая хрень пропущены

public void loadDataWithBaseURL(String page) {
  StringBuilder s = new StringBuilder();
  s.append("<!DOCTYPE >");
  s.append("<html xmlns=\"http://www.w3.org/1999/xhtml\" debug=\"true\">");
  s.append("<head>");
  s.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />");
  s.append("<meta name=\"viewport\" ");
  s.append("content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\"> ");
  s.append("<meta name=\"apple-mobile-web-app-capable\" content=\"yes\"> ");
  s.append("<meta name=\"viewport\" content=\"target-densitydpi=device-dpi\" /> ");
  s.append("<script type=\"text/javascript\"> ");
  s.append("function init(testVal)");
  s.append("{");
  s.append("AndroidFunction.click(testVal);");
  s.append("}");
  s.append("</script>");
  s.append("</head>");
  s.append("<body>");
  s.append(page);
  s.append("</body></html>");
  this.loadData(s.toString(), "text/html; charset=UTF-8", "utf-8");
 }
}
Самая главная часть, это метод loadDataWithBaseURL. Тут добавляется шапка для текста с описанием javascript-функции init(testVal) в теле которой происходит вызов функции из интерфейса AndroidFunction.
Второе, проинициализировал этот контрол так:
mWebView = (TextViewScroller) findViewById(R.id.TextView1);
mWebView.getSettings().setJavaScriptEnabled(true);
WebAppInterface www = new WebAppInterface(this);
mWebView.addJavascriptInterface(www, "AndroidFunction");
Тут включается поддержка javascript контролом, добавляется интерфейс. Сам интерфейс WebAppInterface выглядит так:
private class WebAppInterface {
  Context mContext;

  /** Instantiate the interface and set the context */
  WebAppInterface(Context c) {
   mContext = c;
  }

  @JavascriptInterface
  public void click(final String link) {

   runOnUiThread(new Runnable() {// запуск в потоке UI
    @Override
    public void run() {
     mSearch.setText(link);// вывод в EditText самой ссылки, mSearch - принадлежит activity, а сам этот интерфейс - приватный класс её, например
     }
    }
   });

  }
 }
Ну и последняя вещь, в самом тексте заместо ссылки надо вставить такие строчки (для того чтобы ссылка выглядела как ссылка):
page.append("<input value=\"");
    page.append("текст на экране");
    page.append("\" type=\"button\" name=\"submit\" style=\"border: none; background: transparent;color: blue;cursor: pointer;padding: 0px;margin-right:0px; \" ");
    page.append("id=\"btnSubmit\" onclick=\"javascript:return init(\'");
    page.append("текст, который придет в обработчик");
    page.append("');\" /> ");
Или такие, чтобы была как кнопка:
page.append("<input value=\"");
     page.append("текст на экране");
     page.append("\" type=\"button\" name=\"submit\" ");
     page.append("id=\"btnSubmit\" onclick=\"javascript:return init(\'");
     page.append("текст, который придет в обработчик");
     page.append("');\"/>");

Комментариев нет:

Отправить комментарий