基于HarmonyOS API 24 React Native跨平台鸿蒙开发实战系列:Image标签图片自适应显示(一)
本文是基于HarmonyOS API 24的进行的React Native跨平台技术实战项目
React Native 跨端鸿蒙开发,行业简称 RNOH(React Native OpenHarmony),是社区 + 华为共建的适配层方案:把 Meta 的 React Native 框架完整移植到鸿蒙(HarmonyOS NEXT / OpenHarmony),让一套 React/JS/TS 代码,同时运行在Android、iOS、鸿蒙手机 / 平板 / PC多端,属于原生级跨端方案,区别于 WebView 套壳网页方案。
简单一句话:前端工程师不用学 ArkTS,用熟悉的 React 语法写业务,底层自动映射成鸿蒙 ArkUI 原生控件,打包成鸿蒙标准 hap 应用上架应用市场。
它的核心定位可以概括为:不改变 React/TypeScript 前端研发习惯,复用现有 RN 业务代码资产,依托鸿蒙系统底层接口做一层高性能中间适配层,将 JSX 组件、JS 业务逻辑映射为鸿蒙原生 ArkUI 控件,最终构建可在手机、平板、车机、智慧屏、PC 等全鸿蒙设备运行、支持上架华为应用市场的原生级应用。和 UniApp、WebView 套壳等网页类跨端方案有本质区别,RNOH 不依赖浏览器内核渲染页面,所有 UI 渲染、手势交互、视图层级全部交给鸿蒙系统原生图形引擎处理,不存在网页性能瓶颈、样式兼容偏差等问题。
兼容完整 React 生态、Hooks、JSX、RN 标准组件,前端工程师无需学习 ArkTS、ArkUI 声明式语法,仅需少量平台兼容代码即可完成多端适配;底层打通鸿蒙 NAPI、ArkUI C 底层接口,兼顾代码复用性与鸿蒙原生能力调用,核心面向存量 RN App 快速新增鸿蒙渠道,是前端团队切入鸿蒙生态最低成本的技术路线。
因为编辑额器会自动识别,通常我们只设置其中的一个,另一个会按原来图的比例显示该图,如果同时设置两个属性的话,那图片的比例就会变形,显示会片的与原来差别太的从而不美观。
Web图片只设置宽度或高度时,浏览器会根据图片的原始宽高比自动调整另一维度,以保持比例不变。以下是具体原理和实现方式:
- 原理:
比例保持:当只设置宽度或高度时,浏览器会按原始比例计算另一维度。例如,若图片原宽高比为4:3,设置宽度为400px,则高度自动调整为300px 。
- 避免变形:同时设置宽高可能导致拉伸或压缩,而单独设置可防止比例失真 。
原理分析:
这种方式虽然编写起来快速而方便,但在浏览器加载显示图片时可能会造成页面里的元素抖动或移位,造成很差的用户体验。其原因是:浏览器在遇到img标签时,会根据img标签的src属性值向服务器请求读取图片,在图片读取回来并显示之前,浏览器会在图片所在位置放置一个空白的图片占位符。
如果img标签指定了宽和高,则图片占位符的尺寸等于所指定的宽和高,但如果img标签没指定宽和高,则图片占位符默认尺寸为32像素×32像素(不同的浏览器,图片占位符的默认大小不一样),这时候如果图片周围有文字或其它内容,当图片被浏览器从服务器上读取回来并显示的时候,图片占位符就会被替换成图片,占位符的尺寸也会重新被图片的实际尺寸所替换。造成的视觉效果是:图片突然撑开了周围的文字或其它内容。这就是抖动和移位现象,所以不推荐在编写img标签时缺省宽度和高度属性。

