【Android WebView】WebView基础

在这里插入图片描述

一、简介

WebView是一个基于webkit引擎、展现web页面的控件。Android的Webview在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了Chrome。

二、重要类

以WebView类为基础,WebSettings、WebViewClient、WebChromeClient为辅助共同完成安卓段加载网页的操作。

1、WebView
        //1、加载网页相关
        
        //直接加载服务器网页
        my_web_view.loadUrl("https://www.baidu.com")
        //直接加载本地网页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()
        
        // 结合工具类
        my_web_view.webViewClient = object : WebViewClient() // 设置webViewClient
        my_web_view.webChromeClient = object : WebChromeClient()// 设置WebChromeClient

    /**
     * 返回键处理,网页中可返回上一页,不处理返回键直接退出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进行开关控制
        webSettings.javaScriptEnabled = true         
        // 适配
        webSettings.useWideViewPort = true//自适应屏幕->自动将图片调整到自适应webView 大小
        webSettings.loadWithOverviewMode = true//自适应屏幕->缩放到屏幕大小
        //缩放
        webSettings.setSupportZoom(true)//支持缩放,默认为true。
        webSettings.builtInZoomControls = true//设置是否展示内置的缩放控件,默认为false
        webSettings.displayZoomControls = true//显示原生的缩放控件

        //其他
        webSettings.allowFileAccess = true // 可访问文件
        webSettings.javaScriptCanOpenWindowsAutomatically = true // 支持js 自动打开新窗口
        webSettings.loadsImagesAutomatically = true // 支持自动加载图片
        webSettings.defaultTextEncodingName = "UTF-8" // 默认值也是UTF-8

        //缓存控制
        webSettings.domStorageEnabled = true // 开启dom缓存功能
        webSettings.databaseEnabled = true // 开启数据库缓存功能
        webSettings.setAppCacheEnabled(true)// 开启application 缓存功能
        webSettings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK //设置缓存模式                           (LOAD_CACHE_ELSE_NETWORK,有缓存时加载缓存,即使缓存过期,没有时从网络加载)
        webSettings.setAppCachePath("") // 设置app缓存目录,api已弃用。

        // 5.1以上默认禁止了https和http混用,开启如下
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
        }

    }
3、WebViewClient

协助WebView工作,有一些列回调方法,用于处理各种通知 & 请求事件等。

    my_web_view.webViewClient = object : WebViewClient() {
            //加载url、返回false 代表使用webView 加载url 不使用系统浏览器。
            override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
               // 如下loadUrl,return true 这种也代表不使用系统浏览器。但是官方建议直接 return false
              //  view?.loadUrl("https://www.baidu.com")
              //  return true
                return false// 直接return false即可
            }

            // 页面加载时回调
            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                super.onPageStarted(view, url, favicon)
            }

            // 页面加载完成时回调
            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
            }

            // 加载页面资源时调用(如页面上有好多图片,没加载一张就会回调一次)
            override fun onLoadResource(view: WebView?, url: String?) {
                super.onLoadResource(view, url)
            }

            // 加载页面时服务器出现错误(例如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);
              
                // 接受所有网站的证书,忽略SSL错误,执行访问网页。这种方式在发生ssl不会影响网页加载。
                // 但是google play 认为这是不安全的操作。会给你警告。
                handler?.proceed() 
                // handler?.cancel() // 发生ssl时挂起连接表现为白屏,默认方式。

            }
        }
4、WebChromeClient
    /**
     * WebChromeClient类:辅助webView 处理js dialog、网站icon、网站title。
     * js的各种dialog事件触发时可由webChromeClient的响应方法回调到。
     * */
    private fun webChromeClient() {
        my_web_view.webChromeClient = object : WebChromeClient() {
            // 获得网页进度时回调
            override fun onProgressChanged(view: WebView?, newProgress: Int) {
                super.onProgressChanged(view, newProgress)
            }

            // 获取网页的标题时回调
            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 调用 JS 代码

方式
  • webView的loadUrl(" javascript:js方法()")
  • webView的evaluateJavascript()
<html>
<head>
    <meta charset="UTF-8">
    <title>SunnyDay</title>
    <!--内部引入法-->
    <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>>

如上准备个1.html文件

1、webView#loadUrl 加载原理及其代码

借助webChromeClient 的各种回调处理。一般为js的各种dialog 方法触发时被安卓webViewClient的各种回调监听方法拦截消费。

        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只是载体,内容的渲染需要使用webViewChromeClient类去实现,所以在这里写回调处理。
        web_view.webChromeClient = object : WebChromeClient() {
            // 此方法可回调到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 {
            // 调用js时要保证网页加载完成,否则js代码调用失败。因为html中也是页面加载完成才响应的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)总结

/**
 * Android call js method practice
 * 两种方式:
 * 1、webView的loadUri(" javascript:js方法()")
 *    这种方式一般调用的为js的dialog方法,使用安卓的WebChromeClient 对应回调方法进行拦截处理。
 * 2、webView的evaluateJavascript
 *     直接调用js的方法,还可以获得js方法返回值回调
 *     js方法结果回调为String 类型值
 *     js方法无返回值,这里回调为null
 *
 *     建议以这种方式,既可快捷获得返回值,又可通过1中的dialog回调处理。
 *
 *     小结:Android call js method
 *          安卓调用js方法后可以在安卓端获得结果回调处理。
 * */
调用方式优点缺点适用场景
loadUrl方便简洁效率低,获取返回值麻烦不需要获取返回值时
evaluateJavascript效率高安卓4.4以上才能使用安卓4.4以上

四、Js调用安卓代码

方式
  • 通过webView的addJavascriptInterface方法
  • 通过重写webViewClient的shouldOverrideUrlLoading方法筛选url调用
  • 通过 WebChromeClient 的dialog 回调判断筛选url调用
<html>
<head>
    <meta charset="UTF-8">
    <title>SunnyDay</title>
    <!--内部引入法-->
    <script>
        //方式1:对象映射方式
        function callAndroid(){
             // 调用安卓的hello方法,由于安卓中添加了对象映射,test.hello()就相当于安卓的      
             //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 方法回调拦截 JS 对话框
        function callAndroid3(){
              //1、首先搞个输入框,触发时安卓可获得回调
              //2、收到回调后安卓处理,点击确定返回输入框值,点击取消返回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()">点我即可调用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调用安卓方法方式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的为动态定义的
                val requestUrl = request?.url
                Log.i("JsCallAndroidActivity", "" + requestUrl) //js://webview?arg1=111&arg2=222
                return if (requestUrl.toString() == "js://webview?arg1=111&arg2=222") {
                    // 符合筛选,调用安卓方法。
                    printLog()
                    true
                } else {
                    super.shouldOverrideUrlLoading(view, request)
                }
            }

        }
 private fun printLog() {
        Log.i("JsCallAndroidActivity", "android method:print log !")
    }
3、通过 WebChromeClient 的dialog 回调判断筛选url调用

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 调用了 Android 的方法")
                        // 符合筛选,调用安卓方法。
                        printLog()
                    }
                    return true
                }

                return super.onJsPrompt(view, url, message, defaultValue, result)
            }
        }
