本文介绍Fusion App2.0在本地交互和兼容性方面的提升,阐述其在混合开发中优势,如降低成本、无需服务器部署。还详细讲解加载本地H5、核心监听判断、模拟用户点击、隐藏网页滑动条、禁用浏览页长按菜单、本地H5更改网页字体等功能实现方法。
此内容由AI生成,仅用于文章内容的总结
前言
值得一提的是,Fusion App2.0相较于1.13版本,对于本地交互方面以及兼容性有质的飞跃,旧版本的交互还需要取一个网页加载过渡,这意味着我们无法将H5加载页面跳转放在本地,虽然H5布局可以放在本地,但是超链接点击会有闪烁,所以需要新建很多个相同的h5加载动画,来监听跳转。
好在新版本解决了这一问题,这让混合开发的成本大大降低,不需要服务器部署,完全本地也可以实现丝滑的交互。并且不需要去适配网页夜间模式,内置了网页夜间渲染。
下面我将详细讲解,由浅入深带你快速上手,并且提供了优化的思路与方法。
一、如何加载本地H5?
local uiManager=this.uiManager
--第1个浏览页加载本地网页,并且浏览页添加一个,地址填about:empty
activity.uiManager.currentPage.webView.loadUrl("file://"..activity.getLuaDir().."/index.html")--加载APP内部网页
--如果只有一个页面,这样就够了,如果有多个浏览页都加载本地网页看下面
--第2个浏览页加载本地网页
activity.uiManager.getFragment(1).webView.loadUrl("file://"..activity.getLuaDir().."/youxi/index2.html")
--第3个浏览页加载本地网页
activity.uiManager.getFragment(2).webView.loadUrl("file://"..activity.getLuaDir().."/guanyu/index3.html")
--第4个浏览页加载本地网页
activity.uiManager.getFragment(3).webView.loadUrl("file://"..activity.getLuaDir().."/start/index4.html")
--以此类推即可,不过一般四个就够了,需要开启离屏预加载
补充一个新方式:
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)
这个方式可以实现不需要引入html文件,将html,css甚至js全部封装进lua进行解析。
二、核心监听判断
往往来讲,我们既然用H5,基本都是当布局使用的,所以,点击H5布局能实现与原生的交互,这是最核心的问题,我的思路就是通过网页监听事件,拦截H5的超链接,实现跳转子页面以及与其他原生功能交互。
--核心网页判断
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
})
Fa2默认的监听事件可以删掉,这里是监听所有浏览页的,不论你用了几个本地H5浏览页,都可以在上边这些代码中监听,网页后退()
缺一不可。通过上述方法我们已经初步实现了网页点击与子页面的交互功能。
三、模拟用户点击
上面讲了H5去定向到原生,也就是说我们已经实现了以H5当布局时,点击布局元素实现原生的功能。
那么原生如何定向到H5呢?在一些引入外部网站时可能会用到,假设我们引入了一个我们的博客网站,但是我想让顶栏用原生框架,那么我们可以删除掉网站的原有头部顶栏元素(或者利用JS屏蔽元素)这里屏蔽要屏蔽最大的父元素。然后我们找到网站的侧滑栏按钮元素,用JS的模拟点击该元素。
可通过 document.querySelector 获取网页元素,再调用 click 方法来模拟点击。在原生Lua布局框架中调用网页,可将JavaScript代码注入到网页中执行。假设侧滑栏元素的CSS选择器为 .sidebar-toggle
:
// 获取要点击的元素
var element = document.querySelector('.sidebar-toggle');
if (element) {
// 模拟点击事件
element.click();
} else {
console.log('未找到对应的元素');
}
再举个简单的例子,比如APP我们设置了一个悬浮球,让他实现返回网页顶部。Fa中文函数模块配置了返回顶部功能,直接使用即可。
--悬浮按钮点击事件
function onFloatingActionButtonClick(v)
--TODO:onFloatingActionButtonClick
返回网页顶部()
end
--[[这里的Js应该是这个:
// 页面加载完成后执行滚动到顶部操作
window.onload = function() {
window.scrollTo(0, 0);
};
]]
不过这个中文函数自带的返回顶部是直接跳到顶部,并不是平滑动画返回顶部,要实现平滑返回,可以这样写JS:
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代码写进你的原生点击事件即可。
四、隐藏网页滑动条
我们还可以把本地网页的上下滑动条给隐藏起来,把下面CSS代码放入本地html文件的head标签内即可
<style>
html,
body {
overflow-y: hidden;
}
html {
scroll-behavior: smooth;
}
</style>
当然,这个功能使用也会有一些网站无法生效,网页可能有其他CSS规则也在设置 overflow-y
属性,且具有更高的优先级,比如内联样式或者使用了 !important
声明的样式,就会覆盖你设置的 overflow-y: hidden
。
一些框架或库也可能会动态地给 html 或 body 元素添加样式,影响滚动条的显示和页面的滑动。
还有就是如果网页内容的高度超出了视口高度,且没有设置合适的容器来限制内容的显示区域,可能会导致滚动条无法隐藏。因为浏览器为了让用户能够查看全部内容,会强制显示滚动条。
五、禁用浏览页的长按菜单
我们可以禁止本地浏览页的长按功能,无法复制和出现菜单,从而实现伪原生,你可以用lua,也可以用js实现。先来说lua代码:
--第一个浏览页禁止长按
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禁止长按选中文本:在HTML文件的 <head>
标签内的 <style>
标签中添加如下代码:
* {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
使用JavaScript禁止长按弹出菜单
document.addEventListener('contextmenu', function (e) {
e.preventDefault();
}, false);
document.addEventListener('touchstart', function (e) {
e.preventDefault();
}, { passive: false });
六、原生遮罩动画
你或许可以加入一个短暂遮罩动画函数,实现丝滑载入,配合离屏预加载谁知道你是H5?布局好看就完事了
七、本地H5更改网页字体
更改网页字体的目的是如果你的APP设置了自定义字体,那么你的网页尽可能的也需要使用相应的字体。字体不需要外链,直接读取APP内本地的字体文件即可,如果你的H5页面比较多,如果按照传统路径会增加大量的空间和重复字体文件,通过相对路径
,实现所有本地网页加载同一个目录下的文件。
路径对照表
路径写法 | 含义说明 |
---|---|
test.html | 此页面在当前页面所在目录下 |
./test.html | 此页面在当前页面所在目录下,与直接写文件名含义相同 |
/test.html | 此页面在网站根目录下 |
../test.html | 此页面在当前页面的上一级目录下 |
../../test.html | 此页面在当前页面的上一级的上一级目录下(即上两级目录下),每增加一级上级目录,就增加一个../ |
../web/test.html | 此页面在当前页面上一级目录的web子目录下 |
下面css代码放进html即可
@font-face {
font-family: 'ziti';
src: url('../../font.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
body {
font-family: 'ziti', sans-serif;
}
这个实例的路径说明一下,字体font.ttf
放在了工程根目录,这个css代码对应的html路径在子页面目录,即需要往上两级
去加载文件,也就是../../
八、去除加载进度条
--去除加载进度条
activity.uiManager.getFragment(0).webView.parent.removeViewAt(2)
--去头部留白--document.body.style.paddingTop=0--此处用的是JS
九、浏览页自定义布局三种方法
第一种
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)--调用方法
第二种
local homepagelayout=--这里写布局,有几个页面就需要添加几个空白浏览页(about:blank)
activity.uiManager.getFragment(0).view.removeAllViews().addView(loadlayout(homepagelayout))
--lua布局对应fa自带浏览页 0就是第一个浏览页(需要开启全部离屏预加载)
第三种
local layout=--这里写布局,有几个页面就需要添加几个空白浏览页(about:none)
--上面的layout和下面括号里的layout对应,添加多个请有相应的修改。
this.uiManager.getFragment(0).view.addView(loadlayout(layout))
--lua布局对应fa自带浏览页 0就是第一个浏览页
补充这个自定义布局是为了应对有多个浏览页时,例如第一个浏览页用原生布局,第二个浏览页用HTML布局等等
评论 (1)