включить / отключить масштабирование в Android WebView - PullRequest
64 голосов
/ 26 февраля 2011

В WebSettings есть несколько методов, связанных с масштабированием:

  • WebSettings.setSupportZoom
  • WebSettings.setBuiltInZoomControls

Я заметил, что они работают по-разному на некоторых устройствах. Например, на моем Galaxy S функция масштабирования по умолчанию включена, но на LG P500 она отключена (и теперь я не знаю, как включить ТОЛЬКО масштабирование, но скрыть кнопки масштабирования).

На P500, когда я звоню setBuiltInZoomControls(true), работают оба этих варианта (мультитач и кнопки).

Как включить мультисенсорное масштабирование и отключить кнопки масштабирования на устройствах, таких как LG P500? (Также я знаю, что такие же проблемы есть на устройствах HTC)

ОБНОВЛЕНИЕ: Вот почти полный код для решения

    if (ev.getAction() == MotionEvent.ACTION_DOWN ||
            ev.getAction() == MotionEvent.ACTION_POINTER_DOWN ||
            ev.getAction() == MotionEvent.ACTION_POINTER_1_DOWN ||
            ev.getAction() == MotionEvent.ACTION_POINTER_2_DOWN ||
            ev.getAction() == MotionEvent.ACTION_POINTER_3_DOWN) {
        if (multiTouchZoom && !buttonsZoom) {
            if (getPointerCount(ev) > 1) {
                getSettings().setBuiltInZoomControls(true);
                getSettings().setSupportZoom(true);
            } else {
                getSettings().setBuiltInZoomControls(false);
                getSettings().setSupportZoom(false);
            }
        }
    }

    if (!multiTouchZoom && buttonsZoom) {
        if (getPointerCount(ev) > 1) {
            return true;
        }
    }

Этот код находится в моем onTouchEvent переопределенном методе WebView.

Ответы [ 8 ]

110 голосов
/ 26 октября 2011

В API> = 11 вы можете использовать:

wv.getSettings().setBuiltInZoomControls(true);
wv.getSettings().setDisplayZoomControls(false);

Согласно SDK:

public void setDisplayZoomControls (boolean enabled) 

С: Уровень API 11

Устанавливает, используются ли кнопки масштабирования на экране.Комбинация встроенных элементов управления масштабированием включена и отключены элементы управления масштабированием на экране позволяет масштабировать пинч, чтобы работать без элементов управления на экране

37 голосов
/ 18 марта 2011

Я посмотрел исходный код для WebView и пришел к выводу, что не существует элегантного способа выполнить то, что вы просите.

В итоге я создал подкласс WebView и переопределил OnTouchEvent. В OnTouchEvent для ACTION_DOWN я проверяю, сколько указателей там используется MotionEvent.getPointerCount(). Если есть более одного указателя, я звоню setSupportZoom(true), в противном случае я звоню setSupportZoom(false). Я тогда называю super.OnTouchEvent().

Это эффективно отключит масштабирование при прокрутке (таким образом отключая элементы управления масштабированием) и включит масштабирование, когда пользователь собирается ущипнуть масштаб. Не очень хороший способ сделать это, но до сих пор он работал хорошо для меня.

Обратите внимание, что getPointerCount() был введен в 2.1, поэтому вам придется делать некоторые дополнительные вещи, если вы поддерживаете 1.6.

29 голосов
/ 10 августа 2012

У нас была та же проблема при работе над приложением Android для клиента, и мне удалось «взломать» это ограничение.

Я взглянул на исходный код Android для класса WebView и заметил updateZoomButtonsEnabled() -метод , который работал с ZoomButtonsController -объектом , чтобы включить и отключить управление масштабированием зависит от текущего масштаба браузера.

Я искал метод для возврата ZoomButtonsController -экземпляра и нашел getZoomButtonsController() -метод , который возвратил этот самый экземпляр.

Хотя метод объявлен public, он не задокументирован в WebView -документации, и Eclipse не может его найти. Итак, я попытался поразмышлять над этим и создал свой собственный WebView -подкласс, чтобы переопределить onTouchEvent() -метод, который вызвал элементы управления.

public class NoZoomControllWebView extends WebView {

    private ZoomButtonsController zoom_controll = null;

    public NoZoomControllWebView(Context context) {
        super(context);
        disableControls();
    }

