Scrollen in der Webansicht deaktivieren?

86

Bis jetzt war ich nur ein iPhone-Entwickler und jetzt habe ich beschlossen, Android einen Wirbel zu geben. Etwas, das ich auf Android nicht herausfinden konnte, ist, wie man programmgesteuert das Scrollen in einem verhindert WebView.

Etwas Ähnliches wie die iPhone-Prävention der onTouchMoveVeranstaltung wäre großartig!

Jake Sankey
quelle

Antworten:

179

Hier ist mein Code zum Deaktivieren des gesamten Bildlaufs in der Webansicht:

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

So blenden Sie nur die Bildlaufleisten aus, deaktivieren jedoch nicht das Scrollen:

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

Sie können auch versuchen, ein einspaltiges Layout zu verwenden. Dies funktioniert jedoch nur bei einfachen Seiten und deaktiviert das horizontale Scrollen:

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

Sie können auch versuchen, Ihre Webansicht mit einer vertikal scrollenden Bildlaufansicht zu verpacken und alle Bildlaufvorgänge in der Webansicht zu deaktivieren:

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

Und setzen

webview.setScrollContainer(false);

Vergessen Sie nicht, den webview.setOnTouchListener(...)obigen Code hinzuzufügen , um das Scrollen in der Webansicht zu deaktivieren. Die vertikale ScrollView ermöglicht das Scrollen des WebView-Inhalts.

Peceps
quelle
funktioniert gut, verursacht aber nach wenigen Sekunden einen Absturz auf dem Samsung i5700 spica in /system/lib/libwebcore.so.
Lukas
LayoutAlgorithm.SINGLE_COLUMN oder webview.setOnTouchListener?
Peceps
3
Wenn Sie eine WebView in eine ScrollView einfügen, setzen Sie das Attribut android: isScrollContainer der WebView auf "false", anstatt android: scrollbars auf "none" zu setzen. Dies hat zur Folge, dass die Bildlaufbehandlung der Webansicht vollständig deaktiviert und entsprechend ihrem Inhalt erweitert werden kann. Das Scrollen wird dann ausschließlich von der übergeordneten ScrollView ausgeführt.
BladeCoder
1
Wenn Sie MotionEvent.ACTION_MOVEEreignisse in Ihrem behandeln müssen, WebViewsiehe meine Antwort unten.
GDanger
1
Das Ignorieren der ACTION_MOVEauf der setOnTouchListenerVeranstaltung einige Nebenwirkungen hat , so würde ich diese Antwort nicht empfehlen; 1. Schnelle Wischvorgänge werden als onclickEreignisse auf der Seite gezählt. 2. Verhindert das Überlaufen von Elementen auf der Seite. Dies kann je nach Site für eine ordnungsgemäße Interaktion erforderlich sein. 3. Das JS- touchmoveEreignis. @GDanger hat die richtige Antwort, die das überschreibt, overScrollByindem es das erweitert, WebViewda es keine anderen Effekte hat, sondern nur das Scrollen von Seiten verhindert. stackoverflow.com/a/26129301/1244574
jkasten
22

Ich weiß nicht, ob Sie es noch brauchen oder nicht, aber hier ist die Lösung:

appView = (WebView) findViewById(R.id.appView); 
appView.setVerticalScrollBarEnabled(false);
appView.setHorizontalScrollBarEnabled(false);
umar
quelle
18
OK. Dadurch werden die Bildlaufleisten deaktiviert, das Scrollen durch Ziehen wird jedoch nicht verhindert. Es scheint, dass das HTML auch passen muss ...
Rdmüller
Wenn Sie Ihre Webseiten nur für die Android-Webansicht entwerfen, empfehle ich, Ihre Webseiten in einer Tabelle zu erstellen. Die Breite sollte wie width = "100%" sein und für die Höhe gleich sein. Es wird also kein Ziehen mehr geben.
Umar
width = 100% funktioniert nicht immer, zum Beispiel: stackoverflow.com/questions/6460871/…
NoBugs
Super ... es ist was ich brauche. Vielen Dank
Peter
21

Das WebViewIgnorieren von Bewegungsereignissen ist der falsche Weg. Was ist, wenn Sie WebViewvon diesen Ereignissen erfahren müssen?

Unterklassen WebViewund überschreiben Sie stattdessen die nicht privaten Bildlaufmethoden.

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

Wenn man sich die aussehen Quelle für WebViewkönnen Sie sehen , dass onTouchEventAnrufe , doDragdie Anrufe overScrollBy .

GDanger
quelle
1
Wenn Sie das Scrollen programmgesteuert deaktivieren / aktivieren müssen, sehen Sie sich diese von mir erstellte Übersicht an .
GDanger
1
Ihre Methode funktioniert bei mir. Und ich stimme dir ganz zu. In meinem Fall kann ich den in WebView eingebetteten Video- und Audio-Fortschrittsbalken nicht mithilfe der Antwort "Akzeptieren" ziehen.
Codezjx
Das ist die richtige Antwort. Es sind jedoch einige Verbesserungen an übergeordneten Konstruktoren erforderlich. Bitte schauen Sie sich meine vollständige Antwort unten an. stackoverflow.com/a/51936944/393502
Vansi
13

Durch Hinzufügen der Randdetails zum Textkörper wird das Scrollen verhindert, wenn Ihr Inhalt ordnungsgemäß umbrochen wird.

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

Einfach genug und viel weniger Code + Bug Overhead :)

