Code Monkey home page Code Monkey logo

react-native-swipeable's Introduction

React Native Swipeable NPM version

A powerful React Native swipe component. Supports both iOS and Android.

Installation

npm i --save react-native-swipeable

Usage

Wrap your ListView/TableView items with the Swipeable component:

import Swipeable from 'react-native-swipeable';

const leftContent = <Text>Pull to activate</Text>;

const rightButtons = [
  <TouchableHighlight><Text>Button 1</Text></TouchableHighlight>,
  <TouchableHighlight><Text>Button 2</Text></TouchableHighlight>
];

function MyListItem() {
  return (
    <Swipeable leftContent={leftContent} rightButtons={rightButtons}>
      <Text>My swipeable content</Text>
    </Swipeable>
  );
}

Props

prop type default description
children renderable null swipeable content
leftContent renderable null (optional) left content visible during pull action
rightContent renderable null (optional) right content visible during pull action
leftButtons renderable[] null (optional) array of buttons, first being the innermost; ignored if leftContent present
rightButtons renderable[] null (optional) array of buttons, first being the innermost; ignored if rightContent present
leftActionActivationDistance integer 125 (optional) minimum swipe distance to activate left action
onLeftActionRelease function null (optional) user has swiped beyond leftActionActivationDistance and released
rightActionActivationDistance integer 125 (optional) minimum swipe distance to activate right action
onRightActionRelease function null (optional) user has swiped beyond rightActionActivationDistance and released
leftButtonWidth integer 75 (optional) resting visible peek of each left button after buttons are swiped open
rightButtonWidth integer 75 (optional) resting visible peek of each right button after buttons are swiped open
onRef function null (optional) receive swipeable component instance reference
onPanAnimatedValueRef function null (optional) receive swipeable pan Animated.ValueXY reference for upstream animations

Advanced Props

Check out the Swipeable component's propTypes for a huge list of options including animation lifecycle hooks and low-level overrides.

Instance Methods

recenter()

Imperatively reset swipeable component back to initial position. This is useful if buttons are exposed and the user has begun scrolling the parent view.

class MyListItem extends Component {

  swipeable = null;

  handleUserBeganScrollingParentView() {
    this.swipeable.recenter();
  }

  render() {
    return (
      <Swipeable onRef={ref => this.swipeable = ref} rightButtons={rightButtons}>
        <Text>My swipeable content</Text>
      </Swipeable>
    );
  }
}

Example

To run the example:

npm run build
cd example
npm install
react-native run-ios # or run-android

Common Issues

Action being triggered more than once (#3)

This seems to occur occasionally (but not always) with certain ScrollView and ListView configurations. The fix is simple though, just ensure that scrollEnabled is set to false while the user is swiping a row.

<ScrollView scrollEnabled={!this.state.isSwiping}>
  <Swipeable
    onSwipeStart={() => this.setState({isSwiping: true})}
    onSwipeRelease={() => this.setState({isSwiping: false})}
  </Swipeable>
</ScrollView>

or:

<ListView
  scrollEnabled={!this.state.isSwiping}
  renderRow={() => (
    <Swipeable
      onSwipeStart={() => this.setState({isSwiping: true})}
      onSwipeRelease={() => this.setState({isSwiping: false})}
    </Swipeable>
  )}
/>

License

MIT

react-native-swipeable's People

Contributors

cedricboidin avatar denis-shvets avatar francoisdebellescize avatar jshanson7 avatar rdourado avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-swipeable's Issues

Question: how to use the onPanAnimatedValueRef prop?

Hello,

I want to use the onPanAnimatedValueRef prop to add some animation to the right content:

onPanAnimatedValueRef={(pan) => { 
    pan.addListener(val => {
        // change the style of the right content
    })
}}

But I'm not sure how to change the style from the listener method. Any ideas?

Buttons Not Tapable

We have the Swipeable component inside of a FlatList, and we just recently updated to React Native 0.51, and now the implemented right buttons have very inconsistent tap registry. The taps will register about 20% of the time, with triggering behaviors also inconsistent.

I believe that it has something to do with the nested TouchableHighlights, but I'm still investigating.

This seems like a relevant issue, and I'm going to attempt to implement some solutions found in the thread.
facebook/react-native#3082

Thanks

Key issues when using FlatList

When trying to render swipeable in FlatList component, i get the following error:

ExceptionsManager.js:71 Warning: Each child in an array or iterator should have a unique "key" prop.

Check the render method of Swipeable. It was passed a child from DiscogsSearch. See https://fb.me/react-warning-keys for more information.

Is Swipeable compatible with Flatlist?

Also the swipe actions fire multiple times on one swipe, but i'm not sure if that is a related issue.

cannot read property 'style' of undefined

error comes out right after npm install

index.js: 606:36

style: _reactNative.ViewPropTypes.style,

anyone have workaround on this ?
react-native-cli: 2.0.1
react-native: 0.42.0

Is it possible to expand instead of retract on onLeftActionRelease?

Hi, do you have any tips to continue the animation of fully expanding the cell in addition to changing it's background color (or even it's content) when the user has swiped beyond the action distance and releases the cell, instead of retracting back to the original position, this gives feedback to the user as a confirmation that the action was executed.

