Tắt tính năng cuộn trong chế độ xem web?


86

Từ trước đến nay, tôi chỉ là nhà phát triển iPhone và bây giờ tôi đã quyết định sử dụng Android. Một điều mà tôi chưa thể tìm ra trên Android là làm thế nào để ngăn chặn việc cuộn trong một chương trình WebView?

Một cái gì đó tương tự như iPhone ngăn chặn onTouchMovesự kiện sẽ rất tuyệt!

Câu trả lời:


179

Đây là mã của tôi để tắt tất cả các thao tác cuộn trong webview:

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

Để chỉ ẩn các thanh cuộn, nhưng không tắt cuộn:

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

hoặc bạn có thể thử sử dụng bố cục cột đơn nhưng điều này chỉ hoạt động với các trang đơn giản và nó vô hiệu hóa tính năng cuộn ngang:

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

Bạn cũng có thể thử kết hợp chế độ xem web của mình với chế độ xem cuộn cuộn theo chiều dọc và tắt tất cả các thao tác cuộn trên chế độ xem web:

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

Và thiết lập

webview.setScrollContainer(false);

Đừng quên thêm webview.setOnTouchListener(...)mã ở trên để tắt tất cả các thao tác cuộn trong chế độ xem web. ScrollView dọc sẽ cho phép cuộn nội dung của WebView.


hoạt động tốt, nhưng sau vài giây gây ra lỗi trên Samsung i5700 spica trong /system/lib/libwebcore.so.
Lukas

LayoutAlgorithm.SINGLE_COLUMN hoặc webview.setOnTouchListener?
peceps

3
Nếu bạn đặt WebView trong ScrollView, hãy đặt thuộc tính android: isScrollContainer của WebView thành "false" thay vì đặt android: scrollbars thành "none". Điều này có tác dụng vô hiệu hóa hoàn toàn việc xử lý cuộn của webview và cho phép nó mở rộng theo nội dung của nó. Sau đó, Scroll sẽ chỉ được xử lý bởi ScrollView cha.
BladeCoder

1
Nếu bạn cần xử lý MotionEvent.ACTION_MOVEcác sự kiện trong của bạn, WebViewhãy xem câu trả lời của tôi bên dưới.
GDanger

1
Lờ đi ACTION_MOVEtrên setOnTouchListenersự kiện có một số tác dụng phụ vì vậy tôi sẽ không khuyên bạn câu trả lời này; 1. Các lần vuốt nhanh được tính là onclicksự kiện tới trang. 2. Ngăn việc cuộn tràn các phần tử trên trang, điều này có thể cần thiết để tương tác thích hợp tùy thuộc vào trang web. 3. Sự touchmovekiện JS . @GDanger có câu trả lời chính xác đang ghi đè overScrollBybằng cách mở rộng WebViewvì nó không có tác dụng phụ, chỉ ngăn việc cuộn trang. stackoverflow.com/a/26129301/1244574
jkasten

22

Tôi không biết nếu bạn vẫn cần nó hay không, nhưng đây là giải pháp:

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

18
đồng ý. điều này sẽ tắt các thanh cuộn, nhưng nó không ngăn cản việc cuộn bằng cách kéo. Dường như html phải phù hợp với quá ...
rdmueller

Nếu bạn đang thiết kế các trang web của mình chỉ cho chế độ xem web android thì tôi khuyên bạn nên tạo các trang web của mình trong bảng. Chiều rộng phải giống như width = "100%" và giống với chiều cao. vì vậy sẽ không có kéo nữa.
umar

width = 100% không phải lúc nào cũng hoạt động, ví dụ: stackoverflow.com/questions/6460871/…
NoBugs

tuyệt vời .. đó là những gì tôi cần. Cảm ơn bạn
Peter

21

Làm cho các WebViewsự kiện chuyển động bỏ qua là một cách sai lầm để thực hiện nó. Nếu WebViewnhu cầu nghe về những sự kiện này thì sao?

Thay vào đó phân lớp WebViewvà ghi đè các phương thức cuộn không riêng tư.

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

Nếu bạn nhìn vào các nguồn cho WebViewbạn có thể thấy rằng onTouchEventcác cuộc gọi doDragmà gọi overScrollBy .


1
Nếu bạn cần tắt / bật tính năng cuộn theo chương trình, hãy xem ý chính mà tôi đã tạo.
GDanger

1
Phương pháp của bạn phù hợp với tôi. Và tôi hoàn toàn đồng ý với bạn. Trong trường hợp của tôi, tôi không thể kéo thanh tiến trình video và âm thanh nhúng vào WebView bằng cách sử dụng câu trả lời chấp nhận.
codezjx

Đây là câu trả lời đúng. Mặc dù nó cần một số chỉnh sửa trên các hàm tạo ghi đè. Hãy xem câu trả lời đầy đủ của tôi dưới đây. stackoverflow.com/a/51936944/393502
Vansi

13

Thêm chi tiết lề vào phần nội dung sẽ ngăn không cho cuộn nếu nội dung của bạn kết thúc đúng cách, như vậy:

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

Đủ dễ dàng và ít chi phí mã + lỗi hơn rất nhiều :)


1
Xuất sắc! +1 cho một giải pháp chỉ HTML đơn giản. Đôi khi tôi muốn, bố trí trong android là dễ dàng như css ...
Pritesh Desai

