JsBridge
负责Javascript与Native之间相互通信。Js可以调用Native中的方法,Native也可以调用Javascript中的函数。
注意:Js中被Native调用的函数要暴露到window
上,不然是调用不到;Native提供给Js调用的对象也挂载到了window
上。
以Android为例,简单介绍下JsBridge
Activity
Activity 是最容易吸引用户的地方,它是一种可以包含用户界面的组件,主要用于和用户进行交互。
WebView
WebView是Activity中的一种控件,借助它我们就可以在自己的用用程序里嵌入一个浏览器,从而非常轻松地展示各种各样的网页。
Js-Native 通信
Android Studio 新建EmptyActivity项目
- 增加创建EmptyActivity项目照片
- 需要加载的主Activity应该已经在
AndroidManifest.xml
文件中配置好了,我们不需要做过多更改。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.WebViewActivity"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
- 主Activity的布局xml
../res/layout/activity_main.xml
中增加WebView控件和Button控件,采用线性布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity"
android:orientation="vertical">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/button"
android:layout_margin="8dp"
android:text="Increase Count"
></Button>
</LinearLayout>
- 增加
MyJsnterface
方法
class MyJsInterface(private val mContext:Context) {
// 获取安卓版本
@JavascriptInterface
fun getAndroidVersion ():Int {
return Build.VERSION.SDK_INT
}
// 显示 toast弹窗提示
@JavascriptInterface
fun showToast () {
Toast.makeText(mContext,"Toast from android",Toast.LENGTH_SHORT).show()
}
}
- 增加html文件,放置在
main/assets
目录下
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<label>this is a test page</label>
<label> count: <span id="count"> 0 </span></label>
<label id="version"></label>
<button onclick="printAndroidVersion()">
Click me to print android version
</button>
<button onclick="showToast()"> Click me to print a toast</button>
</body>
<script>
const printAndroidVersion = () => {
const version = Android.getAndroidVersion();
document.getElementById('version').innerText = `Android version ${version}`;
}
const showToast = () => {
Android.showToast();
}
const increaseCount = () => {
const count = document.getElementById("count").textContent;
document.getElementById("count").textContent = Number.parseInt(count) + 1;
}
</script>
</html>
- 主Activity
com.example.webviewactivity/MainActivity.kt
中新增WebView相关代码
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 获取在布局中增加的WebView控件
val webView:WebView = findViewById(R.id.webView)
// webview支持javascript脚本
webView.settings.javaScriptEnabled = true
// 当从一个网页跳转到另外一个网页时,希望目标网页仍然在当前WebView中显示,而不是打开系统浏览器
webView.webViewClient = WebViewClient()
// 允许加载本地文件
webView.settings.allowFileAccess = true
// 支持 content URL
webView.settings.allowContentAccess = true
// 加载本地 index.html 文件
webView.loadUrl("file:///android_asset/index.html")
// 将Java对象注入到webview中,在页面中可以通过第二个参数提供的名字访问到Java对象
// Android 会挂到 window对象上
webView.addJavascriptInterface(MyJsInterface(this),"Android")
// 找到Button空间添加Click事件
findViewById<Button>(R.id.button).apply {
setOnClickListener {
// 调用 index.html中提供的javascript方法,方法也需要暴露到window上
webView.loadUrl("javascript:increaseCount()")
}
}
}
}
都配置好之后,手机插到电脑上,然后点击运行按钮,会降app装到手机上,然后就能点击我们新增的按钮进行 js <=> native
通信测试了。
适配
flexible 方案
flexible 方案本质是使用rem单位进行布局。
rem
rem 大小取决于根元素的字体大小,因此 1rem 继承了根元素的
font-size
大小。
核心代码
function r() {
var width = document.documentElement.clientWidth;
var e = width / 828 * 100;
document.documentElement.style.fontSize = e + 'px';
window.addEventListener('resize', r);
}
使用方式
在828px的设计稿模式下,我们直接将设计稿给的px/100换成rem单位。
例如:828px设计稿下,元素的宽度为100px,我们可以给元素赋值为1rem
。
随着viewport
的兼容性越来越好,flexible
这种形式逐渐被抛弃。下面我们看下viewport方案。
viewport 方案
该方案即将视口宽度window.innerWidth
和视口高度window.innerHeight
平均分成100份,1vw即视口宽度的1%,1vh即视口高度的1%。
转换插件
我们不需要自己转换单位,还是在项目中写px,可以通过插件去转换。
- postcss-px-to-viewport
- postcss-px-to-viewport-8-plugin 插件作者说postcss-px-to-viewport插件使用遇到报错可以选用这个插件)
注意:这个插件对JS动态Css、内联Css样式均不生效,所以尽量在这些样式中避免
出现width、height、font-size等需要转换值的样式。
常见问题
- input 调起数字键盘
<input type="number" pattern="[0-9]*" />
- ios input无法输入
[input] {
user-select: auto;
}
- ios
font-weight: 500
加重不明显
/* 直接升级成 font-weight: 700 */ 提升加粗效果
- ios 底部安全距离
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
- 1px 边框
width: 200%;
height: 200%;
border: 1px solid #000;
transform:scale(0.5);
- 隐藏滚动条
-webkit-scrollbar {
display: none;
}
- 文字溢出效果
单行文字溢出
width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
多行文字溢出
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2; // 控制行数
-webkit-box-orient: vertical;