Вимкнути прокрутку у веб-перегляді?


86

До цього часу я був лише розробником iPhone, а тепер вирішив закрутити Android. Щось, що я не зміг зрозуміти на Android, це як програмно запобігти прокрутці в WebView?

Щось схоже на запобігання onTouchMoveзаходу iPhones було б чудово!

Відповіді:


179

Ось мій код для відключення всієї прокрутки у веб-перегляді:

  // disable scroll on touch
  webview.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
  });

Щоб приховати лише смуги прокрутки, але не вимкнути прокрутку:

WebView.setVerticalScrollBarEnabled(false);
WebView.setHorizontalScrollBarEnabled(false);

або ви можете спробувати використати макет з одним стовпцем, але це працює лише на простих сторінках і вимикає горизонтальну прокрутку:

   //Only disabled the horizontal scrolling:
   webview.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

Ви також можете спробувати обернути свій веб-перегляд вертикально прокручуваним прокручуванням і вимкнути всю прокрутку в веб-перегляді:

<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"    >
  <WebView
    android:id="@+id/mywebview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="none" />
</ScrollView>

І встановити

webview.setScrollContainer(false);

Не забудьте додати webview.setOnTouchListener(...)код вище, щоб вимкнути всю прокрутку в веб-перегляді. Вертикальний ScrollView дозволить прокручувати вміст WebView.


працює нормально, але через кілька секунд викликає збій на Samsung i5700 spica в /system/lib/libwebcore.so.
Лукас

LayoutAlgorithm.SINGLE_COLUMN або webview.setOnTouchListener?
peceps

3
Якщо ви розміщуєте WebView у ScrollView, встановіть для атрибута android: isScrollContainer WebView значення «false», а не встановлюйте для android: scrollbars «none». Це призводить до повного відключення обробки прокрутки веб-перегляду та дозволяє йому розширюватися відповідно до його змісту. Потім прокрутка буде оброблятися виключно батьківським ScrollView.
BladeCoder

1
Якщо вам потрібно обробляти MotionEvent.ACTION_MOVEподії, WebViewперегляньте мою відповідь нижче.
GDanger

1
Ігнорування ACTION_MOVEна setOnTouchListenerподія має деякі побічні ефекти , так що я б не рекомендував цей відповідь; 1. Швидкі пальці вважаються onclickподіями на сторінці. 2. Запобігає переповненню прокрутки елементів на сторінці, це може знадобитися для належної взаємодії залежно від сайту. 3. touchmoveПодія JS . @GDanger має правильну відповідь, яка має перевагу над overScrollByрозширенням, WebViewоскільки вона не має інших побічних ефектів, а лише запобігає прокрутці сторінки. stackoverflow.com/a/26129301/1244574
jkasten

22

Я не знаю, потрібно це вам все ще чи ні, але ось рішення:

appView = (WebView) findViewById(R.id.appView); 
appView.setVerticalScrollBarEnabled(false);
appView.setHorizontalScrollBarEnabled(false);

18
в порядку. це вимикає смуги прокрутки, але це не перешкоджає прокрутці шляхом перетягування. Здається, і html теж повинен поміститися ...
rdmueller

Якщо ви розробляєте свої веб-сторінки лише для веб-перегляду Android, я рекомендую зробити ваші веб-сторінки в таблиці. Ширина має бути приблизно width = "100%" і однаковою для висоти. так що перетягування більше не буде.
умар

ширина = 100% не завжди працює, наприклад: stackoverflow.com/questions/6460871 / ...
NoBugs

чудово .. це те, що мені потрібно. Дякую
Пітер

21

Здійснення WebViewігнорування подій руху - це неправильний шлях. Що робити, якщо WebViewпотрібно почути про ці події?

Натомість підкласуйте WebViewі замінюйте не приватні методи прокрутки.

public class NoScrollWebView extends WebView {
    ...
    @Override
    public boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, 
                                int scrollRangeX, int scrollRangeY, int maxOverScrollX, 
                                int maxOverScrollY, boolean isTouchEvent) {
        return false;
    }

    @Override
    public void scrollTo(int x, int y) {
        // Do nothing
    }

    @Override
    public void computeScroll() {
        // Do nothing
    }
}

Якщо ви подивіться на джерелі для WebViewви можете бачити , що onTouchEventвиклики , doDragякі називають overScrollBy .


