diff --git a/demo/Demo.js b/demo/Demo.js index d3cba75..829de5e 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -13,9 +13,6 @@ import ViewPagerDemo from './demos/ViewPagerDemo'; import TabBarDemo from './demos/TabBarDemo'; import MediaKitDemo from './demos/MediaKitDemo'; - - - export default class Demo extends Component { render() { return ( diff --git a/demo/demos/ButtonDemo.js b/demo/demos/ButtonDemo.js index e196496..2f8230b 100644 --- a/demo/demos/ButtonDemo.js +++ b/demo/demos/ButtonDemo.js @@ -5,35 +5,302 @@ import { TouchableHighlight, View, Text, - PixelRatio + PixelRatio, + LayoutAnimation, + ScrollView, + StyleSheet } from 'react-native'; import {Button} from 'react-native-yui'; +import DemoSection from './DemoSection'; export default class ButtonDemo extends Component { render() { + var animations = { + duration: 200, + create: { + type: LayoutAnimation.Types.linear, + property: LayoutAnimation.Properties.opacity, + }, + update: { + type: LayoutAnimation.Types.easeInEaseOut, + }, + }; + return ( - + + + + + + + + + + + + + + + + + + > + + + ); } -} \ No newline at end of file +} diff --git a/demo/demos/DemoList.js b/demo/demos/DemoList.js index dfade4f..6dc3b58 100644 --- a/demo/demos/DemoList.js +++ b/demo/demos/DemoList.js @@ -29,7 +29,7 @@ const dataSource = ds.cloneWithRowsAndSections({ }, { name: 'Button', - desc: '具有高亮变化的按钮' + desc: '可设置图片和文字的按钮' }, { name: 'ViewPager', diff --git a/demo/demos/DemoSection.js b/demo/demos/DemoSection.js index 7012349..32505d9 100644 --- a/demo/demos/DemoSection.js +++ b/demo/demos/DemoSection.js @@ -8,6 +8,9 @@ import { export default class DemoSection extends Component { render() { + + let {containerStyle} = this.props; + return ( @@ -18,7 +21,7 @@ export default class DemoSection extends Component { + style={{...containerStyle, paddingHorizontal: 5, paddingVertical: 8}}> {this.props.children} diff --git a/demo/jpg/head.jpg b/demo/jpg/head.jpg new file mode 100644 index 0000000..e6d16d3 Binary files /dev/null and b/demo/jpg/head.jpg differ diff --git a/demo/jpg/headHighLight.jpg b/demo/jpg/headHighLight.jpg new file mode 100644 index 0000000..20367ee Binary files /dev/null and b/demo/jpg/headHighLight.jpg differ diff --git a/library/Button.js b/library/Button.js index a0c9ee1..93ad675 100644 --- a/library/Button.js +++ b/library/Button.js @@ -4,65 +4,201 @@ import React, { } from 'react'; import { - Platform, View, Text, - TouchableOpacity + Image, + TouchableOpacity, + LayoutAnimation, + Dimensions, + Platform, + UIManager } from 'react-native'; +if (Platform.OS === 'android') { + UIManager.setLayoutAnimationEnabledExperimental(true) +} + +const {width, height} = Dimensions.get('window'); +const emptyView = ; + export default class Button extends Component { constructor(props) { super(props); this.state = { - active: false + active: false, + source: props.source, + isActiveImage: false + }; + } + + _getRenderStyle(style, targetStyle) { + + let isEmptyObject = true; + for (let prop in style) { + isEmptyObject = false; + break; + } + + if (!style || isEmptyObject) { + return { + height: targetStyle.height ? targetStyle.height : height, + width: targetStyle.width ? targetStyle.width : width + } + } + return style; + } + + _renderImage(imageStyle) { + + let {resizeMode, ..._imageStyle} = imageStyle; + if (!resizeMode) { + resizeMode = this.props.text ? 'contain' : 'cover'; + } + + if (this.props.source) { + return ( + + + + ); + } + else { + return (emptyView) + } + } + + _renderText(fontStyle) { + + if (this.props.text) { + + let _text = this.props.text; + + if (this.props.activeText && this.state.active) { + _text = this.props.activeText + } + + return ( + + {_text} + + ) + } else { + return (emptyView) } } render() { + + let {active} = this.state; + + let { + style, + activeStyle, + text, + activeText, + fontStyle, + activeFontStyle, + activeSource, + imageStyle, + activeImageStyle, + type, + children, + } = this.props; + let activeOpacity = 0.5; - if(this.props.activeBackgroundColor || this.props.activeFontColor) { + if (activeStyle || activeFontStyle || activeImageStyle || activeText || activeSource) { activeOpacity = 1; } - let containerStyle = { - ...this.props.style, - alignItems: 'center', - justifyContent: 'center' - } - let fontStyle = { - ...this.props.fontStyle - } + let _containerStyle = {...style}; - if(this.state.active) { - if(this.props.activeBackgroundColor) { - containerStyle.backgroundColor = this.props.activeBackgroundColor; + let _contentViewSize = this._getRenderStyle({}, style); + + let _fontStyle = {...fontStyle}; + + let _imageStyle = this._getRenderStyle(imageStyle, style); + + if (active) { + + if (activeFontStyle) { + _fontStyle = activeFontStyle; + } + if (activeImageStyle) { + _imageStyle = activeImageStyle } - if(this.props.activeFontColor) { - fontStyle.color = this.props.activeFontColor; + if (activeStyle) { + _containerStyle = activeStyle; + _contentViewSize = this._getRenderStyle({}, activeStyle); + if (!activeImageStyle && !text && !children) { + _imageStyle = this._getRenderStyle(activeImageStyle, activeStyle); + } } } + let _image = this._renderImage(_imageStyle); + let _text = this._renderText(_fontStyle); + + let front = type == 'iconLeft' || type == 'iconTop' + ? _text + : _image; + let behind = type == 'iconLeft' || type == 'iconTop' + ? _image + : _text; + + let _contentViewLayoutStyle = { + flex:1, + flexDirection: type == 'iconLeft' || type == 'iconRight' ? 'row' : 'column', + justifyContent: _containerStyle.justifyContent ? _containerStyle.justifyContent : 'center', + alignItems: _containerStyle.alignItems ? _containerStyle.alignItems : 'center', + }; + return ( this.touchOpacity = ref} onPressIn={this.onPressIn.bind(this)} onPressOut={this.onPressOut.bind(this)} activeOpacity={activeOpacity} - style={containerStyle}> - - {this.props.children} + style={{..._containerStyle,overflow:'hidden'}} + onLayout={(event) => {}} + > + + {front} + {behind} + {children} + ); } + componentWillUpdate() { + if (this.props.animated) { + LayoutAnimation.configureNext(this.props.animations); + } + } + onPressIn() { this.props.onPressIn && this.props.onPressIn(); this.setState({ active: true }); + if (this.props.activeSource) { + this.setState({ + isActiveImage:true, + source:this.props.activeSource + }); + this.forceUpdate(); + } } onPressOut() { @@ -71,5 +207,56 @@ export default class Button extends Component { this.setState({ active: false }); + if(this.state.isActiveImage) { + this.setState({ + isActiveImage:false, + source:this.props.source + }); + this.forceUpdate(); + } + } +} + +Button.propTypes = { + type: PropTypes.oneOf(['iconLeft', 'iconRight', 'iconTop', 'iconBottom']), + text: PropTypes.string, + fontStyle: PropTypes.object, + activeText: PropTypes.string, + activeFontStyle: PropTypes.object, + style: PropTypes.object, + activeStyle: PropTypes.object, + imageStyle: PropTypes.object, + activeImageStyle: PropTypes.object, + animated: PropTypes.bool, + animations: PropTypes.object, + onPressIn: PropTypes.func, + onPressOut: PropTypes.func, + source: PropTypes.oneOfType([ + PropTypes.shape({ + uri: PropTypes.string + }), + PropTypes.number + ]), + activeSource: PropTypes.oneOfType([ + PropTypes.shape({ + uri: PropTypes.string + }), + PropTypes.number + ]) +}; + +Button.defaultProps = { + animated: false, + type: 'iconBottom', + imageStyle: {}, + animations: { + duration: 200, + create: { + type: LayoutAnimation.Types.linear, + property: LayoutAnimation.Properties.opacity, + }, + update: { + type: LayoutAnimation.Types.easeInEaseOut, + } } } \ No newline at end of file