造成扭曲或拉伸的根源在于:
图片的宽和高没有同比例缩放。好比孙悟空在变化成小鸟的时候,如果头没有相应的变小,那么就会有一个小鸟身、大鸟头。如果按等比缩放,就不会扭曲或拉伸。
所以如果指定图片列表中的图片为统一的尺寸,则还需要对列表中的图片进行一定的编辑处理,使源图片的实际尺寸与统一指定的尺寸相符,或等比相符。比如图片的统一尺寸为400×300,那么图片尺寸类似为800×600或1200×900就是等比相符。
今天来实践一下图片自适应的功能,在以前的开发中,我们经常会对一些图片如果想要自适应的话,可以定高、或者是定宽的形式来写,但是在ReactNative鸿蒙开发中,貌似不太行。
import React from 'react';
import { View, Text, Dimensions, StyleSheet, Image } from 'react-native';
//获取屏幕的宽高
const screenWidth =Math.round( Dimensions.get('window').width);
const screenHight =Math.round( Dimensions.get('window').height);
const AppStyles = StyleSheet.create({
wrap: {
width: '100%',
height: screenHight,
backgroundColor: '#85BDFF'
},
title: {
width: '100%',
height: 72,
fontFamily: 'OPPOSans, OPPOSans',
fontWeight: 'normal',
paddingTop: 50,
fontSize: 36,
color: '#304057',
lineHeight: 72,
textAlign: 'center',
fontStyle: 'normal'
},
banner: {
paddingTop: 50,
paddingRight: 32,
paddingLeft: 32,
},
bannerItem: {
paddingTop: 10,
display: 'flex',
flexDirection:'row',
alignItems: 'center',
justifyContent: 'center',
width: '50%',
}
})
function App() {
return (
<View style={AppStyles.wrap}>
<Text style={AppStyles.title}>鸿蒙ReactNative系统</Text>
<View style={AppStyles.banner}>
<View style={{display:'flex',flexDirection:'row',justifyContent:'space-between'}}>
<View style={AppStyles.bannerItem}>
<Image style={{width:27,height:27}} source={require('./images/checked.png')}></Image>
<Text style={{paddingLeft: 4}}>实时业绩便捷查询</Text>
</View>
<View style={AppStyles.bannerItem}>
<Image style={{width:27,height:27}} source={require('./images/checked.png')}></Image>
<Text style={{paddingLeft: 4}}>订单状态轻松把控</Text>
</View>
</View>
<View style={{display:'flex',flexDirection:'row',justifyContent:'space-between'}}>
<View style={AppStyles.bannerItem}>
<Image style={{width:27,height:27}} source={require('./images/checked.png')}></Image>
<Text style={{paddingLeft: 4}}>宣传数据全程管理</Text>
</View>
<View style={AppStyles.bannerItem}>
<Image style={{width:27,height:27}} source={require('./images/checked.png')}></Image>
<Text style={{paddingLeft: 4}}>海量素材一站转发</Text>
</View>
</View>
</View>
<Image style={{width:289}} source={require('./images/login-bg.png')}></Image>
</View>
);
}
export default App;

可以看到这里的图片并没有显示,说明并不能这种写法:
解决方案:
那么,现在只能来写固定值的宽与高来显示这个图片尝试一下。
安装DevEco Studio程序

选择目标安装目录:

设置环境变量,但是需要重启一下:

新建一个空白模板:

设置API为24的模板项目:
初始化项目,自动下载相关依赖:

完整代码:
import React from 'react';
import { View, Text, Dimensions, StyleSheet, Image } from 'react-native';
//获取屏幕的宽高
const screenWidth =Math.round( Dimensions.get('window').width);
const screenHight =Math.round( Dimensions.get('window').height);
const AppStyles = StyleSheet.create({
wrap: {
width: '100%',
height: screenHight,
backgroundColor: '#85BDFF'
},
title: {
width: '100%',
height: 72,
fontFamily: 'OPPOSans, OPPOSans',
fontWeight: 'normal',
paddingTop: 50,
fontSize: 36,
color: '#304057',
lineHeight: 72,
textAlign: 'center',
fontStyle: 'normal'
},
banner: {
paddingTop: 50,
paddingRight: 32,
paddingLeft: 32,
},
bannerItem: {
paddingTop: 10,
display: 'flex',
flexDirection:'row',
alignItems: 'center',
justifyContent: 'center',
width: '50%',
}
})
function App() {
return (
<View style={AppStyles.wrap}>
<Text style={AppStyles.title}>鸿蒙ReactNative系统</Text>
<View style={AppStyles.banner}>
<View style={{display:'flex',flexDirection:'row',justifyContent:'space-between'}}>
<View style={AppStyles.bannerItem}>
<Image style={{width:27,height:27}} source={require('./images/checked.png')}></Image>
<Text style={{paddingLeft: 4}}>实时业绩便捷查询</Text>
</View>
<View style={AppStyles.bannerItem}>
<Image style={{width:27,height:27}} source={require('./images/checked.png')}></Image>
<Text style={{paddingLeft: 4}}>订单状态轻松把控</Text>
</View>
</View>
<View style={{display:'flex',flexDirection:'row',justifyContent:'space-between'}}>
<View style={AppStyles.bannerItem}>
<Image style={{width:27,height:27}} source={require('./images/checked.png')}></Image>
<Text style={{paddingLeft: 4}}>宣传数据全程管理</Text>
</View>
<View style={AppStyles.bannerItem}>
<Image style={{width:27,height:27}} source={require('./images/checked.png')}></Image>
<Text style={{paddingLeft: 4}}>海量素材一站转发</Text>
</View>
</View>
</View>
<Image style={{width:289, height: 182}} source={require('./images/login-bg.png')}></Image>
</View>
);
}
export default App;

使用技巧:
无需指定图像的实际大小,也就是说,这两个值可以比实际的尺寸大一些或小一些。浏览器会自动调整图像,使其适应这个预留空间的大小。使用这种方法就可以很容易地为大图像创建其缩略图,或是放大很小的图像。但需要注意的是,浏览器还是必须要下载整个文件,不管它最终显示的尺寸到底是多大,而且,如果没有保持其原来的宽度和高度比例,图像会发生扭曲。
可以非常容易地实现对页面区域的填充,同时还可以改善文档的性能。不需要创建一个具有完整尺寸的图像,使用 height 和 width 属性把它扩展到更大的尺寸(在文档中放置一个彩色的横条)。
更多推荐




所有评论(0)