Android-用WebView开发简单的浏览器

Android 提供了 WebView 组件,WebView 本身就是一个浏览器实现。

例子中主要用到了 WebView 的以下方法:

  • void loadUrl(String url) 加载指定 url 对应的网页
  • void goBack() 后退
  • void goForward() 前进
  • boolean canGoBack() 根据历史记录判断是否可以回退
  • boolean canGoForward() 根据历史记录判断是否可以前进
  • WebSettings getSettings() 获得对 WebView 进行控制的 WebSettings 对象
    (调用其setJavaScriptEnabled方法使WebView支持JavaScript
  • void setWebViewClient(WebViewClient client) WebViewClient 负责处理
    WebView 各种通知,请求,比如页面开始加载及加载完成、资源加载中、url已打开等
  • void setWebChromeClient(WebChromeClient client) WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度

浏览器功能概述:

  1. 第一次打开应用时默认会把百度设置为首页,可通过底部主页按钮跳转到主页,或通过长按弹出对话框修改主页
  2. 主页的 URL 地址使用SharedPreference保存
  3. 底部四个ImageButton从做往右依次为主页 刷新 回退 前进
  4. 顶部的ActionBarvoid setCustomView(View)添加了一个自定义的用于输入网址的输入框和一个转到按钮,转到按钮默认是不可见且不可用的,当点击了用于输入网址EditText就会显示并可用。
  5. 用于显示网页加载进度的ProgressBar

截图

这里写图片描述

代码部分

  • 每次打开一个网页时会调用该方法,在这里控制ActionBar内的Edittext显示加载中...
 mWebView.setWebViewClient(new WebViewClient() {            @Override            public void onPageStarted(WebView view, String url, Bitmap favicon) {                super.onPageStarted(view, url, favicon);                mShowTitle.setText("加载中...");            }            ...}
  • 覆写shouldOverrideUrlLoading并返回true,否则 WebView 默认会调用系统的浏览器或第三方浏览器,而不使用当前activity中的WebView
mWebView.setWebViewClient(new WebViewClient() {            ...            @Override            public boolean shouldOverrideUrlLoading(WebView view, String url) {                view.loadUrl(url);                return true;            }            ...}
  • 当网页加载进度改变时会回调onProgressChanged方法,在这里更新用于显示进度的ProgressBar。注意newProgress值为 0 到 100 ,因而将ProgressBar最大值设为 100 。
  • onReceivedTitle返回当前加载网页的标题将标题显示在 actionBar 内的 EditText 上。
mWebView.setWebChromeClient(new WebChromeClient() {            @Override            public void onProgressChanged(WebView view, int newProgress) {                mProgressBar.setProgress(newProgress);                if (newProgress == 100) {                    mProgressBar.postDelayed(() -> mProgressBar.setProgress(0), 2000);                }        }            @Override            public void onReceivedTitle(WebView view, String title) {                super.onReceivedTitle(view, title);                currentUrlTitle = title;                mShowTitle.setText(currentUrlTitle);            }        });
  • 监听物理按键返回的点击事件,如果WebView历史记录里有上一页相关记录就调用void goBack()方法
@Override    public void onBackPressed() {        if (mWebView.canGoBack())            mWebView.goBack();        else finish();    }
  • 判断当前是否处于正在输入网址(actionBar上的 EditText)的状态
    1 是的话调用此方法表示输入结束从使转到按钮消失并不可用
    2 使EditText控件失去焦点,不然会一直显示光标,效果不好
private void finishEdit() {        if (isEditFocus) {            isEditFocus = false;            mShowTitle.clearFocus();            Animation animation = AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_out);            animation.setFillAfter(true);            mLoadUrl.startAnimation(animation);            mLoadUrl.setEnabled(false);            mShowTitle.setText(currentUrlTitle);        }    }

这个方法有三个地方调用到:
1 当正在输入网址时用户转移注意力到WebView上,并触摸到WebView,此时会先判断软键盘是否正在显示,正在显示就关闭软键盘然后使输入框失去焦点并隐藏转到按钮

 mWebView.setOnTouchListener((View view, MotionEvent event) -> {       if (event.getAction() == MotionEvent.ACTION_DOWN) {           finishEdit();           InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);           if (imm.isActive())               imm.hideSoftInputFromWindow(mShowTitle.getWindowToken(),0);       }       return false;   });

2 当正在输入网址时点击了物理按键返回,此时void onBackPressed()方法是不会被调用的,因为此时软键盘正在显示,调用boolean dispatchKeyEvent(KeyEvent event)方法拦截返回按键的点击事件,关闭软键盘的同时使输入框失去焦点并隐藏转到按钮。

@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)            finishEdit();        return super.dispatchKeyEvent(event);    }

