react-native-swipeable icon indicating copy to clipboard operation
react-native-swipeable copied to clipboard

Open onPress

Open AndiCrisan opened this issue 6 years ago • 7 comments

Can I do the opposite of .recenter with an onPress action? For example i want to activate the right content by using onPress action on an icon.

AndiCrisan avatar May 04 '18 12:05 AndiCrisan

You can use Animated API to activate the right content by using onPress action on an icon.

example:

 var pan = this.swipe.state.pan;

      pan.flattenOffset();

      Animated.timing(pan, {
        toValue: { x: -100, y: 0 },
        duration: 250
      }).start();

reftp740 avatar Jun 25 '18 01:06 reftp740

Using @reftp740 example, I got it working with this:

<TouchableHighlight
   onPress={() => {
      let pan = this.swipeable.state.pan;
      pan.flattenOffset();
      Animated.timing(pan, {
         toValue: { x: -100, y: 0 },
         duration: 250,
       }).start();
    }
}>
   Click me
</TouchableHighlight>

<Swipeable onRef={ref => (this.swipeable = ref)}>{blah}</Swipeable>

dringala avatar Aug 03 '18 09:08 dringala

The above code worked for opening it, however if you tried to swipe close the item would have a glitch and close weird because the state didn't match up with what was showing on the screen. I wrote a open and toggle function to help with opening an closing the buttons. There's very simple working example below, there's also an expo snack if you want to see it in action

/// @name open
/// @description This will open the left or right buttons
/// @arg {string} side ['right'] - The side to open.
/// @arg {fn} onDone - do something after the buttons are open
Swipeable.prototype.open = function open (side = 'right', onDone) {
  const { pan } = this.state
  const left = side === 'left'
  const right = side === 'right'

  this.setState({
    leftActionActivated: left,
    leftButtonsActivated: left,
    rightActionActivated: right,
    rightButtonsActivated: right,
  }, () => {
    const animationFn = this._getReleaseAnimationFn()
    const animationConfig = this._getReleaseAnimationConfig()
    this.setState({
      lastOffset: animationConfig.toValue,
      leftActionActivated: false,
      leftButtonsActivated: left,
      leftButtonsOpen: left,
      rightActionActivated: false,
      rightButtonsActivated: right,
      rightButtonsOpen: right,
    })
    pan.flattenOffset()

    animationFn(pan, animationConfig).start(onDone)
  })
}

/// @name toggle
/// @description This will open the left or right buttons
/// @arg {string} side ['right'] - The side to open.
/// @arg {fn} onDone - do something after the buttons are toggled
Swipeable.prototype.toggle = function toggle (side = 'right', onDone) {
  if (!this.state[`${side}ButtonsOpen`]) {
    this.open(side, onDone)
  } else {
    this.recenter()
  }
}
Working Example
import React, { PureComponent } from 'react'
import { TouchableHighlight, Text } from 'react-native'
import Swipeable from 'react-native-swipeable'

const styles = {
  button: {
    padding: 10,
    backgroundColor: '#1d87e5',
  },
}

function Button ({ title, style, ...props } = {}) {
  return (
    <TouchableHighlight style={[ styles.button, style ]} {...props}>
      <Text style={{ color: '#fff' }}>{title}</Text>
    </TouchableHighlight>
  )
}

class Page extends PureComponent {
  render () {
    return (
      <>
        <Button onPress={() => this.swipeable.toggle('right')} title="Toggle Right" />
        <Button onPress={() => this.swipeable.toggle('left')} title="Toggle Left" />
        <Swipeable
          onRef={(ref) => {
            this.swipeable = ref
          }}
          leftButtons={[ <Button style={{ alignItems: 'flex-end' }} title="Learn More" /> ]}
          rightButtons={[ <Button title="Learn More" /> ]}
        >
          <Text>
            Lorem ipsum dolor sit amet, consectetur adipisicing elit
          </Text>
        </Swipeable>
      </>
    )
  }
}

tjbenton avatar Oct 30 '18 19:10 tjbenton

Both of this solution work , but open always the last record and not the one user select.

Can u help on this ? @denis-shvets @jshanson7

Tilenozz avatar Feb 04 '20 08:02 Tilenozz

Using @reftp740 example, I got it working with this:

<TouchableHighlight
   onPress={() => {
      let pan = this.swipeable.state.pan;
      pan.flattenOffset();
      Animated.timing(pan, {
         toValue: { x: -100, y: 0 },
         duration: 250,
       }).start();
    }
}>
   Click me
</TouchableHighlight>

<Swipeable onRef={ref => (this.swipeable = ref)}>{blah}</Swipeable>

Your solution work , but open always the last record and not the one user select.

Can u help on this ?

Tilenozz avatar Feb 04 '20 08:02 Tilenozz

From what you're saying it sounds like you're trying to render multiple Swipeables in the same component and you can't set the ref to the same thing (this.swipeable) otherwise the last Swipeable will be the only one you have access to because it would be the last one to run it's onRef function. Assuming this is the case you would have to store all the refs in an array and loop over them. It would look something like this, sorry I don't have the time to do a full working example but this should get you headed in the right direction.

class Page extends PureComponent {
  swipeable = []

  forEachSwipeable (callback) {
    this.swipeables.forEach(callback)
  }

  renderSwipeable () {
    return (
      <Swipeable
        onRef={(ref) => {
          this.swipeables.push(ref)
        }}
        ...
      >
        ...
      </Swipeable>
    )
  }

  render () {
    return (
      <>
        ...
        this.renderSwipeable()
        this.renderSwipeable()
      </>
    )
  }
}

tjbenton avatar Feb 05 '20 15:02 tjbenton

Tried this :

The Flatlist is composed by 2 element.

<Swipeable onRef={(ref) => { this.swipeable = ref; this.swipeable_arr.push(ref) }}

<TouchableOpacity onPress={() => this.openSlider(this.swipeable)} ><Text>Click</Text>

openSlider = (item) => {

for (let i = 0; i < this.swipeable_arr.length; i++) {

  console.log("Total Size ", this.swipeable_arr.length)
  const element = this.swipeable_arr[i];

  if (item == element) {
    console.log("Equal")
     Animated.timing(item.state.pan, {
       toValue: { x: -500, y: 0 },
       duration: 250,
     }).start();
  } else {
    console.log("Not equal")
  }
}

But this will open always the last item ...

This is the log ...

Total Size 2 Not equal Total Size 2 Equal

Tilenozz avatar Feb 06 '20 09:02 Tilenozz