Auri Rahimzadeh
quelle
1
Brillant! +1 für eine einfache Nur-HTML-Lösung. Manchmal wünschte ich, Layout in Android wäre so einfach wie CSS ...
Pritesh Desai
Sieht im Standard-Android-Browser gut aus, scheint aber in Firefox (Fennec) nicht zu funktionieren. Obwohl es nichts gibt, zu dem horizontal gescrollt werden kann, kann ich mit Firefox immer noch nach rechts scrollen, bis der gesamte Inhalt gescrollt ist vom Bildschirm.
Michael
1
Funktioniert nicht mit modernem WebView (Android 5 und höher)
Roel
8

Legen Sie einen Listener in Ihrem WebView fest:

webView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return(event.getAction() == MotionEvent.ACTION_MOVE));
            }
        });
user322987
quelle
3
Es gibt dort eine zusätzliche Klammer am Ende der returnZeile. Auch dies bricht HTML5-Canvas- und JavaScript-Touch-Ereignisse.
Rohan Singh
Dies deaktiviert es sicherlich, aber wie kann ich den Listener später töten, um Eingaben zu erneuern? Ich habe es event.getAction() != MotionEvent.ACTION_MOVEgenauso gut versucht wiereturn true
CQM
Der Standardfall "nichts tun" ist return falsenicht return true.
Matthew Read
6

Ich habe dies noch nicht versucht, da ich noch nicht auf dieses Problem gestoßen bin, aber vielleicht könnten Sie die onScroll-Funktion überschreiben?

@Override
public void scrollTo(int x, int y){
super.scrollTo(0,y);
}
ZeroTruths
quelle
Dies ist, was wir in Indien einen Jugaad nennen ... obwohl es gut funktioniert hat
R4chi7
4

Meine schmutzige, aber einfach zu implementierende und gut funktionierende Lösung:

Fügen Sie einfach die Webansicht in eine Bildlaufansicht ein. Stellen Sie die Webansicht so ein, dass sie viel zu groß als der mögliche Inhalt ist (in einer oder beiden Dimensionen, abhängig von den Anforderungen). ..und richten Sie die Bildlaufleiste (n) der Bildlaufansicht nach Ihren Wünschen ein.

Beispiel zum Deaktivieren der horizontalen Bildlaufleiste in einer Webansicht:

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

Ich hoffe das hilft ;)

user289463
quelle
Ja, aber dann wäre die Bildlaufgröße nicht zu groß mit viel Leerraum unten?
Rafael Sanches
1
Was ist, wenn die Inhaltsbreite 1001 dp beträgt?
Waltsu
3

Ich habe das Flimmern behoben und automatisch gescrollt durch:

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

Wenn es jedoch aus irgendeinem Grund immer noch nicht funktioniert, erstellen Sie einfach eine Klasse, die WebView erweitert, und fügen Sie diese Methode hinzu:

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

Ich schlage vor, WebView zu erweitern, um eine effektivere Steuerung wie Deaktivieren / Aktivieren von Wischen, Aktivieren / Deaktivieren von Berührungen, Listener, Steuerungsübergänge, Animationen, internes Definieren von Einstellungen usw. bereitzustellen.

Abhinav Saxena
quelle
3

Verwenden Sie diese Option, um den Bildlauf zu deaktivieren

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

Dies ist möglicherweise nicht die Ursache Ihres Problems, aber ich habe stundenlang versucht herauszufinden, warum meine Anwendung, die auf dem iPhone einwandfrei funktioniert hat, dazu führt, dass der Android-Browser ständig die vertikalen / horizontalen Bildlaufleisten hochwirft und die Seite tatsächlich verschiebt. Ich hatte ein HTML-Body-Tag mit einer Höhe und Breite von 100% und der Body war voller verschiedener Tags an verschiedenen Orten. Egal was ich versuchte, die Android-Browser zeigten ihre Bildlaufleisten an und bewegten die Seite nur ein wenig, besonders wenn sie schnell wischten. Die Lösung, die für mich funktionierte, ohne etwas in einer APK tun zu müssen, bestand darin, dem Body-Tag Folgendes hinzuzufügen:

leftmargin="0" topmargin="0"

Es scheint, dass die Standardränder für Body-Tags auf den Droiden angewendet, auf dem iPhone jedoch ignoriert wurden

Robert Etheredge
quelle
1

Wenn Sie Webview unterklassifizieren , können Sie onTouchEvent einfach überschreiben, um die Verschiebungsereignisse herauszufiltern, die das Scrollen auslösen.

public class SubWebView extends WebView {

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

Das Studieren der obigen Antworten hat fast für mich funktioniert ... aber ich hatte immer noch ein Problem, dass ich die Ansicht zu 2.1 'schleudern' konnte (schien mit 2.2 & 2.3 behoben zu sein).

Hier ist meine endgültige Lösung

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);
}
}
SteelBytes
quelle
Das Überschreiben der onScrollChanged () -Methode funktioniert bei mir. In meinem Fall kann ich den in WebView eingebetteten Video- und Audio-Fortschrittsbalken nicht mithilfe der Antwort "Akzeptieren" ziehen. Vielen Dank!
Codezjx
-1

Dies sollte die vollständige Antwort sein. Wie von @GDanger vorgeschlagen. Erweitern Sie WebView, um die Bildlaufmethoden zu überschreiben und die benutzerdefinierte Webansicht in Layout-XML einzubetten.

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

Und dann wie folgt in die Layoutdatei einbetten

<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"/>

Verwenden Sie dann in der Aktivität einige zusätzliche Methoden zum Deaktivieren von Bildlaufleisten.

ScrollDisabledWebView webView = (ScrollDisabledWebView) findViewById(R.id.webView);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);
Vansi
quelle
-2

Verwenden android:focusableInTouchMode="false"Sie es einfach in Ihrem WebView .

Socratex
quelle