native react 二级菜单_ReactNative学习笔记--下拉选择菜单的简单封装

ReactNative 学习笔记--封装下拉菜单

单个下拉子项

先看整体要做的效果

1.实现原理:

先做一行按钮,使我们要点击弹出菜单列表的按钮,然后计算点击的按钮所在的位置,再通过点击按钮的高度计算出要弹出列表的位置和宽度高度等,利用绝对布局在Modal组件上显示,并设置对应的效果,例如'fade',弹出的Modal覆盖整个界面,选择列表子项或者点击其他位置(Modal上)都要让Modal消失,再次点击按钮的时候,显示下拉菜单前重新计算对应按钮的位置和点击按钮对应的下拉菜单的位置,然后重新更改下拉菜单的位置和内容并显示,后面就按这个逻辑。

2.实现代码

分两步:

单个子项 SiftListItem

先看render了解整体布局

render() {

return (

{this._renderButton()}

{this._renderSiftList()}

);

}

_renderButton函数 负责按钮 showSiftList控制着是否显示SiftList

里面的item:

item:

{

title:'交易方向',

tag:0,

list:[],

}

_renderButton = ()=> {

const {item,textStyle,style}=this.props;

const {showSiftList}=this.state;

let icon = showSiftList?require('../images/icon_up.svg'):require('../images/btn_down.svg');

return (

onPress={this._onButtonPress}>

numberOfLines={1}>

{item.title}

style={{marginLeft:4}}

height={6}

source={icon}

/>

);

};

_renderSiftList负责下拉菜单绘制,可以写成ListView,如果下拉菜单的高度不大,且确定就可以用ScrollView,这里就是用的ScrollView

_renderModal = ()=> {

const {showSiftList,selectedIndex}=this.state;

const {style,item}=this.props;

if (showSiftList && this._buttonFrame) {

let frameStyle = this._calculatePosition();

return (

transparent={true}

>

{

item.list?item.list.map((sublist,i)=>{

return(

onPress={()=>this.select(i)}

key={i}

>

>

{sublist}

)

}):null}

);

}

};

计算SiftList菜单的位置

_calculatePosition = ()=> {

const {style}=this.props;

let dimensions = Dimensions.get('window');

let windowWidth = dimensions.width;

let windowHeight = dimensions.height;

let dropdownHeight = (style && StyleSheet.flatten(style).height) ||

StyleSheet.flatten(styles.dropdown).height;

let bottomSpace = windowHeight - this._buttonFrame.y - this._buttonFrame.h;

let rightSpace = windowWidth - this._buttonFrame.x;

let showInBottom = bottomSpace >= dropdownHeight || bottomSpace >= this._buttonFrame.y;

let showInLeft = rightSpace >= this._buttonFrame.x;

var style = {

height: dropdownHeight,

top: (showInBottom ? this._buttonFrame.y + this._buttonFrame.h : Math.max(0, this._buttonFrame.y - dropdownHeight))-0.5,

}

if (showInLeft) {

style.left = this._buttonFrame.x;

} else {

let dropdownWidth = (style && StyleSheet.flatten(style).width) || -1;

if (dropdownWidth !== -1) {

style.width = dropdownWidth;

}

style.right = rightSpace - this._buttonFrame.w;

}

if (this.props.adjustFrame) {

style = this.props.adjustFrame(style) || style;

}

return style;

};

子项的选中和下拉菜单的显示、隐藏方法

show = ()=> {

this._updatePosition(() => {

this.setState({

showSiftList: true,

});

});

};

hide = ()=> {

this.setState({

showSiftList: false,

});

};

select = (index)=> {

const {item,selectedCallBack}=this.props;

const {selectedIndex}=this.state;

if (index == null || item.list == null || index >= item.list.length) {

index = selectedIndex;

}

this.setState({

selectedIndex: index,

});

selectedCallBack&&selectedCallBack(index,item.tag);

this.hide();

};

获取按钮对应位置的方法

_updatePosition = (callback)=> {

if (this._button && this._button.measure) {

this._button.measure((fx, fy, width, height, px, py) => {

this._buttonFrame = {x: px, y: py, w: width, h: height};

callback && callback();

});

}

};

封装成一个组件SiftListControl

export default class SiftListControl extends Component {

static defaultProps = {

items:[

{

title:'交易方向',

tag:0,

icon:require('../images/btn_down.svg'),

list:[],

}

]

};

constructor(){

super();

this.state = {

};

}

_selectedIndex = (index,tag)=>{

const {callBack}=this.props;

callBack&&callBack(index,tag);

};

render() {

const {items,subItemStyle}=this.props;

return (

{

items.map((item,i)=>{

return(

style={{backgroundColor:'white',width:subItemStyle.width}}

item={item}

key={i}

selectedCallBack={this._selectedIndex}

>

)

})

}

);

}

}

const styles = StyleSheet.create({

listBar:{

height:32,

flexDirection:'row',

}

});

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Native中实现侧滑菜单可以使用第三方组件库,如react-native-drawer、react-native-side-menu等,也可以自己手写实现。以下是手写实现的简单示例: 1. 安装react-native-gesture-handler库 ```bash npm install react-native-gesture-handler ``` 2. 在App.js中引入GestureHandlerRootView,并在render方法中添加侧滑菜单和主页布局 ```javascript import { GestureHandlerRootView } from 'react-native-gesture-handler'; class App extends Component { constructor(props) { super(props); this.state = { isMenuOpen: false, }; } render() { return ( <GestureHandlerRootView style={{ flex: 1 }}> <View style={{ flex: 1 }}> {this.state.isMenuOpen ? <View style={{ flex: 1, backgroundColor: 'white' }}> <Text>侧滑菜单</Text> </View> : <View style={{ flex: 1, backgroundColor: 'white' }}> <Text>主页布局</Text> </View> } </View> </GestureHandlerRootView> ); } } ``` 3. 添加手势识别和动画 ```javascript import { PanGestureHandler, State } from 'react-native-gesture-handler'; class App extends Component { constructor(props) { super(props); this.state = { isMenuOpen: false, gestureState: State.UNDETERMINED, translateX: new Animated.Value(0), }; this.onGestureEvent = Animated.event( [{ nativeEvent: { translationX: this.state.translateX } }], { useNativeDriver: true } ); } onHandlerStateChange = event => { if (event.nativeEvent.oldState === State.ACTIVE) { const { translationX } = event.nativeEvent; if (translationX < -50) { this.setState({ isMenuOpen: true }); Animated.spring(this.state.translateX, { toValue: -200, useNativeDriver: true, }).start(); } else { Animated.spring(this.state.translateX, { toValue: 0, useNativeDriver: true, }).start(); } } }; render() { return ( <GestureHandlerRootView style={{ flex: 1 }}> <View style={{ flex: 1 }}> <PanGestureHandler onGestureEvent={this.onGestureEvent} onHandlerStateChange={this.onHandlerStateChange} > <Animated.View style={{ flex: 1, transform: [{ translateX: this.state.translateX }], }} > {this.state.isMenuOpen ? <View style={{ flex: 1, backgroundColor: 'white' }}> <Text>侧滑菜单</Text> </View> : <View style={{ flex: 1, backgroundColor: 'white' }}> <Text>主页布局</Text> </View> } </Animated.View> </PanGestureHandler> </View> </GestureHandlerRootView> ); } } ``` 这样就可以实现一个简单的侧滑菜单了。需要注意的是,手写实现的侧滑菜单可能会存在一些问题,如滑动冲突、性能问题等,使用第三方组件库可以避免这些问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值