1
Якщо вам потрібно програмно вимкнути / увімкнути прокрутку, подивіться на цей суть, яку я створив.
GDanger

1
Ваш метод працює для мене. І я цілком з вами згоден. У моєму випадку я не можу перетягнути смужку прогресу відео та аудіо, вбудовану в WebView, використовуючи відповідь "Прийняти".
codezjx

Це правильна відповідь. Хоча це потребує деяких доопрацювань у переважаючих конструкторах. Будь ласка, подивіться на мою повну відповідь нижче. stackoverflow.com/a/51936944/393502
Vansi

13

Додавання деталей полів до основного тексту запобіжить прокрутці, якщо вміст правильно обгортається, так:

<body leftmargin="0" topmargin="0" rightmargin="0" bottommargin="0">

Досить просто, і набагато менше коду + накладні помилки :)


1
Блискуче! +1 для простого рішення лише для HTML. Іноді я бажаю, щоб макет в android був таким же простим, як css ...
Pritesh Desai

Виглядає добре в стандартному браузері для Android, але, здається, не працює у Firefox (Fennec) ... незважаючи на те, що немає до чого прокручувати горизонтально, Firefox все ще дозволяє мені прокручуватись вправо до точки, де прокручується весь вміст поза екраном.
Michael

1
Не працює на сучасному WebView (Android 5 і новіших версій)
Роел

8

Встановіть слухача на своєму WebView:

webView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return(event.getAction() == MotionEvent.ACTION_MOVE));
            }
        });

3
У кінці returnрядка там є додаткова дужка . Крім того, це порушує події на полотні HTML5 та JavaScript.
Рохан Сінгх,

Це, безумовно, відключає його, але як мені вбити слухача пізніше, щоб увімкнути вхід? Я спробував event.getAction() != MotionEvent.ACTION_MOVE, а такожreturn true
ЦМК

Стандартний випадок "нічого не робити" - це return falseні return true.
Метью Прочитав

6

Я ще не пробував цього, оскільки ще не стикався з цією проблемою, але, можливо, ви могли б замінити функцію onScroll?

@Override
public void scrollTo(int x, int y){
super.scrollTo(0,y);
}

Це те, що ми називаємо в Індії Джугаадом ... хоча і працювало чудово
R4chi7

4

Моє брудне, але просте у реалізації та добре працює рішення:

Просто розмістіть веб-перегляд всередині прокрутки. Зробіть веб-перегляд занадто великим, ніж можливий вміст (в одному або обох вимірах, залежно від вимог). ..і налаштуйте смуги прокрутки прокрутки як завгодно.

Приклад вимкнення горизонтальної смуги прокрутки у веб-перегляді:

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="vertical"
>
    <WebView
        android:id="@+id/mywebview"
        android:layout_width="1000dip"
        android:layout_height="fill_parent"
    />
</ScrollView>

Сподіваюся, це допомагає;)


так, але тоді розмір прокрутки не буде занадто великим з великою кількістю пробілу внизу?
Рафаель Санчес,

1
Що робити, якщо ширина вмісту буде 1001dp?
Waltsu

3

Я вирішив мерехтіння та автоматичну прокрутку за допомогою:

webView.setFocusable(false);
webView.setFocusableInTouchMode(false);

Однак, якщо він все ще не працює з якихось причин, просто створіть клас, який розширює WebView, і покладіть на нього цей метод:

// disable scroll on touch
  setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
  });

Я пропоную розширити WebView, щоб забезпечити більш ефективний контроль, наприклад, відключити / увімкнути салфетки, увімкнути / вимкнути дотики, слухачі, керувати переходами, анімацією, визначити параметри внутрішньо, тощо.


3

Щоб вимкнути прокрутку, скористайтеся цим

webView.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) 
    {
        return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
});

2

Можливо, це не джерело вашої проблеми, але я годинами намагався відстежити, чому моя програма, яка чудово працювала на iphone, змушує браузер Android постійно викидати вертикальні / горизонтальні смуги прокрутки і фактично переміщати сторінку. У мене був HTML-тег body із висотою та шириною, встановленим на 100%, і тіло було повно різних тегів у різних місцях. Незалежно від того, що я намагався, браузери для Android показували свої смуги прокрутки і лише трохи переміщали сторінку, особливо коли робили швидке проведення. Рішення, яке працювало для мене без необхідності робити щось у файлі .apk, було додати наступне до тегу body:

