『Android基础入门』视图绑定与网络编程WebView

696 阅读5分钟


我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿

👨‍🎓作者简介:一位喜欢写作,计科专业的大二菜鸟

🏡个人主页:starry陆离

🕒首发日期:2022年7月11日星期一

🌌上期文章:『Android基础入门』网络编程之OKHTTP与Retrofit框架

📚订阅专栏:『Android基础入门』 如果文章有帮到你的话记得点赞👍+收藏💗支持一下哦


1. 视图绑定

视图绑定 | Android 开发者 | Android Developers (google.cn)

通过视图绑定viewBinding功能,您可以更轻松地编写可与视图交互的代码。在模块中启用视图绑定之后,系统会为该模块中的每个 XML 布局文件生成一个绑定类。绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。

1.1 打开 viewBinding

     //默认是关闭的,手动打开
     viewBinding{
         enabled=true
     }

image-20220513142622276

1.2 viewBinding的使用

自动将xml文件生成java类 类的名字以xml的名字+Binding

也正是如此让我们不需要再使用findViewById()来获取控件,直接类名.组件ID就可以获取到控件的引用

  //改造activity
 activityMainBinding=ActivityMainBinding.inflate(getLayoutInflater());
 setContentView(activityMainBinding.getRoot());
 ​
 //优势一:无需findViewById,简化控件获取
 //优势二:避免报空指针,控件管理更方便,有条理
 activityMainBinding.txtViewId.setText("HNUCM");

image-20220513142829993

2. WebView

在 WebView 中编译 Web 应用 | Android 开发者 | Android Developers (google.cn)

如果希望在客户端应用中提供 Web 应用(或只是网页),则可以使用 WebView 执行该操作。WebView 类是 Android 的 View 类的扩展,可将网页显示为 Activity 布局的一部分。它不会包含功能全面的网络浏览器的任何功能,例如导航控件或地址栏。WebView 默认只显示网页。

android里可以嵌套网页,如微信公众号,小程序

2.1 app嵌入网页

在xml文件中添加一个webView控件

image-20220514100509268

要在 WebView 中加载网页,使用 loadUrl()方法:

 activityMainBinding.webViewId.loadUrl("http://www.qq.com");
 ​
 activityMainBinding.webViewId.loadUrl("http://www.qq.com");
 ​
 activityMainBinding.webViewId.setWebViewClient(new WebViewClient(){
     @Override
     public boolean shouldOverrideUrlLoading(WebView view, String url) {
         view.loadUrl(url);
         return true;
     }
 });

这样我们可以看到,成功将网页嵌入到了app中,不过网页仍然是以网页端显示

image-20220513144419007

2.2 设置显示样式

通过如下设置可以使样式和手机端样式显示

image-20220513145243760

 WebSettings webSettings = activityMainBinding.webViewId.getSettings();
 //如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
 webSettings.setJavaScriptEnabled(true);
 ​
 //设置自适应屏幕,两者合用
 webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
 webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
 //自适应屏幕
 activityMainBinding.webViewId.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
 webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
 ​
 //缩放操作
 webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
 webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
 webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
 ​
 //其他细节操作
 webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
 webSettings.setAllowFileAccess(true); //设置可以访问文件
 webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
 webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
 webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
 ​
 //优先使用缓存
 webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
 //缓存模式如下:
 //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
 //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
 //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
 //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
 //不使用缓存
 webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
 ​

2.3 嵌入自定义(本地)网页

创建一个assets文件夹

Tips:Assets 目录是 Android 的一种特殊目录,用于放置 APP 所需的固定文件,且该文件被打包到 APK 中时,不会被编码到二进制文件

image-20220513145608614

将自己写好的student.html(这是我web课的一个小作业)网页脚本,复制到assets文件夹下

需要修改一下文件的路径:

 activityMainBinding.webViewId.loadUrl("file:///android_asset/student.html");

image-20220513150142453

运行同样可以显示

image-20220513151557033

可以看到在html(web)中的语法都能在android中生效,跳转同样的可以通过<a></a>标签实现

除此之外webView提供了跳转的方法

先在xml创建两个按钮来监听点击事件

image-20220513152141224

webView提供goBack()goForward()方法监听网页间的跳转

 activityMainBinding.button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
          activityMainBinding.webViewId.goBack();
      }
  });
 ​
 activityMainBinding.button2.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View view) {
         activityMainBinding.webViewId.goForward();
     }
 });

image-20220513152424521

可以看到无论是用<a></a>标签还是,Android原生的按钮监听都能实现网页的跳转

android10.1

3. 思索&下期预告

理想情况下,Android中的所有UI全部都可以通过webView使用网页来实现,但为什么web没有取代Android开发?那是不是前端的工程师都可以兼职开发Android,干嘛还要发展Android呢?

4.完整代码

