Android?WebView基礎(chǔ)舉例詳解
一、簡介
WebView是一個基于webkit引擎、展現(xiàn)web頁面的控件。Android的Webview在低版本和高版本采用了不同的webkit版本內(nèi)核,4.4后直接使用了Chrome。
二、重要類
以WebView類為基礎(chǔ),WebSettings、WebViewClient、WebChromeClient為輔助共同完成安卓段加載網(wǎng)頁的操作。
1、WebView
//1、加載網(wǎng)頁相關(guān)
//直接加載服務(wù)器網(wǎng)頁
my_web_view.loadUrl("https://www.baidu.com")
//直接加載本地網(wǎng)頁file:///android_asset/為固定寫法)
my_web_view.loadUrl("file:///android_asset/1.html")
// 緩存歷史清理
//Clears the resource cache. Note that the cache is per-application,
// so this will clear the cache for all WebViews used.
my_web_view.clearCache(true)
// 清空歷史(本webView瀏覽的)
my_web_view.clearHistory()
// 結(jié)合工具類
my_web_view.webViewClient = object : WebViewClient() // 設(shè)置webViewClient
my_web_view.webChromeClient = object : WebChromeClient()// 設(shè)置WebChromeClient
/**
* 返回鍵處理,網(wǎng)頁中可返回上一頁,不處理返回鍵直接退出App
* */
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
//when user press back code and canGoBack
if (keyCode == KeyEvent.KEYCODE_BACK && my_web_view.canGoBack()) {
my_web_view.goBack()
return true
}
return super.onKeyDown(keyCode, event)
}
2、WebSettings
/**
* WebSettings類:對webView 進行配置管理
* */
@SuppressLint("SetJavaScriptEnabled", "ObsoleteSdkInt")
private fun webViewSettings() {
val webSettings = my_web_view.settings
// js交互控制
//支持js交互,動畫等操作會造成cpu、電量消耗可在activity、 fragment的onResume、onStop進行開關(guān)控制
webSettings.javaScriptEnabled = true
// 適配
webSettings.useWideViewPort = true//自適應(yīng)屏幕->自動將圖片調(diào)整到自適應(yīng)webView 大小
webSettings.loadWithOverviewMode = true//自適應(yīng)屏幕->縮放到屏幕大小
//縮放
webSettings.setSupportZoom(true)//支持縮放,默認(rèn)為true。
webSettings.builtInZoomControls = true//設(shè)置是否展示內(nèi)置的縮放控件,默認(rèn)為false
webSettings.displayZoomControls = true//顯示原生的縮放控件
//其他
webSettings.allowFileAccess = true // 可訪問文件
webSettings.javaScriptCanOpenWindowsAutomatically = true // 支持js 自動打開新窗口
webSettings.loadsImagesAutomatically = true // 支持自動加載圖片
webSettings.defaultTextEncodingName = "UTF-8" // 默認(rèn)值也是UTF-8
//緩存控制
webSettings.domStorageEnabled = true // 開啟dom緩存功能
webSettings.databaseEnabled = true // 開啟數(shù)據(jù)庫緩存功能
webSettings.setAppCacheEnabled(true)// 開啟application 緩存功能
webSettings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK //設(shè)置緩存模式 (LOAD_CACHE_ELSE_NETWORK,有緩存時加載緩存,即使緩存過期,沒有時從網(wǎng)絡(luò)加載)
webSettings.setAppCachePath("") // 設(shè)置app緩存目錄,api已棄用。
// 5.1以上默認(rèn)禁止了https和http混用,開啟如下
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
}
}
3、WebViewClient
協(xié)助WebView工作,有一些列回調(diào)方法,用于處理各種通知 & 請求事件等。
my_web_view.webViewClient = object : WebViewClient() {
//加載url、返回false 代表使用webView 加載url 不使用系統(tǒng)瀏覽器。
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
// 如下loadUrl,return true 這種也代表不使用系統(tǒng)瀏覽器。但是官方建議直接 return false
// view?.loadUrl("https://www.baidu.com")
// return true
return false// 直接return false即可
}
// 頁面加載時回調(diào)
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
}
// 頁面加載完成時回調(diào)
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
}
// 加載頁面資源時調(diào)用(如頁面上有好多圖片,沒加載一張就會回調(diào)一次)
override fun onLoadResource(view: WebView?, url: String?) {
super.onLoadResource(view, url)
}
// 加載頁面時服務(wù)器出現(xiàn)錯誤(例如404)
override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
super.onReceivedError(view, request, error)
// todo 展示自定義html頁面,提示錯誤。
}
// 處理https請求
override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
// 不要使用super,否則有些手機訪問不了,因為包含了一條 handler.cancel()
// super.onReceivedSslError(view, handler, error);
// 接受所有網(wǎng)站的證書,忽略SSL錯誤,執(zhí)行訪問網(wǎng)頁。這種方式在發(fā)生ssl不會影響網(wǎng)頁加載。
// 但是google play 認(rèn)為這是不安全的操作。會給你警告。
handler?.proceed()
// handler?.cancel() // 發(fā)生ssl時掛起連接表現(xiàn)為白屏,默認(rèn)方式。
}
}
4、WebChromeClient
/**
* WebChromeClient類:輔助webView 處理js dialog、網(wǎng)站icon、網(wǎng)站title。
* js的各種dialog事件觸發(fā)時可由webChromeClient的響應(yīng)方法回調(diào)到。
* */
private fun webChromeClient() {
my_web_view.webChromeClient = object : WebChromeClient() {
// 獲得網(wǎng)頁進度時回調(diào)
override fun onProgressChanged(view: WebView?, newProgress: Int) {
super.onProgressChanged(view, newProgress)
}
// 獲取網(wǎng)頁的標(biāo)題時回調(diào)
override fun onReceivedTitle(view: WebView?, title: String?) {
super.onReceivedTitle(view, title)
}
// 是否由客戶端處理js Alert 事件,true 代表客戶端處理,false 代表客戶端不處理。
// 一般客戶端處理時客戶端 展示對話框讓用戶進行選擇
override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
AlertDialog.Builder(mContext)
.setTitle("Title")
.setMessage(message)
.setPositiveButton("確定") { dialog, which ->
result?.confirm()
}.setCancelable(false)
.show()
return true
}
// js Confirm 對話框攔截,true代表點擊確定,false 代表點擊取消。
override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
return super.onJsConfirm(view, url, message, result)
}
// 輸入框攔截,true 代表返回輸入框的值,false 代表返回null
override fun onJsPrompt(
view: WebView?,
url: String?,
message: String?,
defaultValue: String?,
result: JsPromptResult?
): Boolean {
return super.onJsPrompt(view, url, message, defaultValue, result)
}
}
}
三、Android 調(diào)用 JS 代碼
方式
- webView的loadUrl(" javascript:js方法()")
- webView的evaluateJavascript()
<html>
<head>
<meta charset="UTF-8">
<title>SunnyDay</title>
<!--內(nèi)部引入法-->
<script>
function showAlertDialog(result){
alert("i am js alert dialog,i am js method!"+result)
return "i am js method!"
}
</script>
</head>
<body>
<h3>i am a simple html page</h3>
</body>
</html>>
如上準(zhǔn)備個1.html文件
1、webView#loadUrl 加載原理及其代碼
借助webChromeClient 的各種回調(diào)處理。一般為js的各種dialog 方法觸發(fā)時被安卓webViewClient的各種回調(diào)監(jiān)聽方法攔截消費。
webSettings = web_view.settings
webSettings.javaScriptEnabled = true//允許啟用js功能
webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗
// 加載Assets下html文件(這時js代碼也就載入了)
//加載assets文件夾下的html文件時使用固定格式語法即可:file:///android_asset/文件名.html
web_view.loadUrl("file:///android_asset/1.html")
web_view.webViewClient = object : WebViewClient(){}
callByLoadUrl()
//webView只是載體,內(nèi)容的渲染需要使用webViewChromeClient類去實現(xiàn),所以在這里寫回調(diào)處理。
web_view.webChromeClient = object : WebChromeClient() {
// 此方法可回調(diào)到alert警告框的信息。
override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
val build = AlertDialog.Builder(mContext)
.setTitle("Js showAlertDialog Method")
.setMessage(message)
.setPositiveButton("確定") { dialog, which ->
result?.confirm()
}.setCancelable(false)
build.create().show()
return true
}
}
/**
* 方式1:webView的loadUrl()
* */
private fun callByLoadUrl() {
// 點擊安卓按鈕加載js方法
btn_call_js_method.setOnClickListener {
// 調(diào)用js時要保證網(wǎng)頁加載完成,否則js代碼調(diào)用失敗。因為html中也是頁面加載完成才響應(yīng)的js。
web_view.loadUrl("javascript:showAlertDialog(\"result\")")
}
}
2、webView#evaluateJavascript
webSettings = web_view.settings
webSettings.javaScriptEnabled = true//允許啟用js功能
webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗
// 加載Assets下html文件(這時js代碼也就載入了)
web_view.loadUrl("file:///android_asset/1.html")//加載assets文件夾下的html文件時使用固定格式語 法即可:file:///android_asset/文件名.html
web_view.webViewClient = object : WebViewClient(){}
callByEvaluateJavascript()
/**
*方式2:webView的evaluateJavascript
* js 方法無返回值時it為 null
*/
private fun callByEvaluateJavascript() {
btn_call_js_method.setOnClickListener {
web_view.evaluateJavascript("javascript:showAlertDialog()") {
Log.d("AndroidCallJsActivity", "" + it)//AndroidCallJsActivity"i am js method!"
}
}
}
3、總結(jié)
/**
* Android call js method practice
* 兩種方式:
* 1、webView的loadUri(" javascript:js方法()")
* 這種方式一般調(diào)用的為js的dialog方法,使用安卓的WebChromeClient 對應(yīng)回調(diào)方法進行攔截處理。
* 2、webView的evaluateJavascript
* 直接調(diào)用js的方法,還可以獲得js方法返回值回調(diào)
* js方法結(jié)果回調(diào)為String 類型值
* js方法無返回值,這里回調(diào)為null
*
* 建議以這種方式,既可快捷獲得返回值,又可通過1中的dialog回調(diào)處理。
*
* 小結(jié):Android call js method
* 安卓調(diào)用js方法后可以在安卓端獲得結(jié)果回調(diào)處理。
* */
| 調(diào)用方式 | 優(yōu)點 | 缺點 | 適用場景 |
|---|---|---|---|
| loadUrl | 方便簡潔 | 效率低,獲取返回值麻煩 | 不需要獲取返回值時 |
| evaluateJavascript | 效率高 | 安卓4.4以上才能使用 | 安卓4.4以上 |
四、Js調(diào)用安卓代碼
方式
- 通過webView的addJavascriptInterface方法
- 通過重寫webViewClient的shouldOverrideUrlLoading方法篩選url調(diào)用
- 通過 WebChromeClient 的dialog 回調(diào)判斷篩選url調(diào)用
<html>
<head>
<meta charset="UTF-8">
<title>SunnyDay</title>
<!--內(nèi)部引入法-->
<script>
//方式1:對象映射方式
function callAndroid(){
// 調(diào)用安卓的hello方法,由于安卓中添加了對象映射,test.hello()就相當(dāng)于安卓的
//JsInterface().hello()
test.hello(" i am js code! ");
}
//方式2:重寫shouldOverrideUrlLoading 進行攔截
function callAndroid2(){
document.location = "js://webview?arg1=111&arg2=222";
}
//方式3:WebChromeClient 的 onJsAlert、onJsConfirm、onJsPrompt 方法回調(diào)攔截 JS 對話框
function callAndroid3(){
//1、首先搞個輸入框,觸發(fā)時安卓可獲得回調(diào)
//2、收到回調(diào)后安卓處理,點擊確定返回輸入框值,點擊取消返回null
var result=prompt("js://demo?arg1=111&arg2=222");
alert("demo " + result);
}
</script>
</head>
<body>
<h3>i am a simple html page</h3>
//方式1
<button type="button" id="btn" onclick="callAndroid()">點我即可調(diào)用Android的hello方法</button>
//方式2
<button type="button" id="btn2" onclick="callAndroid2()">方式2</button>
//方式3
<button type="button" id="button3" onclick="callAndroid3()">方式3</button>
</body>
</html>>
1、addJavascriptInterface
(1)定義對象映射方法
/**
* 1、自定義對象用于對象映射
* 2、自定義方法,映射后供js對象使用
* 3、方法必須加JavascriptInterface注解
*/
class JsInterface {
@JavascriptInterface
fun hello(msg: String) {
Log.d("JsCallAndroidActivity", "android method hello is called:$msg")
}
}
(2)映射
//js調(diào)用安卓方法方式1:
webSettings = web_view_th.settings
webSettings.javaScriptEnabled = true//允許啟用js功能
webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗
web_view_th.loadUrl("file:///android_asset/2.html")
// 定義對象映射,把自定義的JsInterface映射給"test",供js對象使用。
web_view_th.addJavascriptInterface(JsInterface(), "test")// 一行代碼十分簡單
2、重寫webViewClient的shouldOverrideUrlLoading方法
webSettings = web_view_th.settings
webSettings.javaScriptEnabled = true//允許啟用js功能
webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗
web_view_th.loadUrl("file:///android_asset/2.html")
web_view_th.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
//view?.url //file:///android_asset/2.html ,
//注意這里的兩個url不相同 get的url為 webViewLoad的,request的為動態(tài)定義的
val requestUrl = request?.url
Log.i("JsCallAndroidActivity", "" + requestUrl) //js://webview?arg1=111&arg2=222
return if (requestUrl.toString() == "js://webview?arg1=111&arg2=222") {
// 符合篩選,調(diào)用安卓方法。
printLog()
true
} else {
super.shouldOverrideUrlLoading(view, request)
}
}
}
private fun printLog() {
Log.i("JsCallAndroidActivity", "android method:print log !")
}
3、通過 WebChromeClient 的dialog 回調(diào)判斷篩選url調(diào)用
webSettings = web_view_th.settings
webSettings.javaScriptEnabled = true//允許啟用js功能
webSettings.javaScriptCanOpenWindowsAutomatically = true // 允許js彈窗
web_view_th.loadUrl("file:///android_asset/2.html")
web_view_th.webChromeClient = object : WebChromeClient() {
override fun onJsPrompt(
view: WebView?,
url: String?,
message: String?,
defaultValue: String?,
result: JsPromptResult?
): Boolean {
val uri = Uri.parse(message)
if ("js" == uri.scheme) {
if ("demo" == uri.authority) {
result?.confirm("JS 調(diào)用了 Android 的方法")
// 符合篩選,調(diào)用安卓方法。
printLog()
}
return true
}
return super.onJsPrompt(view, url, message, defaultValue, result)
}
}
4、小結(jié)
/** * js call android method practise * 1、webView的addJavascriptInterface(自定義對象,“映射給的自定義字符串對象”) * 這種方式最簡單,自定義對象,內(nèi)部定義一系列方法供js調(diào)用。js拿到映射對象即可調(diào)用安卓自定義的對象方法 * * 2、重寫webViewClient的shouldOverrideUrlLoading方法,篩選請求的url是否為js規(guī)定的url,是規(guī)定的則調(diào)用安卓的相應(yīng)方法。 * * 3、通過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調(diào)攔截JS對話框alert()、confirm()、prompt(),原理與2一致。 * */
| 調(diào)用方式 | 優(yōu)點 | 缺點 | 適用場景 |
|---|---|---|---|
| WebView.addJavascriptInterface 對象映射 | 方便簡潔 | Android 4.2 一下存在漏洞 | Android 4.2 以上相對簡單的應(yīng)用場景 |
| WebViewClient.shouldOverrideUrlLoading 回調(diào)攔截 | 不存在漏洞 | 使用復(fù)雜,需要協(xié)議約束 | 不需要返回值情況下 |
| WebChormeClient.onJsAlert / onJsConfirm / onJsPrompt 方法回調(diào)攔截 | 不存在漏洞 | 使用復(fù)雜,需要協(xié)議約束 | 能滿足大多數(shù)場景 |
五、Android 內(nèi)嵌網(wǎng)頁時登錄狀態(tài)同步方案
1、使用 WebView 和 Cookie 同步
Android 的 WebView 是一種能在應(yīng)用中顯示網(wǎng)頁的組件。WebView 會自動處理 Cookies,但為了確保登錄狀態(tài)的同步,可能需要手動同步應(yīng)用和 WebView 的 Cookies。
(1) 獲取應(yīng)用中的 Cookie
如果你的應(yīng)用在登錄后保存了 Cookie,可以通過 CookieManager 來獲取這些 Cookie。
(2) 將 Cookie 注入 WebView:
在加載網(wǎng)頁前,將這些 Cookie 注入 WebView 的 CookieManager。
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
// 獲取應(yīng)用的 Cookie,假設(shè)名為 "appCookie"
String appCookie = "key=value; domain=yourdomain.com";
cookieManager.setCookie("yourdomain.com", appCookie);
// 加載網(wǎng)頁
webView.loadUrl("https://yourdomain.com");
(3) 確保同步:
在 WebView 加載新頁面時,確保 Cookie 同步。
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
CookieManager.getInstance().flush();
}
});
2、使用 Shared Preferences 和 JavaScript Bridge
這種方法可以通過 JavaScript 與 Android 應(yīng)用交互,保持登錄狀態(tài)同步。
(1)保存登錄狀態(tài):
登錄后,將登錄狀態(tài)(例如 token)保存到 Shared Preferences。
SharedPreferences sharedPref = getSharedPreferences("MyApp", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("token", "your_token");
editor.apply();(2)設(shè)置 JavaScript 接口:
在 WebView 中設(shè)置 JavaScript 接口,用于獲取登錄狀態(tài)。
webView.addJavascriptInterface(new Object() {
@JavascriptInterface
public String getToken() {
SharedPreferences sharedPref = getSharedPreferences("MyApp", Context.MODE_PRIVATE);
return sharedPref.getString("token", "");
}
}, "Android");
(3)在網(wǎng)頁中使用:
在網(wǎng)頁的 JavaScript 中調(diào)用這個接口,獲取登錄狀態(tài)。
function getToken() {
return Android.getToken();
}
// 在需要時調(diào)用 getToken(),例如頁面加載完成后
document.addEventListener("DOMContentLoaded", function() {
var token = getToken();
if (token) {
// 使用 token 做進一步處理
}
});
3、使用 OAuth 進行單點登錄(SSO)
如果你的應(yīng)用和網(wǎng)頁都支持 OAuth,可以使用 OAuth 進行單點登錄。
(1)在應(yīng)用中獲取 OAuth Token:
用戶在應(yīng)用中登錄后,獲取 OAuth Token 并保存。
(2)WebView 加載網(wǎng)頁時附加 Token:
在加載網(wǎng)頁時,將 Token 附加在 URL 或請求頭中。
String url = "https://yourdomain.com?token=" + oauthToken;
webView.loadUrl(url);
// 或者設(shè)置請求頭
webView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Bearer " + oauthToken);
request.setRequestHeaders(headers);
return super.shouldInterceptRequest(view, request);
}
});4、使用統(tǒng)一的身份認(rèn)證系統(tǒng)
如果你的應(yīng)用和網(wǎng)頁都使用統(tǒng)一的身份認(rèn)證系統(tǒng)(如 Firebase Authentication),可以通過相同的身份認(rèn)證機制同步登錄狀態(tài)。
(1)應(yīng)用中登錄:
使用統(tǒng)一的身份認(rèn)證系統(tǒng)登錄,并獲取認(rèn)證信息。
(2)WebView 中共享認(rèn)證信息:
通過與身份認(rèn)證系統(tǒng)的集成,在 WebView 中實現(xiàn)自動登錄。
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser currentUser = mAuth.getCurrentUser();
if (currentUser != null) {
String idToken = currentUser.getIdToken(false).getResult().getToken();
String url = "https://yourdomain.com?token=" + idToken;
webView.loadUrl(url);
}六、WebView相關(guān)優(yōu)化建議
1、給 WebView 加一個加載進度條
為了友好展示,重寫 WebChromeClient 的 onProgressChanged 方法。未加載完成時展示loading進度條
2、提高 HTML 網(wǎng)頁加載速度,等頁面 finsh 在加載圖片
public void load () {
if(Build.VERSION.SDK_INT >= 19) {
webView.getSettings().setLoadsImagesAutomatically(true);
} else {
webView.getSettings().setLoadsImagesAutomatically(false);
}
}
3、onReceivedError 時加載自定義界面
web的error 頁面比較丑,我們可以在加載失敗時,展示安卓自定義的錯誤展示頁。
4、動畫、銀屏、視頻 合適加載釋放
動畫、銀屏、視頻 加載會造成cpu、電量消耗可在activity、 fragment的onResume、onStop進行開關(guān)控制。
七、收獲
1、明文傳輸控制
Android P 阻止加載任何 http 的請求,在清單文件application節(jié)點 添加android:usesCleartextTraffic=“true”
2、Android 5.0 之后 WebView 禁止加載 http 與 https 混合內(nèi)容 。這樣會造成某些資源加載失敗。
if (Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP){
webview.getSettings().
setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
/*
例如:https://www.aaa.com.cn/a/b/c/d/e/index.html?uid=0011&URL=http://www.bbb.com.cn/1.png 這個url
1、實際頁面為:https://www.aaa.com.cn/a/b/c/d/e/index.html 后面追加了一些參數(shù)
2、h5頁面上src標(biāo)簽加載http://www.bbb.com.cn/1.png
此時你使用webview.loadUrl("https://www.aaa.com.cn/a/b/c/d/e/index.html?uid=0011&URL=http://www.bbb.com.cn/1.png") 就會出現(xiàn)h5 圖片顯示失敗。
解決方案開啟MixedContentMode
*/
3、硬件加速開啟導(dǎo)致問題
比如不能打開 PDF,播放視頻花屏等等。關(guān)閉硬件加速。
4、重寫webViewClient的shouldOverrideUrlLoading
否則系統(tǒng)不知道你是想用webview打開url 還是使用系統(tǒng)瀏覽器。
5、WebView白屏問題
原因:頁面進度不到100%時顯示的就是白屏,進度到100時開始加載網(wǎng)頁資源。
解決:網(wǎng)上方案較多這里提示一種:進度不到100時展示加載提示。
The end
到此這篇關(guān)于Android WebView基礎(chǔ)的文章就介紹到這了,更多相關(guān)Android WebView基礎(chǔ)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android RefreshLayout實現(xiàn)下拉刷新布局
這篇文章主要為大家詳細(xì)介紹了Android RefreshLayout實現(xiàn)下拉刷新布局,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-10-10
flutter showModalBottomSheet常用屬性及說明
這篇文章主要介紹了flutter showModalBottomSheet常用屬性及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
Android開發(fā)SavedState?Jetpack狀態(tài)保存利器
這篇文章主要為大家介紹了Android開發(fā)SavedState?Jetpack狀態(tài)保存利器使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08
Android中ListView綁定CheckBox實現(xiàn)全選增加和刪除功能(DEMO)
本文通過實例給大家講解了Android中ListView綁定CheckBox實現(xiàn)全選增加和刪除功能(DEMO)的代碼,對android checkbox全選相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧2016-08-08

