文章摘要
白衣 DeepSeek

一.前言

值得一提的是,FA2.0 版本相较于之前的 1.1.3 版本,在本地交互和兼容性方面实现了极为显著的提升。在旧版本中,交互时存在一个明显的问题,即需要借助网页加载过渡。这一情况导致我们无法将 H5 加载页面跳转设置在本地。虽然 H5 布局能够放在本地,但在交互跳转过程中,页面会出现闪烁现象。为了应对这个问题,开发人员只能无奈地新建多个相同的 H5 加载动画,以此来监听跳转。

好在2.0版本成功解决了这一问题,极大地降低了混合开发的成本,无需服务器部署,仅在本地环境下就能实现流畅丝滑的交互体验。不仅如此,FA2.0还内置网页夜间渲染功能,不用耗费精力去适配网页夜间模式。

一.加载本地H5

1.单个浏览页加载

1
2
3
local uiManager=this.uiManager
--第1个浏览页加载本地网页,并且添加一个浏览页,地址填about:empty
activity.uiManager.currentPage.webView.loadUrl("file://"..activity.getLuaDir().."/index.html")--加载本地网页

2.多个浏览页加载

如果只有一个页面,可以用currentPage,也可以用getFragment(0)。多个浏览页都加载本地网页,就是下面这种:

1
2
3
4
5
6
7
8
--第1个浏览页加载本地网页
activity.uiManager.getFragment(0).webView.loadUrl("file://"..activity.getLuaDir().."/index2.html")
--第2个浏览页加载本地网页
activity.uiManager.getFragment(1).webView.loadUrl("file://"..activity.getLuaDir().."/index2.html")
--第3个浏览页加载本地网页
activity.uiManager.getFragment(2).webView.loadUrl("file://"..activity.getLuaDir().."/index3.html")
--第4个浏览页加载本地网页
activity.uiManager.getFragment(3).webView.loadUrl("file://"..activity.getLuaDir().."/index4.html")

这里0就是第一个浏览页,以此类推即可,需要全部开启离屏预加载,关于路径问题,默认是页面文件夹下的html文件,这里写了个表格,便于理解:

路径描述 路径表示
页面文件夹下的html文件(默认情况) 直接文件名(如index.html)
上一级文件夹下的文件 ../文件名(如../index.html)
上两级文件夹下的文件 ../../文件名(如../../index.html)
上一级的另一个文件夹下的文件 ../other/index.html(other为文件夹名,index.html为文件名)

3.local解析加载

这个方式可以实现不需要引入html文件,将html,css甚至js全部封装进lua进行解析,适用于代码简短、结构简单的html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
local html = [[
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.highlight-text {
color: #C0341D;
background-color: #FBE5E1;
padding: 4px;
border-radius: 4px;
}
</style>
<title>高亮文本示例</title>
</head>
<body>
<p><br>这是一个示例文本,<code class="highlight-text">高亮的文字在这里</code></p>
</body>
</html>
]]

local webView = LuaWebView(this)
webView.getSettings().setLoadWithOverviewMode(true)
webView.getSettings().setUseWideViewPort(true)

local FrameLayout = luajava.bindClass "android.widget.FrameLayout"
local Gravity = luajava.bindClass "android.view.Gravity"
local lp = FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT)
activity.addContentView(webView,lp)
--add是添加,set是覆盖
webView.loadDataWithBaseURL(nil, html, nil, nil,nil)

4.LuaWebView加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
layout=--全屏框架
{
LinearLayout;--线性控件
orientation='vertical';--布局方向
layout_width='fill';--布局宽度
layout_height='fill';--布局高度
{
LuaWebView;--浏览器控件
layout_marginTop=状态栏高度(),
layout_width='fill';--浏览器宽度
layout_height='fill';--浏览器高度
id='webView';--控件ID
};

}
activity.setContentView(loadlayout(layout))

webView.loadUrl("file://"..activity.getLuaDir().."/index2.html")--加载本地文件

二.核心监听拦截