3 点击了 actionBar 处的转到按钮
3.1 此时要先判断是否正确输入,然后判断输入网址是否是新的(和当前正在显示的网页的网址不同),满足就让WebView加载该网页
3.2 判断软键盘是否正在显示,正在显示就关闭软键盘然后使输入框失去焦点并隐藏转到按钮

以下代码包含所有按钮的点击事件,每个按钮都在xml中添加了
android:onClick="onClick"属性

 public void onClick(View view) {        switch (view.getId()) {            case R.id.main_goBack:                if (mWebView.canGoBack())                    mWebView.goBack();                break;            case R.id.main_goForward:                if (mWebView.canGoForward())                    mWebView.goForward();                break;            case R.id.main_refresh:                mWebView.loadUrl(currentUrl);                break;            case R.id.actionBar_goto:                String url = mShowTitle.getText().toString() == "" ? null : mShowTitle.getText().toString().equals(currentUrl) ? null : mShowTitle.getText().toString();                if (url != null)                    mWebView.loadUrl(url);                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);                if (imm.isActive())                    imm.hideSoftInputFromWindow(mShowTitle.getWindowToken(),0);                finishEdit();                break;            case R.id.main_home:                if (!currentUrl.equals(homeUrl))                    mWebView.loadUrl(homeUrl);                break;        }    }

值得注意的地方:

  • 在style中使用colorControlHighlight属性改变默认的按钮点击波纹效果的颜色
    比如这样:
@color/colorPrimary
  • 在按钮的xml属性中通过设置
style=`"@style/Base.Widget.AppCompat.Button.Borderless.Colored"

使按钮的点击效果不受布局边界限制。其他默认不可点击的view(如EditText,TextView等)还要在添加一个:

android:clickable="true"
  • 使用到的图标在这里下载的:Material icons - Material Design
  • 调用ActionBarsetCustomView方法前先要调用setDisplayShowCustomEnabled方法并置为true。
  • 修改主页用到了对话框:
 AlertDialog.Builder builder     .setTitle("修改主页")     .setNegativeButton("取消", (DialogInterface dialog, int which) -> dialog.dismiss())

这里本来是用new DialogInterface.OnClickListener() {...}的形式写的,后来改成使用Lambda的方式,这时要在app的build.gradle里加上:

android {    ...        jackOptions {            enabled true        }        ...    }    ...    compileOptions {        targetCompatibility 1.8        sourceCompatibility 1.8    }    ...}

更多相关文章

  1. android wifi之WifiMonitor
  2. android调用手机摄像头拍照
  3. 自定义ThreadPoolExecutor
  4. Android(安卓)高德地图,显示地图,并定位当前的位置
  5. Android(安卓)webView 中loadData方法加载 带中文时出现乱码
  6. 微信青蛙刷脸支付——Android
  7. Android中调用系统所装的软件打开文件
  8. 如何定制PopupWindow弹出框及方法介绍
  9. Android中调用外部程序的方法[整理]

随机推荐

  1. 使用python将图片转换为字符图片
  2. 如何按期执行python脚本?
  3. python 3.3 爬虫之爬取图片
  4. python处理数据,存进hive表
  5. Python笔记-几种取整方式
  6. python 中 字符串转换为数组,字典或表达式
  7. 详解Python中的from..import绝对导入语句
  8. python入门之常见列表、字典知识
  9. 如何使用pip安装Python MySQLdb模块?
  10. 检测Python程序的执行效率