Use Pull and Button at the same time

Hello guys, I want that my action can be triggered by both click on button and Pull. It works fine but sometimes when I pulled the component the action is trigerred but my component does not close well, it stay stuck a the button level (have to close it manually).

Am I the only one that has this issue ? Is there any solution ?

Thanks !

Swipeable as a FlatList item has left and right content way off the viewable area

I have a <FlatList style={{ flex: 1, margin: 8 }} /> where all my items have a top-level element of <Swipeable style={{ flex: 1, marginBottom: 4 }} leftButtons={[ <Button key="delete" title="Delete" /> ]}>{ /* ... */ }</Swipeable>.

When I swipe left to right, the swipeable state works (content is pulled to the right and stays), but I can't see the button. When I pull to the right as far as I can go, I can see the button way off the visible area.

I'm using react native 0.44.0 and node 5.8.0, and currently testing against iPHone 6/iOS 10.2 on my xcode simulator.

Is this an issue with my styling, my react native version, or this component library?

Buttons not visible on Android

screen shot 2017-01-18 at 13 40 38

Everything appears to render correctly in the right position, but it seems like something clipping and preventing the buttons from being visible. I'm using a ListView and Swipeable is the root of renderRow.

I dug through the 0.3.2 diff in hopes of finding a clue, but I got nothing. Any ideas?

Does recenter() work with RN 0.49?

I cannot for some reason get the recenter() to fire or do anything.

this.swipeable = null;

const rightButtons = [<TouchableOpacity onPress={() => this.swipeable.recenter()}><Text>Recenter Me</Text></TouchableOpacity>]

<Swipeable onRef={ref => this.swipeable = ref} rightButtons={rightButtons}> ... <Swipeable/>

Any ideas why this would not work? Does onRef actually work with RN0.49? Anyone on RN0.49 that has this Swipeable recenter() working?

Action is being triggered more than once

                leftContent={leftContent}
                rightContent={rightContent}
                onRightActionComplete={() => {
                    console.log("Right Action Complete");
                }}
                onLeftActionComplete={() => {
                    console.log("Left Action Complete");
                }}

When playing swiping and swiping back while holding the swipeable action open, the action triggers countless times.

When swiping quickly, action triggers twice.

Also, this warning sometimes appear:

Possible Unhandled Promise Rejection (id: 13):

Styling button quirks : Centering text, applying a margin

I cannot:

  1. Center the text on a button. The default keeps it to the left. When I apply traditional centering styles, the text disappears. As a hack, I have to use multiple "ย "
  2. Apply a margin so that there is space between buttons. The top and bottom margin will work, but the buttons always flex fully left and right and cannot be separated from each other.

Maximum threshold the row can be swiped

Currently the swipeable element can be swiped without any restriction. Can the horizontal pan have a threshold value such that the user can't swipe beyond a threshold value?

onPress action