4、小结
/**
 * js call android method practise
 * 1、webView的addJavascriptInterface(自定义对象,“映射给的自定义字符串对象”)
 * 这种方式最简单,自定义对象,内部定义一系列方法供js调用。js拿到映射对象即可调用安卓自定义的对象方法
 *
 * 2、重写webViewClient的shouldOverrideUrlLoading方法,筛选请求的url是否为js规定的url,是规定的则调用安卓的相应方法。
 *
 * 3、通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt(),原理与2一致。
 * */
调用方式优点缺点适用场景
WebView.addJavascriptInterface 对象映射方便简洁Android 4.2 一下存在漏洞Android 4.2 以上相对简单的应用场景
WebViewClient.shouldOverrideUrlLoading 回调拦截不存在漏洞使用复杂,需要协议约束不需要返回值情况下
WebChormeClient.onJsAlert / onJsConfirm / onJsPrompt 方法回调拦截不存在漏洞使用复杂,需要协议约束能满足大多数场景

五、Android 内嵌网页时登录状态同步方案

1、使用 WebView 和 Cookie 同步

Android 的 WebView 是一种能在应用中显示网页的组件。WebView 会自动处理 Cookies,但为了确保登录状态的同步,可能需要手动同步应用和 WebView 的 Cookies。

(1) 获取应用中的 Cookie

