Skip to content
This repository has been archived by the owner on May 15, 2020. It is now read-only.

Commit

Permalink
1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
brentvatne committed Jul 1, 2017
0 parents commit c507a8c
Show file tree
Hide file tree
Showing 6 changed files with 1,252 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": [
"react-native-prettier"
]
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
85 changes: 85 additions & 0 deletions PlatformTouchable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'react';
import {
Platform,
TouchableNativeFeedback,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from 'react-native';

let TouchableComponent;

if (Platform.OS === 'android') {
TouchableComponent =
Platform.Version <= 20 ? TouchableOpacity : TouchableNativeFeedback;
} else {
TouchableComponent = TouchableOpacity;
}

if (TouchableComponent !== TouchableNativeFeedback) {
TouchableComponent.SelectableBackground = () => ({});
TouchableComponent.SelectableBackgroundBorderless = () => ({});
TouchableComponent.Ripple = () => ({});
TouchableComponent.canUseNativeForeground = () => false;
}

export default class PlatformTouchable extends React.Component {
static SelectableBackground = TouchableComponent.SelectableBackground;
static SelectableBackgroundBorderless = TouchableComponent.SelectableBackgroundBorderless;
static Ripple = TouchableComponent.Ripple;
static canUseNativeForeground = TouchableComponent.canUseNativeForeground;

render() {
let {
children,
style,
foreground,
background,
useForeground,
...props
} = this.props;

// Even though it works for TouchableWithoutFeedback and
// TouchableNativeFeedback with this component, we want
// the API to be the same for all components so we require
// exactly one direct child for every touchable type.
children = React.Children.only(children);

if (TouchableComponent === TouchableNativeFeedback) {
useForeground =
foreground && TouchableNativeFeedback.canUseNativeForeground();

if (foreground && background) {
console.warn(
'Specified foreground and background for Touchable, only one can be used at a time. Defaulted to foreground.'
);
}

return (
<TouchableComponent
{...props}
useForeground={useForeground}
background={(useForeground && foreground) || background}>
<View style={style}>
{children}
</View>
</TouchableComponent>
);
} else if (TouchableComponent === TouchableWithoutFeedback) {
return (
<TouchableWithoutFeedback {...props}>
<View style={style}>
{children}
</View>
</TouchableWithoutFeedback>
);
} else {
let TouchableFallback = this.props.fallback || TouchableComponent;
return (
<TouchableFallback {...props} style={style}>
{children}
</TouchableFallback>
);
}
}
}
69 changes: 69 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# `<Touchable>` (react-native-platform-touchable)

A wrapper around the various `Touchable*` components built into React Native core in order to use `TouchableNativeFeedback` whenever possible, provide an easier interface to using it, and flatten out API differences between the Touchable components.

- iOS: Defaults to `TouchableOpacity` with default `activeOpacity`.
- Android: Defaults to `TouchableNativeFeedback` with background from Android app style, unless Android API <= 20 / Android < 5.0, then defaults to `TouchableOpacity`.
- `Touchable` requires exactly one child, for example:

```javascript
// Good
<Touchable>
<Child>
<GrandChild />
<GrandChild />
</Child>
</Touchable>

// Bad
<Touchable>
<Child />
<Child />
</Touchable>
```

## Statics

- `Touchable.SelectableBackground()` - creates an object that represents android theme's default background for selectable elements
- `Touchable.SelectableBackgroundBorderless()` - creates an object that represent android theme's default background for borderless selectable elements.
- `Touchable.Ripple(color: string, borderless: boolean)` - creates an object that represents ripple drawable with specified color (as a string). If property borderless evaluates to true the ripple will render outside of the view bounds.

## props

You can use the same props as you would use on `TouchableOpacity`, `TouchableHighlight`, `TouchableNativeFeedback`, and `TouchableWithoutFeedback`. Listed below.

- `fallback` - If `TouchableNativeFeedback` is not available (on iOS and on Android API <= 20 / Android < 5.0), the component specified in this prop is used instead. Defaults to `TouchableOpacity`.

- `hitSlop` - use this! pass in an object of the format `{ top: number, left: number, right: number, bottom: bottom }`, this makes the `Touchable` easier to press by expanding the touchable area by the number of points that you specify on each side, without having to change the layout of the `Touchable`, eg: by adding padding.
- `onPress` - fired when you press (touch in, release within bounds).
- `onPressIn` - fired immediately on press in (like `onmousedown` on web)
- `onPressOut` - fired immediately on press out (like `onmouseout` on web)
- `onLongPress` - fired when you press and hold.
- `delayLongPress` - time to wait for `onLongPress` to fire.
- `delayPressIn` - time to wait for `onPressIn` to fire
- `delayPressOut` - time to wait for `onPressOut` to fire
- `disabled` - default `false`, when `true` the button is disabled.
- `onLayout` - see [onLayout documentation on View](http://facebook.github.io/react-native/releases/0.45/docs/view.html#onlayout)
- `accessibilityComponentType` - see [Accessibility guide](https://facebook.github.io/react-native/docs/accessibility.html)
- `accessibilityTraits` - see [Accessibility guide](https://facebook.github.io/react-native/docs/accessibility.html)
- `pressRetentionOffset` - see [React Native
documentation](https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html#pressretentionoffset).

### props used by TouchableOpacity (default iOS)

- `activeOpacity` - sets the opacity to animate to when touch is active.

### props used by TouchableNativeFeedback (default Android)

- `background` - customize the touch effect with `Touchable.SelectableBackground`, `SelectableBackgroundBorderless`, or `Touchable.Ripple(color: string, borderless: boolean)`.
- `foreground` - same as `background`, should be used instead of background if the `Touchable` has any images as children and you want the ripple to be rendered above the image (if the image is not opaque, `background` will not be visibl, you must use foreground)

### props used by TouchableHighlight

- `underlayColor` - the color of the background when touch is active.
- `onHideUnderlay` - fired immediately after the underlay is hidden
- `onShowUnderlay` - fired immediately after the underlay is shown

## Rounded corners on Touchables with TouchableNativeFeedback behavior

- See [this example on Snack](https://snack.expo.io/B1ENztH4-) that demonstrates how to have `Touchable` with `TouchableNativeFeedback` behavior respect rounded corners from `borderRadius`.
24 changes: 24 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "react-native-platform-touchable",
"version": "1.1.0",
"description": "Uses TouchableNativeFeedback where possible and fallback to alternatives where not.",
"main": "PlatformTouchable.js",
"scripts": {
"lint": "eslint .",
"prettier": "eslint . --fix"
},
"files": [
"PlatformTouchable.js"
],
"keywords": [
"react-native",
"exponent",
"react"
],
"author": "Brent Vatne <[email protected]>",
"license": "MIT",
"devDependencies": {
"eslint": "^4.1.1",
"eslint-config-react-native-prettier": "^1.0.1"
}
}
Loading

0 comments on commit c507a8c

Please sign in to comment.