Hello,
I would like to be able to capture the simple onPress or onLongPress on this component. Wrapping it up inside a touchable breaks everything.

Is it possible?
Thank you.

Is there a way to reset swiped cells

For example if on swiped button I navigate to next screen when I back swiped button is still open.
Is there a way to reset swiped buttons?
Or to prevent multiple cell swipes - when swipe next cell to close previously displayed button?

Update example

I was trying to build the example following these steps from the readme

npm run build
cd example
npm install
react-native run-ios # or run-android

and ran into a couple of things which I think could be improved/clarified.

The npm run build command will fail with the following error if babel isn't installed globally.

building lib/index.js
make: ./node_modules/.bin/babel: No such file or directory
make: *** [lib/index.js] Error 1

Installing babel globally is actually not recommended by babel itself. To quote them;

Note: Since it's generally a bad idea to run Babel globally you may want to uninstall the global copy by running npm uninstall --global babel-cli.

I'd suggest adding npm install prior to the npm run build in the readme for some of us new comers working with npm that don't straight away understand what the error is about. This will install babel locally.

  1. react-native version
    The react-native version in package.json is fixed to "react-native": "0.40.0",. Besides it being quite old. The main package.json has it set to "react-native": ">=0.44.0". I think at least sync'ing the two files on dependencies would be nice.

Even after fixing these minor things I couldn't get it to work. I had failing scripts like react-native-xcode.sh no longer found in react-native/Packager/ but react-native/scripts/ and import paths not working. I ended up creating a new project as follows (starting from the root folder):
react-native init SwipeableExample
cd SwipeableExample
npm install react-native-swipeable --save
cp ../example/index.*.js ../example/swipeable-example.js .
react-native run-ios

This way the example works.

Versions:
npm 5.3.0
react-native-swipeable 0.6.0
react-native 0.46.4

Swipe performance

Hi,

I used your component to achieve a swipe list view, but the performance seems not well on the device. I used onRightButtonsOpenRelease to close swipe when its parent scrolls, and used onSwipeStart and onSwipeRelease to close one row when the other is swiping. All codes are from your example.

Any ideas to improve the performance issue?

Cheers,

Just awesome

I have tried another common swipeable components, and maaaan... yours is just awesome :)

Thank you very much ;)

Swipeable seems to interfere with iOS NavigationController's 'swipe-back' gesture.

In iOS, when you have a navigation stack, there's a very handy gesture to swipe from the left screen edge to right to pop the current view from the stack and 'navigate backwards'. The swipeables in my ListView seem to be capturing the gesture, even though I only have rightSide content.

Is there a way to prevent it doing this?

how to disable left when closing right?

this is my proplem
1 ,when close the right button its closed. (as expected)
2 , but its activated left button i mean its opened (but i need to disable)

how can i achieve this

Key issues

still Intermittently getting this error:

screen shot 2017-09-13 at 12 39 33 pm

can you point me in the direction of a fix? Here is my swipeable code:

import React, { Component } from 'react';
import {
  Text,
  View,
  Image,
  Linking,
  TouchableHighlight
} from 'react-native';
import { connect } from 'react-redux';
import {
  saveCollectionItem,
} from '../actions/collection-action';
import {
  saveWantlistItem,
} from '../actions/wantlist-action';

import { CardSection } from '../components/common/CardSection';
import { Button } from '../components/common/Button';
import Swipeable from 'react-native-swipeable';
import SearchSuccessModal from '../components/SearchSuccessModal';