Có vẻ tốt trong trình duyệt Android gốc, nhưng dường như không hoạt động trong Firefox (Fennec) ... mặc dù không có gì để cuộn theo chiều ngang, Firefox vẫn cho phép tôi cuộn sang bên phải đến điểm mà tất cả nội dung đã cuộn tắt màn hình.
Michael

1
Không hoạt động trên WebView hiện đại (Android 5 trở lên)
Roel

8

Đặt một trình nghe trên WebView của bạn:

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

3
Có thêm một dấu ngoặc đơn ở cuối returndòng ở đó. Ngoài ra, điều này phá vỡ các sự kiện chạm trên canvas HTML5 và JavaScript.
Rohan Singh

Điều này chắc chắn vô hiệu hóa nó, nhưng làm thế nào để tôi giết người nghe sau đó để kích hoạt lại đầu vào? Tôi cố gắng event.getAction() != MotionEvent.ACTION_MOVEcũng nhưreturn true
CQM

Trường hợp "không làm gì" tiêu chuẩn là return false, không return true.
Matthew Đọc

6

Tôi chưa thử vì tôi vẫn chưa gặp sự cố này, nhưng có lẽ bạn có thể ghi đè chức năng onScroll?

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

Đây là những gì chúng ta gọi là ở Ấn Độ một Jugaad ... mặc dù chỉ làm việc tốt
R4chi7

4

Giải pháp bẩn, nhưng dễ thực hiện và hoạt động tốt của tôi:

Chỉ cần đặt chế độ xem web bên trong chế độ xem cuộn. Đặt chế độ xem web quá lớn so với nội dung có thể (theo một hoặc cả hai chiều, tùy thuộc vào yêu cầu). ..và thiết lập (các) thanh cuộn của chế độ xem như bạn muốn.

Ví dụ để tắt thanh cuộn ngang trên chế độ xem web:

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

Tôi hi vọng cái này giúp được ;)


vâng, nhưng sau đó kích thước cuộn sẽ không quá lớn với nhiều khoảng trắng ở dưới cùng?
Rafael Sanches

1
Điều gì sẽ xảy ra nếu chiều rộng nội dung sẽ là 1001dp?
Waltsu

3

Tôi đã giải quyết hiện tượng nhấp nháy và tự động cuộn bằng cách:

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

Tuy nhiên, nếu nó vẫn không hoạt động vì lý do nào đó, chỉ cần tạo một lớp mở rộng WebView và đặt phương thức này vào nó:

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

Tôi đang đề xuất mở rộng WebView, để cung cấp khả năng kiểm soát hiệu quả hơn, như tắt / bật vuốt, bật / tắt chạm, trình nghe, điều khiển chuyển tiếp, hoạt ảnh, xác định cài đặt nội bộ, v.v.


3

Để tắt cuộn, hãy sử dụng cái này

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

2

Đây có thể không phải là nguồn gốc của vấn đề của bạn nhưng tôi đã dành hàng giờ để cố gắng tìm ra lý do tại sao ứng dụng của tôi hoạt động tốt trên iPhone khiến trình duyệt Android liên tục ném thanh cuộn dọc / ngang và thực sự di chuyển trang. Tôi có một thẻ nội dung html với chiều cao và chiều rộng được đặt thành 100% và phần nội dung có đầy đủ các thẻ khác nhau ở các vị trí khác nhau. Bất kể tôi đã thử gì, các trình duyệt Android sẽ hiển thị thanh cuộn của chúng và di chuyển trang chỉ một chút, đặc biệt là khi thực hiện thao tác vuốt nhanh. Giải pháp phù hợp với tôi mà không cần phải thực hiện bất kỳ điều gì trong APK là thêm phần sau vào thẻ body:

leftmargin="0" topmargin="0"

Có vẻ như các lề mặc định cho thẻ body đã được áp dụng trên droid nhưng bị bỏ qua trên iPhone


1

Nếu bạn phân lớp Webview, bạn có thể chỉ cần ghi đè onTouchEvent để lọc ra các sự kiện di chuyển kích hoạt cuộn.

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

nghiên cứu các câu trả lời ở trên hầu như đã làm việc cho tôi ... nhưng tôi vẫn gặp vấn đề là tôi có thể 'chuyển' chế độ xem trên 2.1 (dường như được sửa với 2.2 & 2.3).

đây là giải pháp cuối cùng của tôi

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

Để ghi đè phương thức onScrollChanged () phù hợp với tôi. Trong trường hợp của tôi, tôi không thể kéo thanh tiến trình video và âm thanh nhúng vào WebView bằng cách sử dụng câu trả lời chấp nhận. Cảm ơn rất nhiều!
codezjx

-1

Đây sẽ là câu trả lời đầy đủ. Theo gợi ý của @GDanger. Mở rộng WebView để ghi đè các phương pháp cuộn và nhúng chế độ xem web tùy chỉnh trong xml bố cục.

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

Và sau đó nhúng vào tệp bố cục như sau

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

Sau đó, trong Hoạt động, sử dụng một số phương pháp bổ sung để tắt thanh cuộn.

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

-3

Chỉ cần sử dụng android:focusableInTouchMode="false"trên webView của bạn .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.