自定义可下拉刷新的WebView

本文介绍如何解决自定义可下拉刷新WebView时遇到的问题,主要难点在于监听WebView是否滚动到顶部。通过创建继承自WebView的类并重写onScrollChanged()方法,配合回调接口的定义,确保只有在WebView顶部时才能执行下拉刷新,防止在WebView非顶部位置误触发刷新,从而修复了用户无法回滑到顶部的bug。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义可下拉刷新的WebView的主要难点在于:监听WebView是否滚动到顶部,因为我是使用google提供的SwipeRefreshLayout实现,所以当webview不处于顶部时,下拉依然刷新,导致一旦将webview上滑之后无法回滑到顶部(被SwipeRefreshLayout获取并刷新)。下面是具体实现逻辑。

1,新建一个类继承自WebView,重写onScrollChanged()方法

public class ListenableWebView extends WebView {

    private IWebViewScroll mIWebViewScroll;

    public ListenableWebView(Context context) {
        this(context, null);
    }

    public ListenableWebView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ListenableWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mIWebViewScroll != null && t == 0) {
            mIWebViewScroll.onTop();
        } else if (mIWebViewScroll != null && t != 0) {
            mIWebViewScroll.notOnTop();
        }
    }


    /**
     * 设置滑动监听
     *
     * @param listener
     */
    public void setOnCustomScrollChanged(IWebViewScroll listener) {
        this.mIWebViewScroll = listener;
    }
}

2,下面是回调接口的定义

public interface IWebViewScroll {
    void onTop();//处于顶部回调
    void notOnTop();//
}

3,使用

public class XWebView extends FrameLayout implements SwipeRefreshLayout.OnRefreshListener {

    private ListenableWebView mWebView;//webview组件
    private SwipeRefreshLayout mSwipeRefreshLayout;//下拉刷新布局
    private String mUrl;//用户加载的链接
    private String mHtmlSource;//用户加载的html源码


    public XWebView(Context context) {
        this(context, null);
    }

    public XWebView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public XWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    //******************************************

    /**
     * 加载html代码
     *
     * @param htmlData
     */
    public void loadHtmlSource(String htmlData) {
        this.mHtmlSource = htmlData;
        mWebView.getSettings().setDefaultTextEncodingName("UTF-8");//设置默认为utf-8
        mWebView.loadData(htmlData, "text/html; charset=UTF-8", null);
    }

    /**
     * 加载某个链接
     *
     * @param url
     */
    public void loadUrl(String url) {
        this.mUrl = url;
        mWebView.loadUrl(url);
    }

    /**
     * 释放webview
     */
    public void release() {
        mWebView.clearCache(true);
        mWebView.clearHistory();
        this.mWebView.destroy();
    }

    //******************************************
    private void init() {
        LayoutInflater.from(getContext()).inflate(R.layout.x_webview, this);
        mWebView = (ListenableWebView) this.findViewById(R.id.id_webview);
        mSwipeRefreshLayout = (SwipeRefreshLayout) this.findViewById(R.id.id_swipe_refresh_layout);
        initSwipeRefreshLayout();
        initWebView();

    }


    /**
     * webview的设置
     */
    private void initWebView() {
        //对webview是否处于顶部进行监听,解决webview往下拉后无法往上拉的冲突(和SwipeRefreshLayout冲突)
        mWebView.setOnCustomScrollChanged(new IWebViewScroll() {
            @Override
            public void onTop() {
                mSwipeRefreshLayout.setEnabled(true);
            }

            @Override
            public void notOnTop() {
                mSwipeRefreshLayout.setEnabled(false);
            }
        });
        mWebView.setVerticalScrollBarEnabled(false);//设置无垂直方向的scrollbar
        mWebView.setHorizontalScrollBarEnabled(false);//设置无水平方向的scrollbar
        WebSettings settings = mWebView.getSettings();
        settings.setSupportZoom(false); // 支持缩放
        settings.setBuiltInZoomControls(false); // 启用内置缩放装置
        settings.setJavaScriptEnabled(true); // 启用JS脚本
        // 设置WebView可触摸放大缩小
        settings.setBuiltInZoomControls(false);
        mWebView.setWebViewClient(new WebViewClient() {
            // 当点击链接时,希望覆盖而不是打开浏览器窗口
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }

            @Override
            public void onReceivedError(WebView view, int errorCode, String description,
                                        String failingUrl) {
                Logger.e("onReceivedError");
                //用javascript隐藏系统定义的404页面信息
                mWebView.loadUrl("file:///android_asset/error.html");
                mSwipeRefreshLayout.setRefreshing(false);
                // mContainerFailView.setVisibility(View.VISIBLE);
               // mWebView.setVisibility(View.GONE);
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                mSwipeRefreshLayout.setRefreshing(true);
                Logger.e("onPageStarted");
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                mSwipeRefreshLayout.setRefreshing(false);
                Logger.e("onPageFinished");
            }
        });
        // 点击后退按钮,让WebView后退
        mWebView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
                        mWebView.goBack();
                        return true;
                    }
                }
                return false;
            }
        });
    }

    /**
     * 设置下拉刷新样式及监听
     */
    private void initSwipeRefreshLayout() {
        mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright, android.R.color.holo_green_light,
                android.R.color.holo_orange_light, android.R.color.holo_red_light);
        mSwipeRefreshLayout.setOnRefreshListener(this);
    }


    /**
     * 下拉刷新的监听
     */
    @Override
    public void onRefresh() {
        if (NetworkUtil.isNetworkConnected(getContext())) {//有网络才允许重新刷新
           mWebView.reload();
        } else {
            mSwipeRefreshLayout.setRefreshing(false);//无网络
            Toaster.showShort(getContext(), TipMsg.HTTP_NO_CONNECTION);
        }
    }


}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值