включение / отключение масштабирования в Android WebView


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

  • WebSettings.setSupportZoom
  • WebSettings.setbuildinzoomcontrols

Я заметил, что они работают по-разному на некоторых устройствах. Например, на моем Galaxy S pinch to zoom включен по умолчанию, но на LG P500 он отключен (и теперь я не знаю, как включить только pinch для масштабирования, но скрыть кнопки масштабирования).

на 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 62

8 ответов:

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

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

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

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

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

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

согласно SDK:

public void setDisplayZoomControls (boolean enabled) 

Так как: уровень API 11

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

у нас была такая же проблема при работе над 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 4 (Android 1.6).


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

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

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

Я немного модифицирую решение Лукаса кнута:

1) нет необходимости в подклассе webview,

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

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

  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);
  }

у Лукаса кнута есть хорошее решение, но на android 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);
}

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

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

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

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

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

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;
    }

}

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

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