class SearchResultItem extends Component {
constructor(props) {
	super(props);
	this.state = {
    leftActionActivated: false,
    rightActionActivated: false,
    };
}
//
//
//
// checkCollectionForRecords() {
//     let discogsRecord = this.props.item.thumb;
//     this.props.collectionRecords.map((collectionRecord) => {
//       if (discogsRecord === collectionRecord) {
//         console.log("already in collection", discogsRecord, collectionRecord);
//         this.setState({collectionRecordSaved: " in collection"})
//       } else if (!collectionRecord) {
//         console.log("NOT HERE ", discogsRecord, collectionRecord);
//         this.setState({collectionRecordSaved: '' })
//       }
//     })
//   }
//
//   checkWantlistForRecords() {
//     let discogsRecord = this.props.item.thumb;
//     this.props.wantlistRecords.map((wantlistRecord) => {
//       // console.log("DATABASE: ", wantlistRecord);
//       if (discogsRecord === wantlistRecord) {
//         console.log("already in wantlist");
//         this.setState({wantlistRecordSaved: " in wantlist"})
//       } else if (!wantlistRecord) {
//         this.setState({wantlistRecordSaved: ''})
//       }
//     })
//   }
//
saveToCollection = () => {
  let discogsRecord = this.props.item.thumb;
  this.props.saveCollectionItem(discogsRecord)
  return (<SearchSuccessModal />);
  console.log('success modals');
 }
//
//
//
saveToWantlist = () => {
  let discogsRecord = this.props.item.thumb;
  this.props.saveWantlistItem(discogsRecord)
  console.log('saved to wantlist: ', discogsRecord);
 }
//
// beenThereDoneThat = () => {
//   const smallWantlistIcon = require('../img/smallWantlistIcon.png');
//   const smallCollectionIcon = require('../img/smallCollectionIcon.png');
//   let collectionRecord = this.state.collectionRecordSaved;
//   let wantlistRecord = this.state.wantlistRecordSaved;
//   if (collectionRecord) {
//     return (
//       <Text
//         style={styles.collectionSavedTextStyle}>
//         <Image source={smallCollectionIcon} />  {collectionRecord}
//       </Text>
//     )
//   } else if (wantlistRecord) {
// return (
//   <Text
//     style={styles.wantlistSavedTextStyle}>
//     <Image source={smallWantlistIcon} />  {wantlistRecord}
//   </Text>
//     )
//   }
// }




render() {
  let discogsRecord = this.props.item.thumb;
  const { item, onSwipeStart, onSwipeRelease } = this.props;
  let discogsString = item.title.split('-');
  const title = discogsString[1];
  const artist = discogsString[0];

  const {
    imageView,
    textView,
    imageStyle,
    titleTextStyle,
    artistTextStyle,
    collectionSavedTextStyle,
    wantlistSavedTextStyle
  } = styles;
  const { leftActionActivated, rightActionActivated, toggle } = this.state;
  const wantlistIcon = require('../img/wantlistButton.png');
  const collectionIcon = require('../img/collectionButton.png');
  const check = require('../img/checkmark.png');

  const leftContent = [
    <View style={[styles.leftSwipeItem, {backgroundColor: leftActionActivated ? '#2EF470' : '#000'}]}>
    {leftActionActivated ?
      <Image style={styles.leftIconStyles} source={check} /> :
      <Image style={styles.leftIconStyles} source={collectionIcon} />}
    </View>
  ];
  const rightContent = [
    <View style={[styles.rightSwipeItem, {backgroundColor: rightActionActivated ? '#F4702E' : '#000'}]}>
    {rightActionActivated ?
      <Image style={styles.rightIconStyles} source={check} /> :
      <Image style={styles.rightIconStyles} source={wantlistIcon} />}
    </View>
  ];

  return (
    <Swipeable
      leftContent={leftContent}
      rightContent={rightContent}
      leftActionActivationDistance={100}
      rightActionActivationDistance={100}
      onLeftActionActivate={() =>
        this.setState({leftActionActivated: true})
    }
      onLeftActionDeactivate={() =>
        this.setState({leftActionActivated: false})
    }
      onRightActionActivate={() =>
        this.setState({rightActionActivated: true})
    }
      onRightActionDeactivate={() =>
        this.setState({rightActionActivated: false})
    }
      onLeftActionRelease={this.saveToCollection}
      onRightActionRelease={this.saveToWantlist}

      onSwipeStart={onSwipeStart}
      onSwipeRelease={onSwipeRelease}


      >
      <CardSection>
        <View style={imageView}>
          {!item.thumb ? <Image
            style={imageStyle}
            source={require('../img/n-a.png')}
          /> : <Image
            style={imageStyle}
            source={{ uri: item.thumb }}
          />}
        </View>

      <View style={textView}>
          <Text style={titleTextStyle}>{title}</Text>
          <Text style={artistTextStyle}>{artist}</Text>
        </View>
      </CardSection>
    </Swipeable>
    );
  }
};

