Включить/отключить масштабирование в Android WebView
В 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.
Ответы
Ответ 1
Я посмотрел исходный код для WebView
, и я пришел к выводу, что нет элегантного способа выполнить то, что вы просите.
То, что я закончил, было подклассификация WebView
и переопределение OnTouchEvent
.
В OnTouchEvent
для ACTION_DOWN
, я проверяю, сколько указателей там используется MotionEvent.getPointerCount()
.
Если имеется более одного указателя, я вызываю setSupportZoom(true)
, иначе я вызываю setSupportZoom(false)
. Затем я вызываю super.OnTouchEvent().
Это приведет к эффективному отключению масштабирования при прокрутке (таким образом отключив элементы управления масштабированием) и включив масштабирование, когда пользователь собирается зажать масштаб. Не очень хороший способ сделать это, но он до сих пор хорошо работал у меня.
Обратите внимание, что getPointerCount()
был введен в 2.1, поэтому вам придется делать некоторые дополнительные вещи, если вы поддерживаете 1.6.
Ответ 2
В API >= 11 вы можете использовать:
wv.getSettings().setBuiltInZoomControls(true);
wv.getSettings().setDisplayZoomControls(false);
В соответствии с SDK:
public void setDisplayZoomControls (boolean enabled)
С: Уровень API 11
Устанавливает, используются ли кнопки масштабирования на экране. Сочетание встроенные средства управления масштабированием включены, а кнопки управления масштабированием экрана отключены позволяет щепотку масштабировать для работы без элементов управления на экране.
Ответ 3
У нас была та же проблема, когда мы работали над Android-приложением для клиента, и мне удалось "взломать" это ограничение.
Я взглянул на исходный код Android для класса WebView и заметил updateZoomButtonsEnabled()
-method, который работал с ZoomButtonsController
-object, чтобы включить или отключить элементы управления масштабированием в зависимости от текущего масштаба браузера.
Я искал метод возврата ZoomButtonsController
-instance и нашел getZoomButtonsController()
-method, который вернул этот самый экземпляр.
Хотя метод объявлен public
, он не документирован в WebView
-документации, и Eclipse тоже не смог его найти. Итак, я пробовал некоторое размышление над этим и создал свой собственный WebView
-subclass, чтобы переопределить метод 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), чтобы скрыть элементы управления.
Я обновил приведенный выше код примера, чтобы сделать именно это.
Ответ 4
Я немного изменил решение Лукаса Кнута:
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);
}
Ответ 5
У Лукаса Кнута есть хорошее решение, но на 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);
}
Ответ 6
Решение, которое вы опубликовали, похоже, работает с тем, чтобы остановить элементы управления масштабированием, появляющиеся при перетаскивании пользователя, однако есть ситуации, когда пользователь будет зажимать масштаб, и появятся кнопки управления увеличением. Я заметил, что есть два способа, по которым веб-просмотр будет принимать масштабирование, и только один из них приводит к появлению элементов управления увеличением, несмотря на ваш код:
Появятся пользовательские кнопки и элементы управления:
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
Можете ли вы пролить свет на свое решение?
Ответ 7
Улучшена версия Лукаса Кнута:
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;
}
}
Ответ 8
Эй, для тех, кто может искать такое решение.. У меня проблема с масштабированием внутри WebView, поэтому лучший способ сделать это в вашем java.class, где вы установили все для 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);