基于Android端CordovaLib的封装,在保留cordova原有功能的基础上,摆脱了必须继承CordovaActivity的限制,大幅提升UI的灵活度,可以像使用webview一样使用在Activity、Fragment甚至是自定义View中使用Cordova的能力。 同时,在原有的基础上提供更加丰富的事件回调,可应用于更加丰富的业务场景中。
- 解决了必须继承的Activity的问题,粒度小,可以像使用webview一样使用,适用于任何个性化的ui
- 提供了丰富的事件回调
implementation("com.xeonyu:cordova-webcontainer:1.0.7")
该方式适用于绝大部分业务场景,集成简单,兼顾ui灵活性
布局示例
<?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="com.yzq.demo.activity.WebContainerActivity">
<!--标题栏-->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/purple_200"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:titleTextColor="@color/white" />
<!--进度条-->
<ProgressBar
android:id="@+id/progressbar"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" />
<!--基于Cordova封装的web容器控件-->
<com.yzq.cordova_webcontainer.CordovaWebContainer
android:id="@+id/web_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/progressbar"
app:layout_goneMarginTop="5dp" />
<!--浮动按钮-->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/reload_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:contentDescription="刷新"
android:src="@drawable/refresh"
android:tint="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
代码示例:
/**
* @description 继承自WebcontainerActivity的使用示例
* @author yuzhiqiang ([email protected])
*/
class WebContainerActivity : CordovaWebContainerActivity() {
private lateinit var binding: ActivityWebContainerBinding
private val TAG = "WebContainerActivity"
/*布局初始化*/
override fun initContentView() {
binding = ActivityWebContainerBinding.inflate(layoutInflater)
setContentView(binding.root)
}
/*初始化Webcontainer控件*/
override fun initWebContainer(): CordovaWebContainer {
with(binding) {
webContainer.run {
/**
* 初始化webcontainer
*/
init(this@MainActivity, LOG.VERBOSE)
return binding.webContainer
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val url = "https://baidu.com/"
binding.webContainer.loadUrl(url)
binding.webContainer.setOnPageScrollChangedListener { xOffset, yOffset, oldxOffset, oldyOffset ->
Log.i(TAG, "yOffset:$yOffset,oldyOffset:$oldyOffset")
}
binding.reloadFab.setOnClickListener {
binding.webContainer.reload()
}
}
}
支持在Fragment中使用,继承CordovaWebContainerFragment
即可,api跟CordovaWebContainerActivity
一致。需要注意的是Fragment的宿主Activity需要处理下页面结果回调的方法。
宿主的Activity中重写下面两个方法,写法固定
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
currentFragment?.onActivityResult(requestCode, resultCode, data)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray,
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
currentFragment?.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
Fragment正常使用即可,示例代码
package com.yzq.demo.fragment
/**
* @description 在Fragment中使用示例
* @author yuzhiqiang ([email protected])
*/
class WebContainerFragment(val webUrl: String) : CordovaWebContainerFragment() {
private lateinit var rootView: View
private lateinit var webContainer: CordovaWebContainer
override fun initContentView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
rootView = layoutInflater.inflate(R.layout.fragment_web_container, container, false)
return rootView
}
override fun initWebContainer(): CordovaWebContainer {
webContainer = rootView.findViewById(R.id.web_container)
webContainer.init(requireActivity() as AppCompatActivity, LOG.VERBOSE)
return webContainer
}
override fun initWidget() {
if (webUrl.isNotEmpty()) {
webContainer.loadUrl(url = webUrl)
} else {
webContainer.loadUrl()
}
}
}
如果你不希望继承指定的Activity,你可以把CordovaWebContainer
作为自定义view使用。
package com.yzq.demo.activity
/**
* @description 直接使用Webcontainer控件的示例,适用于更加灵活的场景,例如你不想继承指定的Activity
* @author yuzhiqiang ([email protected])
*/
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.run {
toolbar.title = "基于Cordova的webview使用"
/*初始化*/
webContainer.init(this@MainActivity, LOG.VERBOSE)
/*加载url*/
// val url = "https://www.baidu.com/"
webContainer.loadUrl()
}
}
//固定写法
override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
super.onSaveInstanceState(outState, outPersistentState)
binding.webContainer.onSaveInstanceState(outState)
}
//固定写法
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
binding.webContainer.onActivityResult(requestCode, resultCode, data)
}
//固定写法
override fun startActivityForResult(intent: Intent, requestCode: Int, options: Bundle?) {
binding.webContainer.startActivityForResult(requestCode)
super.startActivityForResult(intent, requestCode, options)
}
//固定写法
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray,
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
binding.webContainer.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
传入Activity以及LifecycleOwner
/*初始化(必须)*/
webContainer.init(this, this)
/*必须*/
webContainer.loadUrl(url)
webContainer.addPagePbserver(PageObserver)
/*可选拦截请求 等同于shouldInterceptRequest 记得用这个*/
webContainer.webviewClient.interceptRequest { view, request, response ->
val url = request.url.toString()
Log.i(TAG, "interceptRequest:$url")
return@interceptRequest response
}
/*可选 处理准备load的url 等同于 shouldOverrideUrlLoading*/
webContainer.webviewClient.overrideUrlLoading { view, request ->
Log.i(TAG, "overrideUrlLoading:${request.url}")
request.url.toString().let {
if (it.startsWith("baidu://")) {
return@overrideUrlLoading true
}
}
return@overrideUrlLoading false
}
webContainer.setOnPageScrollChangedListener { xOffset, yOffset, oldxOffset, oldyOffset ->
Log.i(TAG, "yOffset:$yOffset,oldyOffset:$oldyOffset")
}
其他使用跟webview api一样
组件内部已经添加如下混淆
#Cordova
-keep class org.apache.cordova.**{*;}
-keep interface org.apache.cordova.**{*;}
-keep enum org.apache.cordova.**{*;}