const styles = {
  container: {
    flexDirection: 'column'
  },

  textView: {
    justifyContent: 'center',
  },
  titleTextStyle: {
    fontSize: 20,
    color: "#DADADA",
    marginLeft: 5
  },
  artistTextStyle: {
    fontSize: 16,
    color: "rgba(217,217,217,.6)",
    marginLeft: 10,
    marginTop: 1
  },
  leftSwipeItem: {
    flex: 1,
    alignItems: 'flex-end',
    justifyContent: 'center',
    paddingRight: 20
  },
  // collectionSavedTextStyle: {
  //   color: '#2EF470',
  //   marginLeft: 12,
  //   marginTop: 9,
  //   fontSize: 10
  // },
  // wantlistSavedTextStyle: {
  //   color: '#F4702E',
  //   marginLeft: 12,
  //   marginTop: 9,
  //   fontSize: 10
  // },
  imageStyle: {
    height: 85,
    width: 85
  },
  rightSwipeItem: {
      flex: 1,
      alignItems: 'flex-start',
      justifyContent: 'center',
      paddingLeft: 20
    }
};

const mapStateToProps = (state) => {
    return {
      ...state
    }
}
// for click events so that dispatches can happen
const mapDispatchToProps = (dispatch) => {
    return {
      saveCollectionItem: (item) => {
          dispatch(saveCollectionItem(item))
      },
      saveWantlistItem: (item) => {
          dispatch(saveWantlistItem(item))
      },
    }
  }



export default connect(mapStateToProps, mapDispatchToProps)(SearchResultItem);

And Here is the FlatList code:

import React, { Component } from 'react';
import axios from 'axios';
import { connect } from 'react-redux';
import {
  saveCollectionItem,
  fetchCollection,
} from '../actions/collection-action';
import {
  saveWantlistItem,
  fetchWantlist,
} from '../actions/wantlist-action';

import {
   Button,
   BarCode,
   ClearText
} from '../components/common';
import fire from '../components/fire';
import SearchResultItem from '../components/SearchResultItem';


import _ from 'lodash';

import {
  View,
  Text,
  TextInput,
  Image,
  ActivityIndicator,
  FlatList
} from 'react-native';

class DiscogsSearch extends Component {
  constructor(props) {
    super(props);
    this.searchDiscogs = this.searchDiscogs.bind(this)

    this.state = {
      text: '',
      loading: false,
      albums: [],
      page: 1,
      discogsRecord: '',
      seed: 1,
      error: null,
      refreshing: false
    };
    this.searchDiscogs = _.debounce(this.searchDiscogs, 150)

  }
  static navigationOptions = {

    tabBarIcon: ({ tintColor }) => (tintColor == '#e91e63' ?
    <Image
      source={require('../img/search_select.png')}
    />
    :
    <Image
      source={require('../img/search.png')}
    />
  ),
};


  searchDiscogs = () => {
    const apiKey = "jbUTpFhLTiyyHgLRoBgq";
    const apiSecret = "LSQDaLpplgcCGlkzujkHyUkxImNlWVoI";
    const { page } = this.state;
    const apiSearch = this.state.newText;
    const url = `https://api.discogs.com/database/search?artist=${apiSearch}
    &key=${apiKey}&secret=${apiSecret}`
    this.setState({ loading: true });

    axios.get(url)
      .then(res => {
        this.setState({
          albums:page === 1 ? res.data.results : [...this.state.albums, ...res.data.results],
          error: res.error || null,
          loading: false,
          refreshing: false
        });
      })
      .catch(error => {
        this.setState({ error, loading: false });
      });

  };

