Skip to content

Commit 4ecd532

Browse files
wintmainwosys
authored andcommitted
[foundation][feat]Add webview action sample
1 parent 57aee16 commit 4ecd532

File tree

4 files changed

+273
-0
lines changed

4 files changed

+273
-0
lines changed

app-catalog/samples/foundation/src/main/AndroidManifest.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,11 @@
363363
android:name=".aidl.AidlSampleActivity"
364364
android:exported="true"
365365
android:theme="@style/Theme.AppCompat.DayNight" />
366+
367+
<activity
368+
android:name=".webview.CustomActionWebViewActivity"
369+
android:exported="true"
370+
android:theme="@style/Theme.AppCompat.DayNight" />
366371
</application>
367372

368373
</manifest>
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright 2023-2025 wintmain
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.wintmain.foundation.webview
18+
19+
import android.content.Context
20+
import android.os.Build.VERSION
21+
import android.os.Build.VERSION_CODES
22+
import android.util.AttributeSet
23+
import android.view.ActionMode
24+
import android.view.ActionMode.Callback
25+
import android.webkit.JavascriptInterface
26+
import android.webkit.WebView
27+
import androidx.core.view.get
28+
import androidx.core.view.size
29+
30+
class CustomActionWebView(
31+
context: Context,
32+
attrs: AttributeSet?,
33+
) : WebView(context, attrs) {
34+
companion object {
35+
private const val TAG = "CustomActionWebView"
36+
}
37+
38+
private var mActionMode: ActionMode? = null
39+
private var mActionList: List<String> = ArrayList()
40+
private var mActionSelectListener: ActionSelectListener? = null
41+
42+
/**
43+
* 处理item,处理点击
44+
* @param actionMode
45+
*/
46+
private fun resolveActionMode(actionMode: ActionMode?): ActionMode {
47+
if (actionMode != null) {
48+
val menu = actionMode.menu
49+
mActionMode = actionMode
50+
menu.clear()
51+
for (i in mActionList.indices) {
52+
menu.add(mActionList[i])
53+
}
54+
for (i in 0..<menu.size) {
55+
val menuItem = menu[i]
56+
menuItem.setOnMenuItemClickListener { item ->
57+
(item.title as String?)?.let { getSelectedData(it) }
58+
releaseAction()
59+
true
60+
}
61+
}
62+
}
63+
mActionMode = actionMode!!
64+
return actionMode
65+
}
66+
67+
override fun startActionMode(callback: Callback?): ActionMode {
68+
val actionMode = super.startActionMode(callback)
69+
return resolveActionMode(actionMode)
70+
}
71+
72+
override fun startActionMode(callback: Callback?, type: Int): ActionMode {
73+
val actionMode = super.startActionMode(callback, type)
74+
return resolveActionMode(actionMode)
75+
}
76+
77+
private fun releaseAction() {
78+
if (mActionMode != null) {
79+
mActionMode!!.finish()
80+
mActionMode = null
81+
}
82+
}
83+
84+
/**
85+
* 点击的时候,获取网页中选择的文本,回掉到原生中的js接口
86+
* @param title 传入点击的item文本,一起通过js返回给原生接口
87+
* IE9以下支持:document.selection   
88+
* IE9、Firefox、Safari、Chrome和Opera支持:window.getSelection()
89+
*/
90+
private fun getSelectedData(title: String) {
91+
val js = "(function getSelectedText() {" +
92+
"var txt1 =window.getSelection().getRangeAt(0).startContainer.data;" +
93+
"var txt2 =window.getSelection().toString();" +
94+
"var title = \"" + title + "\";" +
95+
"JSInterface.callback(txt1,txt2,title);" +
96+
"})()"
97+
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
98+
evaluateJavascript("javascript:$js", null)
99+
} else {
100+
loadUrl("javascript:$js")
101+
}
102+
}
103+
104+
fun linkJSInterface() {
105+
addJavascriptInterface(ActionSelectInterface(), "JSInterface")
106+
}
107+
108+
/**
109+
* 设置弹出action列表
110+
* @param actionList
111+
*/
112+
fun setActionList(actionList: MutableList<String>) {
113+
mActionList = actionList
114+
}
115+
116+
/**
117+
* 设置点击回掉
118+
* @param actionSelectListener
119+
*/
120+
fun setActionSelectListener(actionSelectListener: ActionSelectListener?) {
121+
this.mActionSelectListener = actionSelectListener
122+
}
123+
124+
/**
125+
* 隐藏消失Action
126+
*/
127+
fun dismissAction() {
128+
releaseAction()
129+
}
130+
131+
/**
132+
* js选中的回掉接口
133+
*/
134+
private inner class ActionSelectInterface {
135+
@JavascriptInterface
136+
fun callback(parentText: String?, value: String?, title: String?) {
137+
this@CustomActionWebView.mActionSelectListener?.onClick(title, value, parentText)
138+
}
139+
}
140+
}
141+
142+
interface ActionSelectListener {
143+
fun onClick(title: String?, parentText: String?, selectText: String?)
144+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2023-2025 wintmain
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.wintmain.foundation.webview
18+
19+
import android.os.Bundle
20+
import android.webkit.WebSettings.LayoutAlgorithm.SINGLE_COLUMN
21+
import android.webkit.WebViewClient
22+
import android.widget.Toast
23+
import androidx.appcompat.app.AppCompatActivity
24+
import com.google.android.catalog.framework.annotations.Sample
25+
import com.wintmain.foundation.R
26+
27+
@Sample(name = "CustomActionWebViewActivity", description = "", tags = ["webkit"])
28+
class CustomActionWebViewActivity : AppCompatActivity() {
29+
private lateinit var mWebView: CustomActionWebView
30+
31+
override fun onCreate(savedInstanceState: Bundle?) {
32+
super.onCreate(savedInstanceState)
33+
setContentView(R.layout.custom_action_webview_activity)
34+
mWebView = findViewById(R.id.webview)
35+
36+
val list: MutableList<String> = ArrayList()
37+
list.add("复制")
38+
list.add("分享")
39+
list.add("批注")
40+
//设置item
41+
mWebView.setActionList(list)
42+
43+
//链接js注入接口,使能选中返回数据
44+
mWebView.linkJSInterface()
45+
46+
//增加点击回调
47+
mWebView.setActionSelectListener(object : ActionSelectListener {
48+
override fun onClick(title: String?, parentText: String?, selectText: String?) {
49+
val info = "内容: $selectText\n段落: $parent"
50+
Toast.makeText(applicationContext, info, Toast.LENGTH_LONG).show()
51+
}
52+
})
53+
54+
// 开启 javascript 渲染
55+
val webSettings = mWebView.getSettings()
56+
57+
webSettings.javaScriptCanOpenWindowsAutomatically = true
58+
59+
//关键点
60+
webSettings.useWideViewPort = true
61+
62+
webSettings.layoutAlgorithm = SINGLE_COLUMN
63+
64+
webSettings.displayZoomControls = false
65+
66+
// 设置支持javascript脚本
67+
webSettings.javaScriptEnabled = true
68+
69+
// 允许访问文件
70+
webSettings.allowFileAccess = true
71+
72+
// 设置显示缩放按钮
73+
webSettings.builtInZoomControls = true
74+
75+
// 支持缩放
76+
webSettings.setSupportZoom(true)
77+
78+
webSettings.loadWithOverviewMode = true
79+
80+
mWebView.setWebViewClient(WebViewClient())
81+
82+
// 载入内容
83+
// mWebView.loadUrl("file:///android_asset/111.html")
84+
mWebView.loadData("qweweeeeeeeeeeqewq", "text/html", "utf-8")
85+
}
86+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ Copyright 2023-2025 wintmain
3+
~
4+
~ Licensed under the Apache License, Version 2.0 (the "License");
5+
~ you may not use this file except in compliance with the License.
6+
~ You may obtain a copy of the License at
7+
~
8+
~ https://www.apache.org/licenses/LICENSE-2.0
9+
~
10+
~ Unless required by applicable law or agreed to in writing, software
11+
~ distributed under the License is distributed on an "AS IS" BASIS,
12+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
~ See the License for the specific language governing permissions and
14+
~ limitations under the License.
15+
-->
16+
17+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
18+
android:layout_width="match_parent"
19+
android:layout_height="match_parent"
20+
xmlns:app="http://schemas.android.com/apk/res-auto">
21+
22+
<Button
23+
android:id="@+id/button"
24+
android:layout_width="match_parent"
25+
android:layout_height="wrap_content"
26+
app:layout_constraintEnd_toStartOf="parent"
27+
app:layout_constraintStart_toEndOf="parent"
28+
app:layout_constraintBottom_toTopOf="@+id/webview"
29+
android:text="Button" />
30+
31+
<com.wintmain.foundation.webview.CustomActionWebView
32+
android:id="@+id/webview"
33+
android:layout_width="match_parent"
34+
android:layout_height="wrap_content"
35+
app:layout_constraintTop_toBottomOf="@id/button">
36+
</com.wintmain.foundation.webview.CustomActionWebView>
37+
38+
</androidx.constraintlayout.widget.ConstraintLayout>

0 commit comments

Comments
 (0)