leftmargin="0" topmargin="0"

Здається, поля за замовчуванням для тегу body застосовувались до дроїда, але ігнорувались на iphone


1

Якщо ви підклас Webview, ви можете просто перевизначити onTouchEvent, щоб відфільтрувати події переміщення, які викликають прокрутку.

public class SubWebView extends WebView {

    @Override
    public boolean onTouchEvent (MotionEvent ev)    {
        if(ev.getAction() == MotionEvent.ACTION_MOVE) {
            postInvalidate();
            return true;
        }
        return super.onTouchEvent(ev);
    }
    ...

0

вивчення вищезазначених відповідей майже спрацювало для мене ... але у мене все ще була проблема, що я міг "перекинути" погляд на 2.1 (здавалося, виправлено з 2.2 і 2.3).

ось моє остаточне рішення

public class MyWebView extends WebView
{
private boolean bAllowScroll = true;
@SuppressWarnings("unused") // it is used, just java is dumb
private long downtime;

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

public void setAllowScroll(int allowScroll)
{
    bAllowScroll = allowScroll!=0;
    if (!bAllowScroll)
        super.scrollTo(0,0);
    setHorizontalScrollBarEnabled(bAllowScroll);
    setVerticalScrollBarEnabled(bAllowScroll);
}

@Override
public boolean onTouchEvent(MotionEvent ev) 
{
    switch (ev.getAction())
    {
    case MotionEvent.ACTION_DOWN:
        if (!bAllowScroll)
            downtime = ev.getEventTime();
        break;
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP:
        if (!bAllowScroll)
        {
            try {
                Field fmNumSamples = ev.getClass().getDeclaredField("mNumSamples");
                fmNumSamples.setAccessible(true);
                Field fmTimeSamples = ev.getClass().getDeclaredField("mTimeSamples");
                fmTimeSamples.setAccessible(true);
                long newTimeSamples[] = new long[fmNumSamples.getInt(ev)];
                newTimeSamples[0] = ev.getEventTime()+250;
                fmTimeSamples.set(ev,newTimeSamples);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        break;
    }
    return super.onTouchEvent(ev);
}

@Override
public void flingScroll(int vx, int vy)
{
    if (bAllowScroll)
        super.flingScroll(vx,vy);
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt)
{
    if (bAllowScroll)
        super.onScrollChanged(l, t, oldl, oldt);
    else if (l!=0 || t!=0)
        super.scrollTo(0,0);
}

@Override
public void scrollTo(int x, int y)
{
    if (bAllowScroll)
        super.scrollTo(x,y);
}

@Override
public void scrollBy(int x, int y)
{
    if (bAllowScroll)
        super.scrollBy(x,y);
}
}

Перевизначення методу onScrollChanged () мені підходить. У моєму випадку я не можу перетягнути смужку прогресу відео та аудіо, вбудовану в WebView, використовуючи відповідь "Прийняти". Дуже дякую!
codezjx

-1

Це має бути повною відповіддю. Як запропонував @GDanger. Розширте WebView, щоб замінити методи прокрутки та вставити власний веб-перегляд у макет xml.

public class ScrollDisabledWebView extends WebView {

    private boolean scrollEnabled = false;

    public ScrollDisabledWebView(Context context) {
        super(context);
        initView(context);
    }

    public ScrollDisabledWebView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        initView(context);
    }
    // this is important. Otherwise it throws Binary Inflate Exception.
    private void initView(Context context) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
                                   int scrollRangeX, int scrollRangeY, int maxOverScrollX,
                                   int maxOverScrollY, boolean isTouchEvent) {
        if (scrollEnabled) {
            return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
                    scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
        }
        return false;
    }

    @Override
    public void scrollTo(int x, int y) {
        if (scrollEnabled) {
            super.scrollTo(x, y);
        }
    }

    @Override
    public void computeScroll() {
        if (scrollEnabled) {
            super.computeScroll();
        }
    }
}

А потім вбудуйте у файл макета наступним чином

<com.sample.apps.ScrollDisabledWebView
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    tools:context="com.sample.apps.HomeActivity"/>

Потім в Діяльність також використовуйте додаткові методи для вимкнення смуг прокрутки.

ScrollDisabledWebView webView = (ScrollDisabledWebView) findViewById(R.id.webView);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.