   clearTextInput = () => {
     this._textInput.setNativeProps({ text: '' });
     this.setState({ text: '', albums: [] });
   }
   renderInputButton = () => {
     return <ClearText onPress={this.clearTextInput.bind(this)} />;
   }
  //  handleScroll = () => {
  //   const {currentlyOpenSwipeable} = this.state;
  //
  //   if (currentlyOpenSwipeable) {
  //     currentlyOpenSwipeable.recenter();
  //   }
  // };

   handleRefresh = () => {
     this.setState(
       {
         page: 1,
         seed: this.state.seed + 1,
         refreshing: true
       },
       () => {
         this.searchDiscogs;
       }
     );
   };

   handleLoadMore = () => {
     this.setState(
       {
         page: this.state.page + 1
       },
       () => {
         this.searchDiscogs;
       }
     );
   };

   renderFooter = () => {
     if (!this.state.loading) return null;
     return (
       <View
         style={{
           paddingVertical: 20,
           borderTopWidth: 1,
           borderColor: "#CED0CE"
         }}
       >
         <ActivityIndicator animating size="large" />
       </View>
     );
   };
   _keyExtractor = (item, index) => item.id;


  render() {

    return (
      <View style={styles.container}>

        <View style={styles.inputStyleContainer}>


        <TextInput

          ref={text => this._textInput = text}

          style={styles.inputStyle}

          autoFocus={true}

          type="search"

          value={this.state.newText}

          onChangeText={this.searchDiscogs}

          onChange={(event) => this.setState({ newText: event.nativeEvent.text })}

          placeholder="Artist or Album"

          placeholderTextColor="#D9D9D9"

          selectionColor={'#F42E4A'}

        />

      </View>

      <View style={styles.inputContainer}>

        {this.renderInputButton()}

      </View>
        <FlatList
          data={this.state.albums}
          renderItem={({item}) => (


            <SearchResultItem
             item={item}
             onSwipeStart={() => this.setState({isSwiping: true})}
             onSwipeRelease={() => this.setState({isSwiping: false})}
           />
       )}
          keyExtractor={this._keyExtractor}
          ListFooterComponent={this.renderFooter}
          refreshing={this.state.refreshing}
          onEndReached={this.handleLoadMore}
          onEndReachedThreshold={40}
          style={styles.renderAlbums}
          scrollEnabled={!this.state.isSwiping}
          // backgroundColor={'#1A1A1A'}
          // itemBackgroundColor={'#1A1A1A'}

        />

    </View>
    );
  }
}

const styles = {
  renderAlbums: {
    flex: 1,
    marginTop: -3
  },
  inputContainer: {
    justifyContent: 'flex-end',
    alignItems: 'flex-end',
    height: 5,
    marginRight: 10,
    marginBottom: 0,
  },
  container: {
    flex: 1
  },

  inputStyleContainer: {
    flexDirection: 'column',
    alignItems: 'flex-start',
    marginTop: 25,
    height: 40,
    borderBottomWidth: 1,
    borderBottomColor: "#ffffff",
    marginBottom: 0
  },
  inputStyle: {
    color: '#fff',
    fontSize: 18,
    lineHeight: 23,
    backgroundColor: '#000',
    justifyContent: 'flex-start',
    flex: 1,
    paddingLeft: 7,
    paddingRight: 7,
    paddingBottom: 0,
    marginBottom: 0
  },

};

const mapStateToProps = (state) => {
    return {
      ...state
    }
}
// for click events so that dispatches can happen
const mapDispatchToProps = (dispatch) => {
    return {
      saveCollectionItem: (item) => {
          dispatch(saveCollectionItem(item))
      },
      saveWantlistItem: (item) => {
          dispatch(saveWantlistItem(item))
      },
      fetchCollection: () => {
          dispatch(fetchCollection())
      },
      fetchWantlist: () => {
          dispatch(fetchWantlist())
      },
    }
  }



export default connect(mapStateToProps, mapDispatchToProps)(DiscogsSearch);

Unexpected view/button expansion on slide closing (flickers)

It's a bit difficult to properly describe it, so I recorded the behaviour to make make it easier to explain.

