Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách ngăn chặn cuộn (scroll) trong WebView Android bằng lập trình

Giới thiệu

Bài viết này minh họa cách vô hiệu hóa cuộn (scroll) trong WebView bằng cách gán OnTouchListener và trả về true cho sự kiện ACTION_MOVE. Cách này "ăn" sự kiện chạm, ngăn WebView xử lý cuộn.

Các bước thực hiện

Bước 1: Tạo dự án mới

Mở Android Studio, chọn File → New Project và tạo dự án.

Bước 2: Thiết kế giao diện (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

Bước 3: Viết code logic (src/MainActivity.java)

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {
    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webView);
        webView.setWebViewClient(new WebViewClient());
        webView.loadUrl("https://www.youtube.com");

        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        // VÔ HIỆU HÓA CUỘN
        webView.setOnTouchListener((v, event) -> {
            // Trả về true cho ACTION_MOVE để "ăn" sự kiện cuộn
            return event.getAction() == MotionEvent.ACTION_MOVE;
        });
    }

    @Override
    public void onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }
}

Bước 4: Cấu hình quyền trong AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Chạy ứng dụng

Kết nối thiết bị, nhấn Run. WebView tải YouTube nhưng không thể cuộn trang bằng tay (cuộn bị chặn). Phím Back vẫn hoạt động để quay lại trang trước trong WebView.

Giải thích cơ chế

  • OnTouchListener được gọi trước khi WebView xử lý touch
  • Trả về true = đã xử lý, không truyền tiếp cho WebView
  • Chỉ chặn ACTION_MOVE (cuộn), vẫn cho phép ACTION_DOWN, ACTION_UP (click link, nút...)

Các cách khác kiểm soát cuộn WebView

1. Vô hiệu hóa hoàn toàn (kể cả click):

webView.setOnTouchListener((v, event) -> true);

2. Chỉ cho phép cuộn dọc/ngang (XML):

<WebView
    android:verticalScrollbarPosition="defaultPosition"
    android:overScrollMode="never" />

3. JavaScript injection (cho web nội bộ):

webView.loadUrl("javascript:document.body.style.overflow='hidden';");

4. Custom WebView override onTouchEvent:

public class NonScrollableWebView extends WebView {
    private boolean scrollEnabled = false;
    public void setScrollEnabled(boolean enabled) { scrollEnabled = enabled; }
    @Override public boolean onTouchEvent(MotionEvent ev) {
        return scrollEnabled ? super.onTouchEvent(ev) : (ev.getAction() == MotionEvent.ACTION_MOVE);
    }
}

Lưu ý

  • Cách này chỉ chặn cuộn bằng touch, không ảnh hưởng đến scrollTo(), scrollBy() bằng code
  • Có thể gây trải nghiệm UX kém nếu người dùng cần đọc nội dung dài
  • Nên cân nhắc dùng NestedScrollView bao ngoài WebView nếu muốn kiểm soát cuộn toàn trang