nuke-touchable
Version:
可点击容器
153 lines (143 loc) • 3.96 kB
JSX
/* @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;