UNPKG

nuke-touchable

Version:

可点击容器

153 lines (143 loc) 3.96 kB
/* @jsx createElement */ 'use strict'; import { createElement, findDOMNode, setNativeProps, PropTypes, Component } from 'rax'; import { isWeex, appInfo } from 'nuke-env'; import View from 'nuke-view'; import Ripples from './ripples'; import inheritStyleKeys from './inherit'; const isAndroid = appInfo.platform.toLowerCase() === 'android'; /** * Touchable * @description 可点击容器 */ class Touchable extends Component { constructor(props, context) { super(props); this.originalStyle = null; this.activeStyle = null; this.rippleEnabled = isAndroid && (props.rippleEnabled || (context.androidConfigs && context.androidConfigs.rippleEnabled)); this.touchStart = this.touchStart.bind(this); this.touchEnd = this.touchEnd.bind(this); } calculatedStyle(activeStyle) { const obj = {}; for (const k in activeStyle) { obj[`${k}:active`] = activeStyle[k]; } return obj; } findDom() { if (!this.dom) { this.dom = findDOMNode(this.refs.touch); } return this.dom; } setStyle(styleData) { // const elementStyle = this.findDom().style; setNativeProps(this.refs.touch, { style: styleData, }); // for (const styleName in styleData) { // elementStyle[styleName] = styleData[styleName]; // } } touchStart(e) { const { activeStyle, style, onTouchStart } = this.props; if (!this.originalStyle) { this.originalStyle = { ...style }; } if (!this.activeStyle) { this.activeStyle = { ...activeStyle }; } this.setStyle(Object.assign({}, style, activeStyle)); onTouchStart && onTouchStart(e); } touchEnd(e) { const { style, onTouchEnd } = this.props; this.setStyle(this.originalStyle || style); onTouchEnd && onTouchEnd(e); } getActiveColor(style) { return style['backgroundColor:active'] || null; } calcInheritStyle(customStyles) { if (!customStyles) return {}; const insideStyle = {}; inheritStyleKeys.map((item) => { if (customStyles[item]) { insideStyle[item] = customStyles[item]; } }); return insideStyle; } render() { const { style, rippleEnabled, activeStyle, onPress, ...others } = this.props; const nativeProps = { ...others, ref: 'touch', style: Object.assign({}, style, this.calculatedStyle(activeStyle)), onClick: onPress, }; if (isWeex) { if (this.rippleEnabled) { nativeProps.rippleEnabled = true; } return <View {...nativeProps} />; } const activeColor = this.getActiveColor(nativeProps.style); if (activeColor && !this.rippleEnabled) { nativeProps.onTouchStart = this.touchStart; nativeProps.onTouchEnd = this.touchEnd; } // wave happens only in clickable elements if (this.rippleEnabled && onPress) { const insideStyle = Object.assign({}, { flex: 1 }, this.calcInheritStyle(style)); if (style && style.alignItems) { delete nativeProps.style.alignItems; } return ( <Ripples {...nativeProps} color={activeColor}> <View style={insideStyle}>{this.props.children}</View> </Ripples> ); } return <View {...nativeProps}>{this.props.children}</View>; } } Touchable.contextTypes = { androidConfigs: PropTypes.any, compatibilityConfigs: PropTypes.any, }; Touchable.defaultProps = { rippleEnabled: false, onPress: null, }; Touchable.propTypes = { /** * 点击的回调 click callback */ onPress: PropTypes.func, /** * 长按的回调 long press callback */ onLongPress: PropTypes.func, /** * 样式 style */ style: PropTypes.any, /** * 手指按下时样式 style when touching */ activeStyle: PropTypes.any, /** * 是否开启水波纹效果 enable ripple in Android */ rippleEnabled: PropTypes.boolean, }; const styles = { initial: { cursor: 'pointer', }, }; export default Touchable;