zoukankan      html  css  js  c++  java
  • Android——WebView网页应用

    实验报告

    课程名称 Android应用编程实验

    实验名称:网页应用-WebView
    实验目的:学习WebView的相关功能
    实验仪器设备:电脑、Android Studio、Android手机
    实验内容:

    1. 应用WebView对象浏览网页;
    2. 调用本地HTML网页文件的JavaScript;
    3. 用Android程序操纵JavaScript对话框;

    一、应用WebView对象浏览网页

    1.1实验原理

    WebKit是一个开源的浏览器引擎,WebKit内核具有非常好的网页解析机制,很多系统都使用WebKit做浏览器内核。在WebKit的API包中,最重要、最常用的类是Android.webKit. WebKit。WebView类是WebKit模块Java层的视图类,所有需要使用Web浏览功能的Android应用程序都要创建该视图对象,用于显示和处理请求的网络资源。

    1.2实验过程记录

    1.2.1布局文件

    为实现基本的相机程序效果,使用最简单的线性布局,通过组件的嵌套生成需要的布局。首先指定最外层的线性布局对齐方式为垂直布局,在其中嵌套一个LinearLayout布局,之后再编写EditText组件用来输入网站网址,加入一个button组件用于点击确定。之后在外层的线性布局中加入WebView组件用来展示需要显示的网页,如图1.1所示。
    在这里插入图片描述

    图1.1布局文件

    1.2.2控制文件

    1.2.2.1实例化对象

    在MainActivity.java文件中修改文件,以实现对程序的控制。首先如下图1.2所示实例化所需的对象。
    在这里插入图片描述

    图1.2实例化对象

    在上图1.2中,分别实例化了用于网页浏览的“WebView”类的“webView”对象、用于点击确定的“Button”类的“openWebBtn”对象、用于编辑输入网址的“EditText”类的“editText”。

    1.2.2.2重载构造函数

    对构造函数进行修改,使其实现“关联布局文件和控制文件,设置按钮监听事件”的功能。如图1.3所示。
    在这里插入图片描述

    图1.3重载构造函数

    通过findViewById方法关联图1.1中的相关组件,并为“openWeb”设置监听事件,以实现在鼠标之后,显示网页界面的功能。

    1.2.2.3编写mClick函数

    为按钮的监听事件编写 mClick 类,以实现拍照和退出功能。如图1.4所示:
    在这里插入图片描述

    图1.4 mClick类

    上图中,构造了一个继承于OnClickListener的mClick类。首先定义一个url字符串,在点击按钮之后,通过getText().toString()方法获取文本框中的字符串,将其赋值给url。通过findViewById方法将webView对象与布局文件中的组件相关联,通过loadUrl方法设置网页的网址,从而显示网页。

    1.2.3添加权限

    由于程序中需要实现访问网页的功能,所以需要在程序中添加允许程序网络访问的权限。如下图1.5所示,在 AndroidManifest.xml 文件中添加下列信息,以申请权限。
    在这里插入图片描述

    图1.5添加权限

    1.2.4模拟器测试

    编写程序结束之后,打开AndroidStudio中的安卓模拟器进行测试,但程序不能正常运行。

    1.3实验过程中存在的问题及解决方案

    1.3.1调用系统自带的浏览器

    在之前的程序中,使用了webView.loadUrl () 方法去加载网页的内容。在安卓7.1.1系统的手机模拟器下,运行结果如图1.6所示:
    在这里插入图片描述

    图1.6 调用系统浏览器

    在这里插入图片描述

    图1.7 原始效果

    在输入URL之后,点击“打开网页”按钮,会出现上图1.6所示的系统提示。该提示意思是,询问用户是以WebView Browser浏览器打开,还是以Chrome浏览器打开网页。
    点击选择WebView Browser浏览器打开网页,则会显示如图1.7所示的效果。这样的话,系统会在程序之外调用WebView Browser浏览器来显示网页。
    也就是说,用这种方式打开的网页资源是依赖于系统自带的浏览器,而不是WebView组件,若想用自身WebView组件去实现,需要去调用setWebViewClient()方法来实现。现在将代码修改,添加上setWebViewClient()方法。代码如下图1.8所示:
    在这里插入图片描述

    图1.8 添加setWebViewClient()方法

    在setWebViewClient()方法中重载shouldOverrideUrlLoading,返回值若为true将用webview,false则是系统自身浏览器,现在将返回值改为true,使程序调用webview。
    重新运行安卓模拟器,显示的效果如下图1.9所示:
    在这里插入图片描述

    图1.9 改进webview效果

    现在可以看到,在手机界面的上半部分,是EditText和button组件,下半部分是webview组件。程序没有调用系统自带的浏览器,而是使用了内嵌的webview来浏览网页的。

    1.3.2 返回键问题

    现在已经可以实现不依靠系统自带浏览器打开我们的url资源,但这里会出现一个问题,只要我们一点手机上的返回键,整个程序就直接退出了。我们想要的应该是和浏览器一样的效果,即按下返回键应该还是向后退一步,回到之前浏览的网页,而不是直接退出程序。
    解决方法,是去监听物理返回键并做出对应的相应事件,即重载onKeyDown函数,如图1.10所示:
    在这里插入图片描述

    图1.10 重载onKeyDown方法

    上图中,重载了onKeyDown方法,具体含义为:keyCode代表按键的数字标识符,通过该标识符判断是否为返回键。如果是返回键,则判断目前的网页是否可以返回,如果可以返回,则调用goBack方法,返回网页前一页面;如果不能返回,则退出该程序。

    1.3.3动态权限问题

    Android 6.0 之前我们申请权限直接在配置文件中配置一下即可,但是6.0之后,谷歌官方将权限分为普通权限和危险权限。对于危险权限来说,我们就需要进行动态设置。经过查阅资料,发现访问互联网的权限并不属于危险权限,所以暂时不考虑动态申请了。

    1.4实验结果

    现在已经实现了实验所要求的功能,在Android7.1.1版本的模拟器中运行,并将运行过程录制的视频记录如下:http://47.95.13.239/Study/Android/show/ex6_1.mp4

    二、调用本地HTML网页文件的JavaScript

    2.1实验原理

    WebSettings类用于对WebView对象的属性进行设置;WebViewClient类用于对WebView对象中各种事件的处理,通过重写该方法,可以对WebView对象在页面载入、资源载入、页面访问错误等情况发生时进行各种操作;WebChromeClient是辅助WebView处理JavaScript对话框、网页的标题、网页的图标、加载进度条等操作的类。用户可以在Android程序中调用本地的HTML网页文件的JavaScript。

    2.2实验过程记录

    2.2.1布局文件

    本次布局使用相对布局,需要添加的组件仅仅是一个WebView组件,如图2.1所示。
    在这里插入图片描述

    图2.1 布局文件

    2.2.2控制文件

    2.2.2.1实例化对象

    在MainActivity.java文件中修改文件,以实现对程序的控制。首先如下图1.2所示实例化所需的对象。
    在这里插入图片描述

    图2.2实例化对象

    在上图2.2中,分别实例化了用于网页浏览的“WebView”类的“webView”对象、用于线程间通信的“Handler”类的“handler”对象、用于处理JavaScript的alert对话框的“MWebChromeClient”类的“WebChromeClient”对象。

    2.2.2.2重载构造函数

    对构造函数进行修改,使其实现“关联布局文件和控制文件,设置WebView属性、加载本地HTML资源”的功能。如图2.3所示。
    在这里插入图片描述

    图2.3重载构造函数

    通过findViewById方法关联图2.1中的相关组件,通过WebSettings类设置WebView的相关属性。属性设置的相关含义见表2.1。
    表2.1WebSettings类的方法
    方法 功能
    setAllowFileAccess(false) 设置在WebView内部是否允许访问文件,默认允许访问。
    setJavaScriptEnabled(true) 设置支持JavaScript脚本
    setBuiltInZoomControls(true) 设置支持缩放
    setDefaultFontSize(24) 设置默认字体大小
    之后通过addJavascriptInterface方法,设置JavaScript接口,实现Android与JavaScript的通信。通过loadUrl方法设置需要打开的HTML文件。

    2.2.2.3编写MObiect类

    下面编写MObiect类,用来调用JavaScript,代码如下图2.4所示:
    在这里插入图片描述

    图2.4编写MObiect类

    这里让我奇怪的是,android_show()这个函数没有被调用过,估计程序会出现问题。

    2.2.2.4编写MWebChromeClient类

    编写MWebChromeClient类,用以在Android中响应JavaScript的调用,如图2.5所示:
    在这里插入图片描述

    图2.5 编写MWebChromeClient类

    2.2.2.5编写本地HTML资源文件

    为了实现该程序“调用本地HTML网页文件中的JavaScript”的功能,需要新建一个HTML文件,如图2.15所示,创建asset文件夹。之后在asset文件夹下,创建test.html网页文件。并在文件中写入相关代码,如图2.16所示。
    在这里插入图片描述

    图2.16 HTML文件

    在这里插入图片描述

    图2.15创建asset文件夹

    2.2.3模拟器测试

    编写代码完成,启动安卓模拟器进行测试。程序运行不正常,只显示了空白的页面,如图2.6所示:
    在这里插入图片描述

    图2.6空白界面

    2.3实验过程中存在的问题及解决方案

    首次启动模拟器运行时,正如上图2.6所示,程序不能正常运行,显示界面为空白。仔细阅读代码可以看到,在onCreate方法中,我已经使用了loadUrl方法来设置本地的HTML资源路径,如图2.7红框中的部分所示。为了确定是不是本地的HTML文本资源有问题,我修改了HTML文件,添加了如图2.8红框中的部分。
    在这里插入图片描述

    图2.7控制文件

    在这里插入图片描述

    图2.8 添加测试语句

    在HTML文件中添加该语句之后,如果程序能够正常访问本地HTML资源,应该会在手机界面显示hello段落,如果不能显示“hello”的话,说明本地HTML资源有问题。
    下面运行模拟器进行测试,测试结果如下图2.9所示:
    在这里插入图片描述

    图2.9测试

    可以看到界面中显示了hello,说明程序确实已经访问到了本地的HTML文件。出现刚才的不显示现象,是因为Script脚本这方面出现了某些问题。
    之后我注意到了之前看到的android_show()这个函数,如图2.10红框所示。它在整个程序中是没有被调用过的,我怀疑是这里出现了问题,于是阅读这段代码。
    在这里插入图片描述

    图2.10未调用的函数

    可以看到这段代码中,应该是用handler在Android和js之间传递了信息,通过loadUrl()方法,调用JavaScript中的show_alert()函数,以实现某些功能。但是再回到test.html文件中,发现根本就没有写show_alert () 函数,只写了一个名为addAll的function。我以为是程序错了,就将test.html文件中的addAll函数改名成了show_alert () 。运行程序发现,依然不显示文字。
    最后通过与同学的交流,发现问题出现在test.html文件中,如图2.11红框中所示。
    在这里插入图片描述

    图2.11 错误定位

    问题出现在红色箭头所指的位置。通过查阅资料发现,document.write是JavaScript中对document.open所开启的文档流操作的API方法,它能够直接在文档流中写入字符串,在本程序中,使用了带格式的文本字符串,也就可以将HTML格式的文本写入到文档流中。之前的错误在于,没有将作为字符串输入文档流,破坏了HTML文本标记语言的格式,导致文本不能正常显示。
    现在运行程序,可以看到如下图2.12所示的界面。
    在这里插入图片描述

    图2.12 显示界面

    虽然现在看来程序算是运行正常,但是回到编译器中看看代码,发现刚才的android_show()依然未被调用过。我怀疑android_show()函数并不没有起到调用JavaScript的功能,于是将该函数中的内容删除,只保留函数名,改成如下图2.13所示的内容。
    在这里插入图片描述

    图2.13 修改文件

    重新在模拟器运行程序,结果程序正常显示,效果与图2.12一致。这说明android_show()函数确实没有起作用。经过查阅资料得知,该程序在JS调用Android的过程中,采用的是addJavascriptInterface()方法,通过该方法将 Java 对象和 JS 对象进行映射。程序中定义的MObject类,也就是一个JavaScript接口函数,其中最重要的就是写上“@JavascriptInterface”来表明它是一个JavaScript接口,同时加上这个也是因为安全问题。其他内容在本次程序中暂时没有用到。程序中如图2.14所示的代码,将MObjcet类的对象映射到js的test对象,再通过document.write方法将文本流输出到手机界面。
    在这里插入图片描述

    图2.14 对象映射

    2.4实验结果

    现在已经实现了实验所要求的功能,在Android7.1.1版本的模拟器中运行,运行过程录制的视频如下:http://47.95.13.239/Study/Android/show/ex6_2.mp4

    三、用Android程序操纵JavaScript对话框

    3.1实验原理

    通过addJavascriptInterface()方法实现Java 对象和 JS 对象进行映射,在script脚本标签中定义show_alert()函数,通过alert()方法描述警告框,并通过onJsAlert()方法进行显示处理。

    3.2实验过程记录

    由于例题6_3与例题6_2大段代码相似,其中“布局文件”和“控制文件”的代码与例题6_3相同,下面不再重复记录这两部分。

    3.2.1编写HTML文件

    下面对HTML文件进行编写,如图3.1所示:
    在这里插入图片描述

    图3.1HTML文件

    上图3.1中,同样是编写了一个

    3.2.2模拟器测试

    将编写完成的程序在安卓模拟器上运行,查看运行结果,如图3.2所示。
    在这里插入图片描述

    图3.2运行截图

    在界面的顶部输入测试字符串“zhanghoujin”,点击顶部右侧的“call Android”按钮进行提交,此时会在页面的底部出现一个Toast提示框,输出“Hello zhanghoujin”字样。

    3.3实验过程中存在的问题及解决方案

    因为有了例题6_2的经验,在此次例题6_3中未出现明显的问题。

    3.4实验结果

    现在已经实现了实验所要求的功能,在Android7.1.1版本的模拟器中运行,运行过程录制的视频如下:http://47.95.13.239/Study/Android/show/ex6_3.mp4

    四、源代码

    我已经将整理过的该项目的源代码上传到了GitHub:
    https://github.com/ZHJ0125/AndroidLeaning

    4.1 ex6_1

    4.1.1 activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_gravity="center_horizontal"
        android:gravity="center">
        <LinearLayout
            android:id="@+id/LinearLayout1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <EditText
                android:layout_width="270dp"
                android:layout_height="wrap_content"
                android:id="@+id/editText1"/>
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/button1"
                android:width="1dp"
                android:text="打开网页"/>
        </LinearLayout>
        <WebView
            android:id="@+id/webView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>
    

    4.1.2 MainActivity.java

    package zhj.com.ex6_1;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.KeyEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    import android.widget.Button;
    import android.widget.EditText;
    
    public class MainActivity extends Activity {
        WebView webView;
        Button openWebBtn;
        EditText editText;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            openWebBtn = (Button) findViewById(R.id.button1);
            editText = (EditText)findViewById(R.id.editText1);
            openWebBtn.setOnClickListener(new mClick());
        }
    
        class mClick implements OnClickListener{
            @Override
            public void onClick(View v) {
                String url = editText.getText().toString();
                webView = (WebView)findViewById(R.id.webView1);
                webView.setWebViewClient(new WebViewClient() {
                    /**
                     * 重写shouldOverrideUrlLoading,返回值若为true将用webview,false则是系统自身浏览器
                     */
                    @Override
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {
                        view.loadUrl(url);
                        return true;
                    }
                });
                webView.loadUrl("http://" + url);
            }
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (webView.canGoBack()) {
                    webView.goBack();
                    return true;
                } else {
                    System.exit(0);
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    }
    

    4.1.3 AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="zhj.com.ex6_1">
        <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>
        <uses-permission android:name="android.permission.INTERNET"/>
    </manifest>
    

    4.2 ex6_2

    4.2.1 activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:id="@+id/hello"/>
        <WebView
            android:id="@+id/webView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>
    
    
    ### 4.2.2 MainActivity.java
    ```java
    package zhj.com.ex6_2;
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.webkit.JsResult;
    import android.webkit.WebChromeClient;
    import android.webkit.WebSettings;
    import android.webkit.WebView;
    import android.webkit.JavascriptInterface;
    import android.widget.TextView;
    import android.widget.Toast;
    public class MainActivity extends Activity {
        WebView webView;
        Handler handler = new Handler();
        TextView textView;
        MWebChromeClient mWebChromeClient;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            webView = (WebView)findViewById(R.id.webView1);
            textView = (TextView) findViewById(R.id.hello);
            WebSettings webSettings = webView.getSettings();
            webSettings.setAllowFileAccess(true);
            webSettings.setJavaScriptEnabled(true);
            webSettings.setBuiltInZoomControls(true);
            webSettings.setDefaultFontSize(24);
            MObject mObject = new MObject();
            webView.addJavascriptInterface(mObject, "test");
            mWebChromeClient = new MWebChromeClient();
            webView.setWebChromeClient(mWebChromeClient);
            webView.loadUrl("file:///android_asset/test.html");
        }
        class MObject extends Object{
            @JavascriptInterface
            public void android_show(){
            }
        }
        class MWebChromeClient extends WebChromeClient{
            @Override
            public boolean onJsAlert (WebView view, String url,String message, JsResult result){
                Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
                return true;
            }
        }
    }
    

    4.2.3 test.html

    <!DOCTYPE html>
    <html>
        <head>
            <title>一个简单的JavaScript例程</title>
        </head>
        <body>
            <script language="javascript" type="text/javascript">
                function addAll(a,b,c){
                    return a+b+c;
                }
                var total = addAll(30,40,50);
                var str = "Ran 5 hours,<br> finally finished the ";
                document.write("<html><B> "+ str + total + " km! </B></html>");
            </script>
        </body>
    </html>
    

    4.3 ex6_3

    4.3.1 activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <WebView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="Hello World!"
            android:id="@+id/webView1"/>
    </LinearLayout>
    

    4.3.2 MainActivity.java

    package zhj.com.ex6_3;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.webkit.JavascriptInterface;
    import android.webkit.JsResult;
    import android.webkit.WebChromeClient;
    import android.webkit.WebSettings;
    import android.webkit.WebView;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
        WebView webView;
        Handler handler = new Handler();
        MWebChromeClient mWebChromeClient;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            webView = (WebView)findViewById(R.id.webView1);
            WebSettings webSettings = webView.getSettings();
            webSettings.setAllowFileAccess(true);
            webSettings.setJavaScriptEnabled(true);
            webSettings.setBuiltInZoomControls(true);
            webSettings.setDefaultFontSize(24);
            MObject mObject = new MObject();
            webView.addJavascriptInterface(mObject, "test");
            mWebChromeClient = new MWebChromeClient();
            webView.setWebChromeClient(mWebChromeClient);
            webView.loadUrl("file:///android_asset/test.html");
        }
        class MObject extends Object{
            @JavascriptInterface
            public void android_show(){
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("提示:使用了多线程的run()方法!!");
                        webView.loadUrl("javascript: show_alert()");
                    }
                });
            }
        }
        class MWebChromeClient extends WebChromeClient{
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
                return true;
            }
        }
    }
    

    4.3.3 test.html

    <html>
    <head>
        <title>JavaScript与Android交互</title>
    </head>
    <script type="text/javascript">
        function show_alert(){
            var a = document.getElementById("text").value;
            alert("Hello " + a);
            }
    </script>
    <body>
    <form action="">
        <input type="text" id="text" value=""/>
        <input type="button" id="button" onclick="window.test.android_show()" value="call Android"/>
    </form>
    </body>
    </html>
    

    五、实验总结

    这次安卓实验不太顺利,在例题6_2上花了一些时间,但最后问题都解决了。通过这次实验我意识到,只有把每个细节都搞明白,才能更好地避免错误的发生。虽然这次实验中出现了很多问题,但通过解决问题,我也收获了很多编程方面的知识。
    在Android编程方面,主要掌握了以下知识:

    1. WebView对象的基本功能
    2. 调用本地HTML网页文件的JavaScript脚本
    3. 文档流写入的基本操作
    4. 使用Android操纵JavaScript对话框

    六、部分参考资料

    1. Android与JS交互的细节问题 https://www.jianshu.com/p/01e5d4fa1c79
    2. Android:这是一份全面 & 详细的Webview使用攻略
      https://www.jianshu.com/p/3c94ae673e2a
    3. 最全面总结 Android WebView与 JS 的交互方式
      https://www.jianshu.com/p/345f4d8a5cfa
    4. 你不知道的 Android WebView 使用漏洞 https://www.jianshu.com/p/3a345d27cd42
    5. Android调用js的坑 https://www.jianshu.com/p/01cb2f52c0b0
    6. 前端WebView指南之Android交互https://75team.com/post/android-webview-and-js.html
    7. 安卓开发笔记——WebView组件 https://www.cnblogs.com/lichenwei/p/3959345.html
    8. document.write的用处! https://blog.csdn.net/qq_34986769/article/details/52160532
    9. 124、@JavascriptInterface https://www.cnblogs.com/androidsj/p/6414891.html
  • 相关阅读:
    转: IOS程序内发短信 MFMessageComposeViewController
    对象之间如何比较是否相等?
    相比xib 使用代码编排view 的一个明显的好处就是可以更好地重复使用已有代码,减少代码冗余。
    关于deselectRowAtIndexPath
    IOS中为tableViewCell增加右侧标记(选中或者更多)
    ios 中是否每一个对象(尤其是在使用多线程时),都要判断一下对象是否为nil,以防止程序闪退?
    模拟出ios中流行的黑色背景底
    转 ios给view设置圆角
    转 UIAlertView 不显示、屏幕变灰
    转 UIActivityIndicatorView、UIProgressView 活动与进度指示器-IOS开发
  • 原文地址:https://www.cnblogs.com/ZHJ0125/p/12904515.html
Copyright © 2011-2022 走看看