前提
RN
中似乎没有像我们iOS
一样,有比较通用,好用的HUD
库,(例如SVProgressHUD
或MBProgressHUD
),安卓中叫做TOAST
,找了一些第三方库,不是不能用,就是无法满足我的要求。
于是找到了一个react-native-lyhud
库。
react-native-lyhud库
第三方库的设计思路与应用
这个第三方库,引入了一个组件,然后将这个组件,与我们的View
根组件相关联。然后调用他。
也就是说(以下是示例代码)
import Hud from 'react-native-lyhud'
export default class Examples extends Component {
render() {
return (
<View style={styles.container}>
<Text onPress={()=>{
this.hud.show('打开')
}}
style={styles.text}>
打开!
</Text>
<Hud source={this.state.source} ref={r=>{this.hud = r}} hudType={'error'} textOnly={false}/>
</View>
)
}
}
代码说明
- 上述代码中,
Examples
是我们的根组件,里面的View
是根组件中的视图 -
<Hud />
是这个第三方组件,通过ref={r=>{this.hud = r}}
产生关联,在上面的<Text>
组件中调用他的方法this.hud.close()
这里的使用,必须将hud
放在根组件中,查看它的源码会发现,在我们按下显示HUD之后,其实他绘制了一个占满当前视图的透明View组件,中间放上HUD. 因此,若将他放在了一个子组件中,那么他绘制的背景组件,只会占满那个大小的父组件。
container: {
position: 'absolute',
left: 0,
right: 0,
top:0,
bottom:0,
alignItems: 'center',
justifyContent:'center',
padding:48,
},

图片说明
如图所示,如果我们没有讲HUD组件放在根组件内,而是放在了某个子组件内,那么他生成的
HUD View
只会占满这个子组件。也就是说,如果我们设置了backgroundTouchable = {false}
,那么只会对这个子组件启用。我们去按上面的返回
按键,仍然是可用的。
二次封装 —— 做成一个模态的HUD
这个库基本上能满足我们要的效果,但是因为他提供的props
较多,样式也不大符合我想要的SVProgressHUD
的效果,因此要做一个二次封装
设计思路
首先,将这个第三方库的HUD的样式重新封装,然后提供好以下四个方法。(这四类方法除了Alert外均带有duration —— 显示时长的参数)
- alert —— 带按键和返回事件的提示按钮
showAlert(msg)
- tip —— 不带文字提示,短暂出现的提示信息
showTipMsgWithDuration(msg, duration)
- error —— 错误提示
showErrorMsgWithDuration(msg, duration)
- loading —— 等待提示
showLoadingMsgWithDuration(msg, duration)

使用方法
import MyHUD from '../MyComponents/MyProgressHUD'
export default class PaycodeGenerator extends Component {
render() {
return (
<View style={styles.container} pointerEvents={'auto'}>
<QRView showLoading={(info,duration)=>{this.myHUD.showLoadingMsgWithDuration(info,duration)}}
showAlert={(msg)=>{this.myHUD.showAlert(msg)}}
/>
<MyHUD ref={m => {this.myHUD = m}} />
</View>
);
}
}
class QRView extends Component {
render() {
return (
<View style={styles.qrContainer}>
<Button style={{width: 20, height: 20,}} title={'qq'} onPress={()=>{this.props.showAlert('警告')}}/>
<TouchableOpacity style={styles.rechargeBtn}
onPress={() => {
this.props.showLoading('成功了吗成功了吗成功了吗成功了吗',1500);
}}>
</TouchableOpacity>
</View>
)
}
}
以上为最简的调用代码。
- 导入封装好的
MyProgressHUD
组件 - 添加依赖 ref
- 明确哪个组件可能产生
HUD
—— 这也是目前封装的方法耦合性还是太强的部分。我们必须在根组件中就指定和明确哪些子组件可能产生HUD
事件,这样产生时,子组件,利用props
将参数内容回传给根组件,产生HUD
最后一点,也是我希望有大神可以指出并帮助优化的部分。希望能真正像SVProressHUD
那样,使用一个单例就可以完成提示的弹出。
MyProgressHUD 部分的封装代码
import React, {Component} from 'react';
import {
Alert,
} from 'react-native';
import Hud from 'react-native-lyhud'
export default class MyProgressHUD extends Component {
constructor(props) {
super(props);
this.state = {hudType: 'none', textOnly: false};
}
baseShow(msg, duration) {
this.hud.show(msg);
if (duration !== 0)
this.hud.close(duration);
}
// 进度提示,当duration为0表示一直等待
showLoadingMsgWithDuration(msg, duration) {
this.setState({hudType: 'none', textOnly: false});
this.baseShow(msg, duration);
}
// 弹窗提示
showAlert(msg) {
Alert.alert(msg);
}
// 错误提示
showErrorMsgWithDuration(msg, duration) {
this.setState({hudType: 'error', textOnly: false});
this.baseShow(msg, duration);
}
// 不带图标的提示
showTipMsgWithDuration(msg, duration) {
this.setState({textOnly: true});
this.baseShow(msg, duration);
}
render() {
return (
<Hud style={{backgroundColor: '#f8f9f8',}}
textStyle={{color: 'black', textAlign: 'center', fontSize: 14, borderRadius: 10}}
backgroundTouchable={false}
hudType={this.state.hudType}
textOnly={this.state.textOnly}
ref={r => {
this.hud = r
}}
/>
);
}
}
网友评论