往往来讲,我们既然用H5,基本都是当布局使用的,所以,点击H5布局能实现与原生的交互,这是最核心的问题,我的思路就是通过网页监听事件,拦截H5的超链接,实现跳转子页面以及与其他原生功能交互。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
--核心网页判断
import "net.fusionapp.core.ui.fragment.WebInterface"
import "androidx.viewpager.widget.ViewPager$OnPageChangeListener"
local uiManager=this.uiManager
local viewPager=uiManager.viewPager
local pagerAdapter=uiManager.pagerAdapter
local pagerCount=pagerAdapter.getCount()
function webInterface()
for i = 0,pagerCount-1,1 do
local fragment=uiManager.getFragment(i)
if fragment then
fragment.setWebInterface(WebInterface{onPageFinished=function(view,url)
--页面加载结束事件,这个后退不能去掉,一直带着就可以
网页后退()
end,
onPageStarted=function(view,url,favicon)
--页面开始加载事件,思路就是你点击后可以拦截,直接进入你想要的子页面
--也可以进行其他事件,不一定是进入子页面,自由发挥即可
if url:find("这里填写你的h5布局元素的超链接") then
网页后退()
进入子页面("start")

return false
end

if url:find("这里填写超链接") then
网页后退()
进入子页面("login")
return false
end
end,
onReceivedTitle=function(view,title)
--获取到网页标题时加载的事件
end,
onLoadResource=function(view,url)
--页面资源加载监听
--可通过该方法获取网页上的资源
end,
onUrlLoad=function(view,url)

--即将开始加载事件,url参数是即将加载的url
--该函数返回一个布尔值
--返回true则拦截本次加载
return false
end,
onReceivedSslError=function(view, sslErrorHandler, sslError)
--ssl证书错误处理事件
--需自行处理,请返回true拦截原事件
return false
end
})
end
end
end
webInterface()
viewPager.setOnPageChangeListener(OnPageChangeListener{
onPageSelected=function(n)
webInterface()
end
})

注意,超链接拦截方法是目前来讲最简单且最实用的方法,超链接要满足以下需求:

  • 链接可以打开
  • 打开速度得慢一点,前期加载空白
  • 链接地址前缀统一,方便管理

那满足以上需求的最完美的地址是什么呢?我苦思冥想,百般尝试,终于找到了一个完美方案:
直接使用https://github用户名.github.io/后边你随便写.html

这样写的好处是GitHub本就是国外网站,加载自然慢一些,而且我们的超链接要求一定是能打开的,如果打不开,拦截就会闪烁网页加载失败的页面。虽然GitHub的后边名称不存在,但是Github默认不存在的都会定向到一个提示页面,由此我们可以随便填写以满足不同点击事件的拦截。效果搭配以上代码就是完美衔接跳转,根本看不到中间加载过渡。

这里是监听所有浏览页的,不论你用了几个本地H5浏览页,都可以在上边这些代码中监听,**网页后退()**不要随意删除。通过上述方法我们已经实现了网页点击与原生层的交互功能。

三.模拟用户点击

上面讲了H5去定向到原生,也就是说我们已经实现了以H5当布局时,点击布局元素实现原生的功能。

那么原生如何定向到H5呢?在一些引入外部网站时可能会用到,假设我们引入了一个我们的博客网站,但是我想让顶栏用原生框架,那么我们可以删除掉网站的原有头部顶栏元素(或者利用JS屏蔽元素)这里屏蔽要屏蔽最大的父元素。然后我们找到网站的侧滑栏按钮元素,用JS的模拟点击该元素。

可通过 document.querySelector 获取网页元素,再调用 click 方法来模拟点击。在原生Lua布局框架中调用网页,可将JavaScript代码注入到网页中执行。假设侧滑栏元素的CSS选择器为 .sidebar-toggle 

1
2
3
4
5
6
7
8
// 获取要点击的元素
var element = document.querySelector('.sidebar-toggle');
if (element) {
// 模拟点击事件
element.click();
} else {
console.log('未找到对应的元素');
}