MainActivity代码

 public class MainActivity extends AppCompatActivity {
 ​
     //viewBinding
     //自动将xml文件生成java类  类的名字以xml的名字+Binding
     ActivityMainBinding activityMainBinding;
 ​
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 ​
         //改造activity
         activityMainBinding=ActivityMainBinding.inflate(getLayoutInflater());
         setContentView(activityMainBinding.getRoot());
 ​
         //优势一:无需findViewById,简化控件获取
         //优势二:避免报空指针,控件管理更方便,有条理
         //activityMainBinding.txtViewId.setText("HNUCM");
 ​
 ​
         //问题一:并不是嵌入在app中
         activityMainBinding.webViewId.loadUrl("file:///android_asset/student.html");
 ​
         activityMainBinding.webViewId.setWebViewClient(new WebViewClient(){
             @Override
             public boolean shouldOverrideUrlLoading(WebView view, String url) {
                 view.loadUrl(url);
                 return true;
             }
         });
 ​
 ​
         WebSettings webSettings = activityMainBinding.webViewId.getSettings();
         //如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
         webSettings.setJavaScriptEnabled(true);
 ​
         //设置自适应屏幕,两者合用
         webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
         webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
         //自适应屏幕
         activityMainBinding.webViewId.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
         webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
 ​
         //缩放操作
         webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
         webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
         webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
 ​
         //其他细节操作
         webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
         webSettings.setAllowFileAccess(true); //设置可以访问文件
         webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
         webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
         webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
 ​
         //优先使用缓存
         webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
         //缓存模式如下:
         //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
         //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
         //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
         //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
         //不使用缓存
         webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
 ​
         activityMainBinding.button.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 activityMainBinding.webViewId.goBack();
             }
         });
 ​
         activityMainBinding.button2.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 activityMainBinding.webViewId.goForward();
             }
         });
 ​
     }
 }

activity_main.xml代码

 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".MainActivity">
 ​
 ​
     <WebView
         android:id="@+id/webViewId"
         android:layout_width="match_parent"
         android:layout_height="500dp"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent" />
 ​
     <Button
         android:id="@+id/button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="60dp"
         android:text="返回"
         app:layout_constraintEnd_toStartOf="@+id/button2"
         app:layout_constraintHorizontal_bias="0.5"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/webViewId" />
 ​
     <Button
         android:id="@+id/button2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="前进"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintHorizontal_bias="0.5"
         app:layout_constraintStart_toEndOf="@+id/button"
         app:layout_constraintTop_toTopOf="@+id/button" />
 ​
 </androidx.constraintlayout.widget.ConstraintLayout>

student.html代码

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>Document</title>
     <style>
         th{
             border: 1px solid black;
             background-color: antiquewhite;
             padding: 5px;
         }
         td{
             border: 1px solid black;
             font-family: 'Courier New', Courier, monospace;
             padding: 4px;
         }
         table{
             border-collapse: collapse;
             width: 90%;
             margin: auto;
         }
         div{
             border: 1px solid black;
             width: 60%;
             margin: auto;
         }
 ​
     </style>
 ​
 </head>
 <body style="text-align:center">
     <script>
         function add(obj){
             
             var vstu_id=formNode.stu_id.value;
             var vstu_name=formNode.stu_name.value;
             var vstu_sex=formNode.stu_sex.value;
             if(vstu_id==""||vstu_name==""||vstu_sex==""){
                 alert("数据不能为空!");
             }else{
 ​
             
                 alert(vstu_id+' '+vstu_name+' '+vstu_sex)
 ​
                 var vtable1=document.getElementById('table1'); 
 ​
                 var vtr=document.createElement('tr');
                 
 ​
                 var vtd_id=document.createElement('td');
                 vtd_id.innerText=vstu_id;
 ​
                 var vtd_name=document.createElement('td');
                 vtd_name.innerText=vstu_name;
 ​
                 var vtd_sex=document.createElement('td');
                 vtd_sex.innerHTML=vstu_sex;
 ​
                 var vth_del=document.createElement('td');
                 
                 var va=document.createElement('a');
                 va.setAttribute("href","JavaScript:void(0)");
                 va.setAttribute("onclick","del(this)");
                 va.innerHTML="删除";
                 vth_del.appendChild(va);
 ​
                 vtr.appendChild(vtd_id);
                 vtr.appendChild(vtd_name);
                 vtr.appendChild(vtd_sex);
                 vtr.appendChild(vth_del);
 ​
                 vtable1.appendChild(vtr);
             }
 ​
         }
 ​
         function del(obj){
             var msg="确定删除这条数据吗?";
 ​
             if(confirm(msg)==true){
                 var vth_delNode=obj.parentNode;
                 var vtrNode=vth_delNode.parentNode;
                 var vtable1=vtrNode.parentNode;
                 vtable1.removeChild(vtrNode);
             }
         }
     </script>
     
     <div>
 ​
         <a href ="file:///android_asset/student2.html">跳转</a>
         <form name="formNode" style="margin-top: 15px">
             编号:<input type="text" maxlength="3" size="4" name="stu_id">
             姓名:<input type="text" maxlength="8" size="4" name="stu_name">
             性别:<input type="text" size="4" name="stu_sex">
             <input type="button" value="添加" onclick="add(this)">
         </form>
         <table style="margin-top: 20px; margin-bottom: 20px;" id="table1">
             <caption style="font-size: 20px;">学生成绩表</caption>
             <tr>
                 <th>编号</th>
                 <th>姓名</th>
                 <th>性别</th>
                 <th>操作</th>
             </tr>
     
             <tr>
                 <td>001</td>
                 <td>lixu</td>
                 <td>nan</td>
                 <td><a onclick="del(this)" href="JavaScript:void(0)">删除</a></td>
             </tr>
         </table>
         
     </div>
 </body>
 </html>

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