如果你的应用在登录后保存了 Cookie,可以通过 CookieManager 来获取这些 Cookie。

(2) 将 Cookie 注入 WebView:

在加载网页前,将这些 Cookie 注入 WebView 的 CookieManager。

CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);

// 获取应用的 Cookie,假设名为 "appCookie"
String appCookie = "key=value; domain=yourdomain.com";
cookieManager.setCookie("yourdomain.com", appCookie);

// 加载网页
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 应用交互,保持登录状态同步。

(1)保存登录状态:
登录后,将登录状态(例如 token)保存到 Shared Preferences。

SharedPreferences sharedPref = getSharedPreferences("MyApp", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("token", "your_token");
editor.apply();

(2)设置 JavaScript 接口:
在 WebView 中设置 JavaScript 接口,用于获取登录状态。

webView.addJavascriptInterface(new Object() {
    @JavascriptInterface
    public String getToken() {
        SharedPreferences sharedPref = getSharedPreferences("MyApp", Context.MODE_PRIVATE);
        return sharedPref.getString("token", "");
    }
}, "Android");

(3)在网页中使用:
在网页的 JavaScript 中调用这个接口,获取登录状态。

function getToken() {
    return Android.getToken();
}

// 在需要时调用 getToken(),例如页面加载完成后
document.addEventListener("DOMContentLoaded", function() {
    var token = getToken();
    if (token) {
        // 使用 token 做进一步处理
    }
});

3、使用 OAuth 进行单点登录(SSO)

如果你的应用和网页都支持 OAuth,可以使用 OAuth 进行单点登录。

(1)在应用中获取 OAuth Token:
用户在应用中登录后,获取 OAuth Token 并保存。

(2)WebView 加载网页时附加 Token:
在加载网页时,将 Token 附加在 URL 或请求头中。

String url = "https://yourdomain.com?token=" + oauthToken;
webView.loadUrl(url);

// 或者设置请求头
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、使用统一的身份认证系统

如果你的应用和网页都使用统一的身份认证系统(如 Firebase Authentication),可以通过相同的身份认证机制同步登录状态。

(1)应用中登录:
使用统一的身份认证系统登录,并获取认证信息。

(2)WebView 中共享认证信息:
通过与身份认证系统的集成,在 WebView 中实现自动登录。

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相关优化建议

1、给 WebView 加一个加载进度条

为了友好展示,重写 WebChromeClient 的 onProgressChanged 方法。未加载完成时展示loading进度条

2、提高 HTML 网页加载速度,等页面 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进行开关控制。

七、收获

1、明文传输控制

Android P 阻止加载任何 http 的请求,在清单文件application节点 添加android:usesCleartextTraffic=“true”

2、Android 5.0 之后 WebView 禁止加载 http 与 https 混合内容 。这样会造成某些资源加载失败。
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 后面追加了一些参数

2、h5页面上src标签加载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") 就会出现h5 图片显示失败。

解决方案开启MixedContentMode

*/
3、硬件加速开启导致问题

比如不能打开 PDF,播放视频花屏等等。关闭硬件加速。

4、重写webViewClient的shouldOverrideUrlLoading

否则系统不知道你是想用webview打开url 还是使用系统浏览器。

5、WebView白屏问题

原因:页面进度不到100%时显示的就是白屏,进度到100时开始加载网页资源。

解决:网上方案较多这里提示一种:进度不到100时展示加载提示。

The end

官方文档

练习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/721030.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微服务中的相关概念

Eureka Eureka 是由 Netflix 开发的一个服务发现和注册中心&#xff0c;广泛应用于微服务架构中。Eureka 主要用于管理和协调分布式服务的注册和发现&#xff0c;确保各个服务之间能够方便地找到并通信。它是 Netflix OSS&#xff08;Netflix Open Source Software&#xff09…

指针和数组

同一指针相减的绝对值得到的是之间元素的个数 #include"stdio.h" #include"string.h" int main() {int arr[10]{0};printf("%d\n",&arr[9]- &arr[0]);return 0; } 不同类型的指针减去指针没有意义 地址加地址&#xff0c;指针加指针没…

UE5 C++ 跑酷游戏练习 Part1

一.修改第三人称模板的 Charactor 1.随鼠标将四处看的功能的输入注释掉。 void ARunGANCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) {// Set up action bindingsif (UEnhancedInputComponent* EnhancedInputComponent CastChecked&…

【Linux基础IO】常见的对文件操作的函数、文件描述符fd、访问文件的本质分析

目录 fopen函数 chdir函数 fclose函数 fwrite和fread函数 open函数 umask函数 write函数 read函数 close函数 文件描述符fd 进程访问文件的本质分析 fopen函数 参数mode&#xff1a; w方式打开文件&#xff1a;1、如果被打开文件不存在&#xff0c;系统会在使用fopen函…

玄机平台流量特征分析-常见攻击事

前言 熟悉常见的攻击流量特征&#xff0c;我们就可以通过主机的一个流量情况来判断主机遭受了何种攻击。这里来看看玄机平台的一道题目。 步骤1.1 这里需要我们找出恶意扫描者&#xff0c;也就是黑客的ip。下载好附件之后用wiresharke打开&#xff0c;直接筛选http协议的流量…

CSS【实战】抽屉动画

效果预览 技术要点 实现思路 元素固定布局&#xff08;fixed&#xff09;在窗口最右侧外部js 定时器改变元素的 right 属性&#xff0c;控制元素移入&#xff0c;移出 过渡动画 transition transition: 过渡的属性 过渡的持续时间 过渡时间函数 延迟时间此处改变的是 right …

C# Winform 侧边栏,切换不同页面

在项目中我们经常遇到需要在主界面上切换不同子页面的需求&#xff0c;常用做法是左侧显示子页面菜单&#xff0c;用户通过点击左侧菜单&#xff0c;实现右边子页面的展示。 实例项目实现&#xff1a; 项目左侧侧边栏实现FlowLayoutPanel使用显示不同子窗体 实例链接&#xf…

行业模板|DataEase应用平台对接大屏模板推荐

DataEase开源数据可视化分析工具于2022年6月发布模板市场&#xff08;https://templates-de.fit2cloud.com&#xff09;&#xff0c;并于2024年1月新增适用于DataEase v2版本的模板分类。模板市场旨在为DataEase用户提供专业、美观、拿来即用的大屏模板&#xff0c;方便用户根据…

利用深度学习进行纹理分析以改善计算机视觉

利用深度学习进行纹理分析以改善计算机视觉 人工智能的一个独特应用领域是帮助验证和评估材料和产品的质量。在IBM&#xff0c;我们开发了创新技术&#xff0c;利用原生移动、专用微传感器技术和AI来提供实时工作的解决方案&#xff0c;利用商用智能手机技术&#xff0c;并提供…

.NET周刊【6月第3期 2024-06-18】

国内文章 记一次 .NET某游戏币自助机后端 内存暴涨分析 https://www.cnblogs.com/huangxincheng/p/18243233 文章讨论了程序中非托管内存暴涨的问题。作者描述了友人发现内存问题并请他帮助分析的背景&#xff0c;利用WinDbg工具分析Linux平台上的内存泄漏情况。文章介绍了如…

Jenkins教程-3-github自动化测试任务构建

上一小节我们学习了Jenkins在windows和mac系统上安装搭建环境的方法&#xff0c;本小节我们讲解一下Jenkins构建github自动化测试任务的方法。 接下来我们以windows系统为例&#xff0c;讲解一下构建实际自动化测试任务的具体步骤。 安装git和github插件 点击进入Jenkins插件…

2.什么是计算机程序

什么是计算机程序? 计算机程序是为了告诉计算机"做某件事或解决某个问题"而用"计算机语言编写的命令集合(语句) 只要让计算机执行这个程序,计算机就会自动地、有条不紊地进行工作,计算机的一切操作都是由程序控制的,离开程序,计算机将一事无成 现实生活中你如…

网络安全 - DDoS 攻击原理 + 实验

DDoS 攻击 什么是 DDoS 进攻 D D o S \color{cyan}{DDoS} DDoS&#xff08;Distributed Denial of Service&#xff0c;分布式拒绝服务&#xff09;攻击是一种通过多个计算机系统同时向目标系统发送大量请求&#xff0c;消耗其资源&#xff0c;使其无法正常服务的攻击方式。DD…

经验分享,在线文本比较工具

这里分享一个在线文本比较工具&#xff0c;打开网页即用&#xff0c;很方便 网址&#xff1a; https://www.jq22.com/textDifference 截图&#xff1a;

用python实现多文件多文本替换功能

用python实现多文件多文本替换功能 今天修改单位项目代码时由于改变了一个数据结构名称&#xff0c;结果有几十个文件都要修改&#xff0c;一个个改实在太麻烦&#xff0c;又没有搜到比较靠谱的工具软件&#xff0c;于是干脆用python手撸了一个小工具&#xff0c;发现python在…

设备档案包括哪些内容

设备档案通常包括以下内容和要求&#xff1a; 1. 设备基本信息&#xff1a;包括设备名称、型号、规格、生产厂商、出厂日期、购买日期等。 2. 设备安装信息&#xff1a;包括设备的安装位置、安装日期、安装人员等。 3. 设备维护信息&#xff1a;包括设备的维护保养记录&#xf…

关于办公软件的使用

第一部分&#xff1a; 常用函数的使用 在使用的地方&#xff0c;输入SUM(B2:F2)回车 第二部分&#xff1a; 自定义函数的使用 1、打开 宏编辑 2、 自定义函数方法 3、自定义函数的使用和常用函数一样&#xff1a; 在使用的地方&#xff0c;输入计算面积(A3&#xff0c;B3)…

python学习笔记-07

python内置函数 内置函数就是python自带的函数&#xff0c;不需要我们再去定义的&#xff0c;如print等直接使用即可&#xff0c;内置函数官方文档&#xff1a;官链。 1.数学运算 #数学运算&#xff1a; print(------abs()是绝对值函数------) a-1.1 print({}的绝对值是{}.fo…

c语言---循环 、判断基础知识详解

if语句 else离最近的if语句结合。 if语句题目 //1. 判断一个数是否为奇数 //2. 输出1 - 100之间的奇数 #include <stdio.h> int main() {int n 0;scanf("%d", &n);if (n % 2){printf("奇数\n");}else{printf("不是奇数\n"…

视频太长了,想要剪切掉一节怎么操作?

如果你想为你的视频制作一个具有一定客观性的短视频&#xff0c;并在一些平台上发布&#xff0c;那么剪辑视频片段是不可避免的。通过剪辑视频片段的操作&#xff0c;提出视频中多余的视频内容&#xff0c;将自己需要的内容单独提取出来。但问题是如何操作它。对于新手来说&…