再举个简单的例子,比如APP我们设置了一个悬浮球,让他实现返回网页顶部。Fa中文函数模块配置了返回顶部功能,直接使用即可。

1
2
3
4
5
6
7
8
9
10
11
12
--悬浮按钮点击事件
function onFloatingActionButtonClick(v)
--TODO:onFloatingActionButtonClick
返回网页顶部()
end

--[[这里的Js应该是这个:
// 页面加载完成后执行滚动到顶部操作
window.onload = function() {
window.scrollTo(0, 0);
};
]]

不过这个中文函数自带的返回顶部是直接跳到顶部,并不是平滑动画返回顶部,要实现平滑返回,可以这样写JS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
window.onload = function() {
const duration = 500; // 滚动动画持续时间,单位毫秒
const start = window.pageYOffset;
const startTime = performance.now();

function easeInOutQuad(t) {
return t < 0.5? 2 * t * t : -1 + (4 - 2 * t) * t;
}

function animateScroll() {
const currentTime = performance.now();
const timeElapsed = currentTime - startTime;
const scrollAmount = start * easeInOutQuad(timeElapsed / duration);

window.scrollBy(0, -scrollAmount);

if (timeElapsed < duration) {
requestAnimationFrame(animateScroll);
} else {
window.scrollTo(0, 0);
}
}

requestAnimationFrame(animateScroll);
};

总之,就是利用JS模拟用户点击,点击html中指定元素,并将这个加载JS代码写进你的原生点击事件即可。

四.伪原生的实现

1.隐藏网页滑动条

我们还可以把本地网页的上下滑动条给隐藏起来,把下面CSS代码放入本地html文件的head标签内

1
2
3
4
5
6
7
8
9
<style>
html,
body {
overflow-y: hidden;
}
html {
scroll-behavior: smooth;
}
</style>

如果上述CSS不生效,那就需要webView进行控制了:

1
2
3
4
webView.getSettings().setSupportZoom(false); --禁止网页缩放
webView.getSettings().setBuiltInZoomControls(false); --禁止缩放
webView.getSettings().setDisplayZoomControls(false); --隐藏自带的右下角缩放控件
webView.setVerticalScrollBarEnabled(false)--隐藏垂直滚动条

注意,上述代码如果是在自带的浏览页进行,直接添加会报错,需要先获取:

1
2
3
4
local WebChromeClient = luajava.bindClass "android.webkit.WebChromeClient"
local WebViewClient = luajava.bindClass "android.webkit.WebViewClient"
local uiManager=activity.getUiManager()
local webView=uiManager.getCurrentFragment().getWebView()

2.禁用浏览页长按菜单

我们可以禁止本地浏览页的长按功能,无法复制和出现菜单,从而实现伪原生,你可以用lua,也可以用js实现。先来说lua代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
--第一个浏览页禁止长按
local fragment=uiManager.currentFragment
fragment.setMenuInterface(luajava.bindClass"net.fusionapp.core.ui.fragment.WebViewMenuSupport".Interface{
--显示浏览器菜单时,会经过这个方法
--你可以通过这个方法自定义浏览器菜单
--或者禁用浏览器菜单事件
onMenuItemCreate=function(list)
--添加一项
list.add("白衣")
--删除一项
--list.remove("复制链接")
--如果删除下面的return语句,则浏览器没有长按菜单
-- return list
end,

})

--第二个浏览页禁止长按
local fragment=uiManager.getFragment(1)
fragment.setMenuInterface(luajava.bindClass"net.fusionapp.core.ui.fragment.WebViewMenuSupport".Interface{
onMenuItemCreate=function(list)
--添加一项
list.add("白衣")
--删除一项
--list.remove("复制链接")
--如果删除下面的return语句,则浏览器没有长按菜单
-- return list
end,
})

另一种方法是使用CSS禁止长按选中文本,使用JavaScript禁止长按弹出菜单:

1
2
3
4
5
6
7
8
* {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
1
2
3
4
5
6
7
document.addEventListener('contextmenu', function (e) {
e.preventDefault();
}, false);

document.addEventListener('touchstart', function (e) {
e.preventDefault();
}, { passive: false });

3.隐藏加载进度条

隐藏加载进度条,你可以将进度条颜色设置为透明色,也可以直接用下面代码移除,这种仅适用于FA2

1
2
3
--去除加载进度条
activity.uiManager.getFragment(0).webView.parent.removeViewAt(2)
--去头部留白--document.body.style.paddingTop=0--此处用的是JS

自定义浏览器布局的需要使用以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
local webSettings = mLuaWebView.getSettings();
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);

--// 开启js支持
webSettings.setJavaScriptEnabled(true);


-- 添加以下设置 WebChromeClient 的代码
local WebChromeClient = luajava.bindClass "android.webkit.WebChromeClient"
mLuaWebView.setWebChromeClient(luajava.override(WebChromeClient, {
onProgressChanged = function(view, newProgress)
-- 不做任何与进度条相关的操作,从而不显示默认进度条
end
}))

4.移除默认点击框

有些网页会有默认的点击反馈色块,我们需要删除它:

1
2
3
4
5
6
7
8
9
10
11
12
*:focus {
outline: none;
}

button:focus {
background-color: #e0e0e0;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
}

body {
-webkit-tap-highlight-color: transparent;
}

5.强制删除状态栏

这个是强制删除状态栏,有些沉浸和隐藏仍然还是会有小黑条的,如果需要删除,我们使用以下代码:

1
2
3
4
5
6
7
8
local window=activity.getWindow()
--适配屏幕
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS).addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
--去除空白 (删除状态栏后 Android11+)
window.getAttributes().layoutInDisplayCutoutMode=1
--删除状态栏
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

6.遮罩动画函数

我们可以插入一个遮罩动画,再配合离屏预加载,就可以完美无延迟载入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
--[[
本模板由 壹影(JsHD调试器开发者)制作
]]
--[[
在Fa2里面设置状态栏+顶栏渐变比较奇怪
特别注意:需要打开侧边栏才可以设置渐变哦~
建议关闭原有的悬浮球
]]
-- ****默认导入包****
require "import"
import "android.os.*"
import "android.widget.*"
import "android.view.*"
-- ****不需要请删除****
--遮罩需要引入
import "android.graphics.Color"
local uiManager=this.uiManager
local appBar=uiManager.appBarLayout--状态栏部分
local appfab=uiManager.FloatingActionButton
--侧滑=activity.findViewById(0x7f0900de)
local appdrv=uiManager.getDrawerRecyclerView()
local viewPager=uiManager.viewPager--主题部分viewPager(0)
--local webView=uiManager.getCurrentFragment().getWebView()
local toolbar=uiManager.toolbar--顶栏
import "android.graphics.drawable.GradientDrawable"
function 渐变(left_jb,right_jb,id)
drawable = GradientDrawable(GradientDrawable.Orientation.TR_BL,{
right_jb,--右色
left_jb,--左色
});
id.setBackgroundDrawable(drawable)
end

渐变(0xFFFF6845,0xFFFF2317,appBar)--渐变
--调用渐变函数

-------遮罩动画---------