    public NoZoomControllWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        disableControls();
    }

    public NoZoomControllWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        disableControls();
    }

    /**
     * Disable the controls
     */
    private void disableControls(){
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
            // Use the API 11+ calls to disable the controls
            this.getSettings().setBuiltInZoomControls(true);
            this.getSettings().setDisplayZoomControls(false);
        } else {
            // Use the reflection magic to make it work on earlier APIs
            getControlls();
        }
    }

    /**
     * This is where the magic happens :D
     */
    private void getControlls() {
        try {
            Class webview = Class.forName("android.webkit.WebView");
            Method method = webview.getMethod("getZoomButtonsController");
            zoom_controll = (ZoomButtonsController) method.invoke(this, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        super.onTouchEvent(ev);
        if (zoom_controll != null){
            // Hide the controlls AFTER they where made visible by the default implementation.
            zoom_controll.setVisible(false);
        }
        return true;
    }
}

Возможно, вы захотите удалить ненужные конструкторы и, возможно, отреагировать на исключения.

Хотя это выглядит хакерским и ненадежным, оно возвращается к API Level 4 (Android 1.6).


Как указывалось в комментариях @ jayellos , приватный getZoomButtonsController() -метод больше не существует в Android 4.0.4 и более поздних версиях.

Однако, это не нужно. Используя условное выполнение , мы можем проверить, находимся ли мы на устройстве с API уровня 11+ и использовать предоставляемые функции (см. @ Yuttadhammo answer), чтобы скрыть элементы управления.

Я обновил приведенный выше пример кода, чтобы сделать именно это.

10 голосов
/ 07 февраля 2013

Я немного изменил решение Лукаса Кнута:

1) Нет необходимости создавать подкласс для веб-просмотра,

2) код будет зависать при проверке байт-кода на некоторых устройствах Android 1.6, если вы не поместите несуществующие методы в отдельные классы

3) Элементы управления масштабом будут отображаться, если пользователь прокручивает страницу вверх / вниз. Я просто установил контейнер контроллера масштабирования на видимость GONE

  wv.getSettings().setSupportZoom(true);
  wv.getSettings().setBuiltInZoomControls(true);
  if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
    // Use the API 11+ calls to disable the controls
    // Use a seperate class to obtain 1.6 compatibility
    new Runnable() {
      public void run() {
        wv.getSettings().setDisplayZoomControls(false);
      }
    }.run();
  } else {
    final ZoomButtonsController zoom_controll =
        (ZoomButtonsController) wv.getClass().getMethod("getZoomButtonsController").invoke(wv, null);
    zoom_controll.getContainer().setVisibility(View.GONE);
  }
7 голосов
/ 16 октября 2012

У Лукаса Кнута есть хорошее решение, но на андроиде 4.0.4 на Samsung Galaxy SII я все равно смотрю элементы управления масштабированием.И я решаю это через

if (zoom_controll!=null && zoom_controll.getZoomControls()!=null)
{
   // Hide the controlls AFTER they where made visible by the default implementation.
   zoom_controll.getZoomControls().setVisibility(View.GONE);
}

вместо

if (zoom_controll != null){
   // Hide the controlls AFTER they where made visible by the default implementation.
   zoom_controll.setVisible(false);
}
1 голос
/ 04 мая 2013

Улучшена версия Лукаса Кнута:

public class TweakedWebView extends WebView {

    private ZoomButtonsController zoomButtons;

    public TweakedWebView(Context context) {
        super(context);
        init();
    }

    public TweakedWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public TweakedWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        getSettings().setBuiltInZoomControls(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            getSettings().setDisplayZoomControls(false);
        } else {
            try {
                Method method = getClass()
                        .getMethod("getZoomButtonsController");
                zoomButtons = (ZoomButtonsController) method.invoke(this);
            } catch (Exception e) {
                // pass
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean result = super.onTouchEvent(ev);
        if (zoomButtons != null) {
            zoomButtons.setVisible(false);
            zoomButtons.getZoomControls().setVisibility(View.GONE);
        }
        return result;
    }

}
1 голос
/ 07 июля 2011

Похоже, что опубликованное вами решение не дает элементам управления масштабированием появляться при перетаскивании пользователем, однако существуют ситуации, когда пользователь ущипывает масштабирование и появляются элементы управления масштабированием.Я заметил, что есть 2 способа, которыми веб-просмотр будет принимать масштабирование пинча, и только один из них заставляет элементы управления масштабированием появляться несмотря на ваш код:

Появляются пользовательские масштабирования и элементы управления:

ACTION_DOWN
getSettings().setBuiltInZoomControls(false); getSettings().setSupportZoom(false);
ACTION_POINTER_2_DOWN
getSettings().setBuiltInZoomControls(true); getSettings().setSupportZoom(true);
ACTION_MOVE (Repeat several times, as the user moves their fingers)
ACTION_POINTER_2_UP
ACTION_UP

Пинч-зум пользователя и элементы управления не отображаются:

ACTION_DOWN
getSettings().setBuiltInZoomControls(false); getSettings().setSupportZoom(false);
ACTION_POINTER_2_DOWN
getSettings().setBuiltInZoomControls(true); getSettings().setSupportZoom(true);
ACTION_MOVE (Repeat several times, as the user moves their fingers)
ACTION_POINTER_1_UP
ACTION_POINTER_UP
ACTION_UP

Можете ли вы пролить больше света на свое решение?

0 голосов
/ 06 декабря 2016

Привет всем, кто может искать решение, подобное этому ... У меня была проблема с масштабированием внутри WebView, поэтому лучший способ сделать это - в вашем java.class, где вы установили все для webView, поместить эту две строки кода: это имя моего webView -> webViewSearch = (WebView) findViewById (R.id.id_webview_search);)

// force WebView to show content not zoomed---------------------------------------------------------
    webViewSearch.getSettings().setLoadWithOverviewMode(true);
    webViewSearch.getSettings().setUseWideViewPort(true);
...