安卓从零开始写一个轻量级浏览器(二)

「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战

导入腾讯的X5WebView
为什么不用系统的webview

X5内核相对于系统webview,具有下述明显优势:

  • 速度快:相比系统webview的网页打开速度有30+%的提升;
  • 省流量:使用云端优化技术使流量节省20+%;
  • 更安全:安全问题可以在24小时内修复;
  • 更稳定:经过亿级用户的使用考验,CRASH率低于0.15%;
  • 兼容好:无系统内核的碎片化问题,更少的兼容性问题;
  • 体验优:支持夜间模式、适屏排版、字体设置等浏览增强功能;
  • 功能全:在Html5、ES6上有更完整支持;
  • 更强大:集成强大的视频播放器,支持视频格式远多于系统webview;
  • 视频和文件格式的支持x5内核多于系统内核
  • 防劫持是x5内核的一大亮点

关于TBS

腾讯浏览服务是致力于优化移动端webview体验的整套解决方案。该方案由SDK、手机QQ浏览器X5内核和X5云端服务组成,解决移动端webview使用过程中出现的一切问题,优化用户的浏览体验。同时,腾讯还将持续提供后续的更新和优化,为开发者提供最新最优秀的功能和服务。

导入X5Webview

导入依赖

api 'com.tencent.tbs:tbssdk:44153'
复制代码

implementation和api的区别

implementation 类似于“praivte”,module引用implementation只应用于自身,不会传递。
api类似于“public”,其他module如果dependency该module,也可以引用到该module中的资源,会传递。

添加权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   >

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <application
        ...
        <service
            android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
            android:label="dexopt"
            android:process=":dexopt" >
        </service>
    </application>

</manifest>
复制代码

具体可看 x5快速接入 (tencent.com)

使用方法

fragment_web.xml

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.tencent.smtt.sdk.WebView
            android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
复制代码

新建一个类WebFragment

用argument传链接参数

companion object {
    private const val LOAD_URL = "load_url"
    
    fun load(url: String): WebFragment {
        return WebFragment().apply {
            arguments = bundleOf(LOAD_URL to url)

        }
    }
}
复制代码

接收参数,并表用loadUrl加载

arguments?.let { args ->
    args.getString(LOAD_URL)?.let {
        mBinding.webView.loadUrl(it)
    }
}
复制代码

配置WebSettings

val webSettings: WebSettings = mBinding.webView.settings
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { //解决网页中图片显示不出问题
    webSettings.mixedContentMode = WebSettings.LOAD_DEFAULT
}
webSettings.javaScriptEnabled = true //支持JS
webSettings.domStorageEnabled = true //支持DOM Storage
webSettings.defaultTextEncodingName = "utf-8" //设置编码格式
webSettings.pluginState = WebSettings.PluginState.ON// 支持插件
webSettings.loadsImagesAutomatically = true //支持自动加载图片
webSettings.setSupportZoom(true) //支持缩放,默认为true。是下面那个的前提。
webSettings.builtInZoomControls = true //设置内置的缩放控件。若为false,则该WebView不可缩放
webSettings.displayZoomControls = false //隐藏原生的缩放控件
webSettings.databaseEnabled = true // 数据库存储API是否可用
webSettings.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN //WebView底层布局算法
webSettings.cacheMode =
    WebSettings.LOAD_CACHE_ELSE_NETWORK //设置缓存,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。本地没有缓存时才从网络上获取
webSettings.allowFileAccess = true //设置可以访问文件
webSettings.javaScriptCanOpenWindowsAutomatically = true //支持通过JS打开新窗口

//设置自适应屏幕,两者合用
webSettings.useWideViewPort = true //将图片调整到适合WebView的大小
webSettings.loadWithOverviewMode = true // 缩放至屏幕的大小
复制代码

接着在首页HomeFragment输入搜索链接转跳到WebFragment

fragment_home.xml
搜索框+FrameLayout

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white">

        <EditText
            android:id="@+id/ed_search"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="166dp"
            android:layout_marginEnd="16dp"
            android:padding="12dp"
            android:imeOptions="actionSearch"
            android:background="@drawable/gray_rounded_shape"
            android:drawableLeft="@drawable/ic_search_gray_24dp"
            app:layout_constraintTop_toTopOf="parent" />

        <FrameLayout
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
复制代码

软键盘右下方的搜索按钮

android:imeOptions="actionSearch"
复制代码

HomeFragment

监听搜索按钮

mBinding.edSearch.setOnEditorActionListener(OnEditorActionListener { textView, actionId, keyEvent ->
   if (actionId == EditorInfo.IME_ACTION_SEARCH) {
    //点击搜索要做的操作
    toWebView()
    return@OnEditorActionListener true
   }
复制代码
false
复制代码

})

用childFragmentManager来管理WebFragment后面还涉及多窗口
```kotlin
fun toWebView(){
    childFragmentManager.commit {
        addToBackStack("HomeFragment")
        var search = "${mBinding.edSearch.text}"
        val baiduUrl = "https://www.baidu.com/s?wd=$search"
        var webFragment = WebFragment.load(baiduUrl)
        add(R.id.content, webFragment)//不能使用replace,否则每次返回都要重建
    }
}
复制代码

监听返回键返回桌面

requireActivity().onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {
        isEnabled = childFragmentManager.backStackEntryCount > 0
        if (isEnabled){
            childFragmentManager.popBackStackImmediate()
          
        }
        else requireActivity().finish()
    }
})
复制代码

ezgif.com-gif-maker (9).gif

猜你喜欢

转载自juejin.im/post/7060513024854982670