function 遮罩函数()
require"import"
import "net.fusionapp.core.ui.fragment.WebInterface"
local uimanager=activity.uiManager
local fragment=uimanager.currentFragment
layout={
FrameLayout,
layout_width="fill",
layout_height="fill",
--你的界面布局
--帧动画布局1
{
LinearLayout,
orientation="vertical",
layout_width="fill",
layout_height="fill",
background="#ff1d8ae7";
id="qdy";
},
{
LinearLayout,
orientation="vertical",
layout_width="fill",
layout_height="fill",
background="#ff1d8ae7",
gravity="center",
id="qdt",
{
LinearLayout;
orientation='vertical';--重力属性
layout_width='fill';--布局宽度
layout_height='fill';--布局高度
gravity='center';--默认居中
id="进度条布局";
{
ProgressBar;--默认圆圈
id="进度条";
};
{
TextView;--文本控件
layout_width='fill';--文本宽度
layout_height='50dp';--文本高度
id="qdwb";
gravity='center';--重力属性
textColor='#ffffff';--文字颜色
text="JsHD调试器";--显示的文字
textSize='18sp';--文字大小
};

{
TextView;--文本控件
layout_width='fill';--文本宽度
id="qdwb_1";
gravity='center';--重力属性
textColor='#ffffff';--文字颜色
text="JavaScript HTML DOM手机可视化调试器";--显示的文字
textSize='9sp';--文字大小
};
};

},

{
FrameLayout,--帧布局
layout_width="fill",
layout_height="fill",
{
TextView;--文本控件
layout_width='fill';--文本宽度
layout_height='fill';--文本高度
layout_marginBottom="15dp";
gravity="center|bottom";--重力属性
textColor='#ffffff';--文字颜色
id="版权";
text='Copyright©Yyge.AllRights Reserved';--显示的文字
textSize='10sp';--文字大小

};
};--帧布局
}

--activity.setContentView(loadlayout(layout))--存到破服务器一并搜索
viewPager.getParent().getParent().addView(loadlayout(layout))
function CircleButton(view,InsideColor,radiu)
drawable = GradientDrawable()
drawable.setShape(GradientDrawable.RECTANGLE)
drawable.setColor(InsideColor)
drawable.setCornerRadii({radiu,radiu,radiu,radiu,radiu,radiu,radiu,radiu});
view.setBackgroundDrawable(drawable)
end

--状态栏,导航栏背景
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS).setStatusBarColor(0xff1d8ae7);
activity.getWindow().setNavigationBarColor(Color.parseColor("#ff1d8ae7"));

--dialog1.getWindow().setBackgroundDrawable(ColorDrawable(0x00000000));
import "android.graphics.PorterDuffColorFilter"
import "android.graphics.PorterDuff"
进度条.IndeterminateDrawable.setColorFilter(PorterDuffColorFilter(0xffffffff,PorterDuff.Mode.SRC_ATOP))

function 退出动画()
import "android.view.animation.*"--animation动画
import "android.view.animation.AccelerateInterpolator"
import "android.view.animation.RotateAnimation"--插值器
import "android.view.animation.Animation"
import "android.view.animation.Animation$AnimationListener"--动画监听
-- AccelerateInterpolator 先减速后加速
-- AnticipateInterpolator 动画开始之前有回弹效果
-- BounceInterpolator 结束回弹效果
-- CycleInterpolator 跳一跳效果
-- OvershootInterpolator 动画结束时向前弹一定距离再回到原来位置
-- AccelerateDecelerateInterpolator 系统默认的动画效果,先加速后减速
-- AnticipateOvershootInterpolator 开始之前向前甩,结束的时候向后甩
-- DecelerateInterpolator 开始加速再减速

task(1000,function()
揭露动画一 = ViewAnimationUtils.createCircularReveal(qdt,activity.getWidth(),0,Math.hypot(activity.getWidth(),activity.getHeight())/2,0);
揭露动画一.setDuration(1000)--设置动画时间
揭露动画一.start()--开始动画
揭露动画二 = ViewAnimationUtils.createCircularReveal(qdy,0,activity.getHeight(),Math.hypot(activity.getWidth(),activity.getHeight())/2,0);
揭露动画二.setDuration(1000)--设置动画时间
揭露动画二.start()--开始动画
--动画参考.setVisibility(8)
版权.setVisibility(0)

--参考动画
animationSet = AnimationSet(true)--定义动画变量,使用AnimationSet类,使该动画可加载多种动画
leave_dh1= AlphaAnimation(1,0);--渐变动画
leave_dh1.setDuration(1000);--动画时长
leave_dh1.setFillAfter(true);--动画终止时停留在最后一帧
animationSet.addAnimation(leave_dh1);--添加动画

版权.clearAnimation();--这个不可以删 用于整合两个动画二次播放动画
版权.setAnimation(animationSet);--id控件加载动画

animationSet.setAnimationListener(AnimationListener{--动画监听
onAnimationStart=function()--animationSet动画开始时执行
end,
onAnimationEnd=function()--animationSet动画结束时执行
qdt.setVisibility(8)
qdy.setVisibility(8)
版权.setVisibility(8)
--q.setVisibility(8)
end
})
end)
end--揭露动画--退出动画结束