The circle around the mouse pointer indicates the mouse button is pressed down. In this case I keep it down to swipe. I swipe really slow on purpose because it helps in sometimes getting to show the expanded state (as seen here in the first swipe). In the second swipe it just shows the flickering.

Initially I thought this only occurred on smaller screen sizes (like the iPhone 5/SE), but it also happens on iPhone 6 as can be seen here.

As you can see in the first swipe the whole closing animation seems to be missing completely. The second swipe only shows the flickering. In neither cases there is an FPS drop on the UI or JS thread.

I can also confirm this always happens on a physical device (iPhone 5s). It's not just an occasional artefact.

I found a workaround for this component by ignoring a single refresh the moment the panResponder is granted.

    _handlePanResponderStart = (event, gestureState) => {
        const { lastOffset, pan } = this.state
        this.setState({ skipRefresh: true })
        pan.setOffset(lastOffset)

    shouldComponentUpdate(nextProps, nextState) {
        if (nextState.skipRefresh == true) {
            this.setState({ skipRefresh: false })
            return false
        } else {
            return true
        }
    }

This resolves the issue on the simulator for small and bigger screen sizes and also on the physical device (again only iphone 5s tested).

Extra info
I have not been able to pin/point what is causing it. Interesting to note though is that I switched to your component when I experienced similar behaviour in another component (specifically the dev branch that uses the Animated API instead of tweenstate). I went back to that component see if the same fix works there, but it doesn't. Regardless I think it's interesting that 2 different components show similar behaviour.

Disabling swipe

Hello again,
I'd like to disable a swipeable element once it has been activated, say, by a left pull. How could I achieve that?
I've skimmed through the extensive props list but haven't come across anything that might help.

Thank you.

Support for bouncing a row on mount

Hi, thanks for the great component.

We're using react-native-swipeable for items in a FlatList/SectionList.

The old, experimental SwipeableListView had a prop called bounceFirstRowOnMount that did exactly what it sounds like, it slid the first row to the left & then back to show the user that the row was swipeable.

Is there interest in a feature like that for react-native-swipeable? I (or my teammate) would be interested in helping with it

Obviously, the prop name would have to change. I would propose something like bounceOnMount and then developers could just use the index to bounce the first row.

View style not taking hold on page load

Hi,

Been trying to get a working version of this up and running. Been the easiest swipe library to use so far but I'm having a strange issue.

I'm following along Example #3 from the docs:

render() {
    const {leftActionActivated, toggle} = this.state;

    return (
      <Swipeable
        onLeftActionActivate={() => this.setState({leftActionActivated: true})}
        onLeftActionDeactivate={() => this.setState({leftActionActivated: false})}
        onLeftActionComplete={() => this.setState({toggle: !toggle})}
        leftActionActivationDistance={200}
        leftContent={(
          <View style={[styles.leftSwipeItem, {backgroundColor: leftActionActivated ? 'lightgoldenrodyellow' : 'steelblue'}]}>
            {leftActionActivated ?
              <Text>release!</Text> :
              <Text>keep pulling!</Text>}
          </View>
        )}
      >
        <View style={[styles.listItem, {backgroundColor: toggle ? 'thistle' : 'darkseagreen'}]}>
          <Text>Example 3</Text>
        </View>
      </Swipeable>
    );
  }

On page load, the onLeftActionActivate function actually runs, I get console.log output, however the <View/> background color does not change and the release! text never gets displayed. It only works after I perform some action in my app and then go back to the list and try again.

out

Please let me know if you have any idea whats going on. Thanks!

Can only swipe from "Touchable" elements if using inside of modal

First of all, amazing component! Thanks for creating it!

I'm using this inside of a regular component without issue, but when I try to use it inside of a React Native <Modal>, the only elements I can initiate a swipe from are Touchable wrappers. I'm getting around this by wrapping my entire list item inside of TouchableWithoutFeedback wrapper, but I'm curious why the behavior is different inside of a modal?

In both cases, modal and no modal, I am inside of a <ScrollView> - the only difference is the modal.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.