博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ReactNative学习笔记--下拉选择菜单的简单封装
阅读量:4086 次
发布时间:2019-05-25

本文共 5276 字,大约阅读时间需要 17 分钟。

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 (            
{item.title}
); };_renderSiftList负责下拉菜单绘制,可以写成ListView,如果下拉菜单的高度不大,且确定就可以用ScrollView,这里就是用的ScrollView_renderModal = ()=> { const {showSiftList,selectedIndex}=this.state; const {style,item}=this.props; if (showSiftList && this._buttonFrame) { let frameStyle = this._calculatePosition(); return (
{ item.list?item.list.map((sublist,i)=>{ return(
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(
) }) }
); }}const styles = StyleSheet.create({ listBar:{ height:32, flexDirection:'row', }});

下载链接:


链接:http://www.imooc.com/article/15100

转载地址:http://lueni.baihongyu.com/

你可能感兴趣的文章
什么是0长数组?
查看>>
内存对齐的规则以及作用
查看>>
100条经典C++语言笔试题目-前50题
查看>>
100条经典C++语言笔试题目-后50题
查看>>
Error D8016 '/ZI' and '/Gy-' command-line options are incompatible
查看>>
剑指offer——面试题29:数组中出现次数超过一半的数字
查看>>
剑指offer——面试题30:最小的k个数
查看>>
vs2015中c++中multiset容器定义对象时参数列表中显式调用greater无法被识别的解决办法
查看>>
STL之容器set和multiset的用法详解
查看>>
剑指offer——面试题31:连续子数组的最大和
查看>>
剑指offer——面试题32:从1到n整数中1出现的次数
查看>>
剑指offer——面试题33:把数组排成最小的数
查看>>
剑指offer——面试题34:丑数
查看>>
剑指offer——面试题35:第一次只出现一次的字符
查看>>
剑指offer——面试题36:数组中的逆序对
查看>>
剑指offer——面试题37:两个链表的第一个公共节点
查看>>
剑指offer——面试题38:数字在排序数组中出现的次数
查看>>
剑指offer——面试题39:二叉树的深度
查看>>
剑指offer——面试题40:数组中只出现一次的数字
查看>>
剑指offer——面试题41:和为s的两个数字VS和为s的连续正数序列
查看>>