渐变(0xFFFF6845,0xFFFF2317,qdy)
渐变(0xFFFF6845,0xFFFF2317,qdt)

进度条布局.setVisibility(View.VISIBLE)--显示控件
-- 进度条.IndeterminateDrawable.setColorFilter(PorterDuffColorFilter(0xffffff,PorterDuff.Mode.SRC_ATOP))
function 强制输入框(标题,消息,积极按钮名称)
对话框()
.设置标题(标题)
.设置消息(消息)
.设置积极按钮(积极按钮名称,function()
loadstring([[return (canoffline or 退出程序())]])()
end)
.setCancelable(false)--禁用返回键
.显示()
end
退出动画()
end

-------遮罩动画---------
遮罩函数()

五.本地更改网页字体

更改网页字体的目的是如果你的APP设置了自定义字体,那么你的网页尽可能的也需要使用相应的字体。字体不需要外链,直接读取APP内本地的字体文件即可,如果你的H5页面比较多,如果按照传统路径会增加大量的空间和重复字体文件,通过相对路径,实现所有本地网页加载同一个目录下的文件。

路径写法 含义说明
test.html 此页面在当前页面所在目录下
./test.html 此页面在当前页面所在目录下,与直接写文件名含义相同
/test.html 此页面在网站根目录下
../test.html 此页面在当前页面的上一级目录下
../../test.html 此页面在当前页面的上一级的上一级目录下(即上两级目录下),每增加一级上级目录,就增加一个../
../web/test.html 此页面在当前页面上一级目录的web子目录下

下面css代码放进html即可,这个实例的路径说明一下,字体font.ttf放在了工程根目录,这个css代码对应的html路径在子页面目录,即需要往上两级去加载文件,也就是../../

1
2
3
4
5
6
7
8
9
10
@font-face {
font-family: 'ziti';
src: url('../../font.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}

body {
font-family: 'ziti', sans-serif;
}

六.浏览页自定义布局

1.第一种

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function setContentView(h)
local args={h}
local list=table.clone(args)
table.foreach(list,function(k,v)
list[k]=luajava.instanceof(v,View)and v or loadlayout(v)--加载布局
local webView=this.uiManager.getFragment(k-1).webView--获取浏览器控件( k-1 是网页的页面,可以自己改,注意不能没有浏览页)
webView.setVisibility(8)--隐藏浏览器控件
webView.parent.addView(list[k])--设置布局
end)
end

layout={
LinearLayout,
layout_width=-1,
layout_height=-1,
gravity="center",
{
Button,
},
}

setContentView(layout)--调用方法

2.第二种

1
2
3
local layout=--这里写布局,有几个页面就需要添加几个空白浏览页(about:blank)
activity.uiManager.getFragment(0).view.removeAllViews().addView(loadlayout(layout))
--lua布局对应fa自带浏览页 0就是第一个浏览页(需要开启全部离屏预加载)

3.第三种

1
2
3
4
local layout=--这里写布局,有几个页面就需要添加几个空白浏览页(about:none)
--上面的layout和下面括号里的layout对应,添加多个请有相应的修改。
this.uiManager.getFragment(0).view.addView(loadlayout(layout))
--lua布局对应fa自带浏览页 0就是第一个浏览页

补充这个自定义布局是为了应对有多个浏览页时,例如第一个浏览页用原生布局,第二个浏览页用HTML布局等等