Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to know when hide() or show() is called? #96

Closed
jerocosio opened this issue Mar 1, 2019 · 13 comments
Closed

How to know when hide() or show() is called? #96

jerocosio opened this issue Mar 1, 2019 · 13 comments

Comments

@jerocosio
Copy link

Issue Description

First of all, AMAZING component, congrats!

I want to to change the content of my dragHandler and panel depending if the panel is 'opened' or 'closed' but how can I do that? If I use the open() or hide() methods, the onDragEnd property isn't called.
I could create a function with a set variable to determine if the status is 'opened' or 'closed' the problem there is that I can't know when a user hides the panel by touching the backdrop...

Code Snippets

<SlidingUpPanel
      ref={c => this._panel = c}
      draggableRange={{ top: 700, bottom: 200 }}
      minimumDistanceThreshold={10}
      backdropOpacity={.1}
    >
    {(dragHandlers) => (
      <View style={styles.panel}>
          <View {...dragHandlers} style={styles.dragHandler}>
              WOULD LIKE TO CHANGE THIS DEPENDING ON THE 'OPEN' OR 'CLOSED' STATE...
          </View>
        <View style={styles.panelContent}>
          <View style={styles.buttonContainer}>
             WOULD LIKE TO CHANGE THIS DEPENDING ON THE 'OPEN' OR 'CLOSED' STATE...
          </View>
        </View>
      </View>
    )}
  </SlidingUpPanel>  

This is on what I'm working:

Alt Text


Environment

  • Version: 2.0.1
  • React Native version: 32
  • Platform(s) (iOS, Android, or both?): iOS
  • Device info (Simulator/Device? OS version? Debug/Release?): Device
@octopitus
Copy link
Owner

how didn't I ever think about this scenario when implementing? 🤦‍♂️

@octopitus
Copy link
Owner

octopitus commented Mar 3, 2019

I'm thinking about implement a mechanism to listen to the state changes of the panel. Dragging related events seem not enough.

In a meanwhile, you can listen to the animated value change. Below is an example:

const draggableRange = {top: 700, bottom: 200}
const animatedValue = new Animated.Value(draggableRange.bottom) // Initial position is at bottom.

animatedValue.addListener({ value }) => {
  if (value === draggableRange.top) {
    // At top position
  } 

  if (value === draggableRange.bottom) {
    // At bottom position
  }
})

<SlidingUpPanel
  animatedValue={animatedValue}
  draggableRange={draggableRange}
  ref={c => this._panel = c}>
  // ...
</SlidingUpPanel>

@Vondry
Copy link

Vondry commented Mar 3, 2019

I did implement auto scroll to bottom or top. Direction dependes on where user started and end scrolling, then i can safely call state change.

This use case tries to cover audio player control bar.

let PanelRef = null;
let lastlyScrolled = 0;

	const _onDragStart = (scrolledHeight) => {
		onDragStart(scrolledHeight);
		lastlyScrolled = Math.floor(+scrolledHeight);
	};

	const _onDragEnd = (scrolledHeight) => {
		onDragEnd(scrolledHeight);
		const flooredScrolledHeight = Math.floor(+scrolledHeight);
		if (lastlyScrolled === flooredScrolledHeight) return;

		if (lastlyScrolled < flooredScrolledHeight) {
			onFullyVisible();
			PanelRef.show();
		} else {
			onFullyHidden();
			PanelRef.hide();
		}

		lastlyScrolled = flooredScrolledHeight;
	};

@jerocosio
Copy link
Author

Thanks @octopitus for the quick reply, going to try that out!

@jerocosio
Copy link
Author

jerocosio commented Mar 5, 2019

Your solution works great, but If I open and close the view a lot of times fast, it starts getting super slugish and on the perf monitor I can see that the js is having a lot of trouble, is there something I should do different in my code, could you take a look?

_animatedValue = new Animated.Value(200);

  showOrHide = () => {this.state.panel == 'down' ? this._panel.show() : this._panel.hide()}

  render(){
    const {top, bottom} = this.props.draggableRange
    this._animatedValue.addListener(({value}) => {
      if (value === top) {
        this.setState({panel:'up'})
      }
      if (value === bottom) {
        this.setState({panel:'down'})
      }
    });

    return (
      <SlidingUpPanel
        ref={c => this._panel = c}
        animatedValue={this._animatedValue}
        draggableRange={this.props.draggableRange}
        minimumDistanceThreshold={10}
        backdropOpacity={.1}
        height={700}
      >
      {(dragHandlers) => (
        <View style={styles.panel}>
            <View {...dragHandlers} style={styles.dragHandler}>
              <TouchableOpacity style={styles.dragButton} onPress={this.showOrHide}>
                <Ionicons name={this.state.panel=='up' ? 'ios-arrow-down' : 'ios-arrow-up'} size={25} color={'black'} />
              </TouchableOpacity>
            </View>
          <View style={styles.panelContent}>
            {this.state.panel=='up' ? (
              <KeyboardInput />
            ) : (
            <View style={styles.buttonContainer}>
              <ButtonA text={"Comprar / Vender"} color={"blue"} onPress={this.showOrHide} />
            </View>
          )
          }
          </View>
        </View>
      )}
    </SlidingUpPanel>
    );
  }

A GIF to better understand the issue :)

Alt Text

@octopitus
Copy link
Owner

octopitus commented Mar 5, 2019

Move the part where you add animated listener to componentDidMount and remove the listener when componentWillUnmount. Like this:

componentDidMount() {
  this._animatedValue.addListener(this._onAnimatedValueChange);
}

componentWillUnmount() {
  this._animatedValue.removeListener(this._onAnimatedValueChange);
}

_onAnimatedValueChange({ value }) {
  const {top, bottom} = this.props.draggableRange
  if (value === top) {
    this.setState({panel:'up'})
  }
  if (value === bottom) {
    this.setState({panel:'down'})
  }
}

@jerocosio
Copy link
Author

You're awesome! I don't know if you would like to add this example to the demos. I could share the example + a .gif file :)

@octopitus
Copy link
Owner

It would be great! You can create PR including the .gif and example code.

@waqasahmad34
Copy link

hi i want to use two different SlidingUpPanel that behave differently functionality i have used but i always display one and override other one why its not distinct i also use difference refs. please guide me. thanks

@spmatthews03
Copy link

I know this has been closed and a new PR has been created off of it. But I'm having issues trying to translate this to functional components. I have used 'useEffect' to mount and unmount, but the listeners aren't being fired when the sliding panel is animated.

@romadryud
Copy link

romadryud commented Jan 26, 2021

@spmatthews03 did you figure out how it can be implemented?
@octopitus What do you think about this?

@romadryud
Copy link

@spmatthews03 I checked and seems it work with this structure:

useEffect(() => {
		const slidingListener = animatedValue.addListener(
			onAnimatedValueChange,
		);
		return () => animatedValue.removeListener(slidingListener);
	}, [animatedValue]);

@ronar
Copy link

ronar commented Oct 18, 2022

Move the part where you add animated listener to componentDidMount and remove the listener when componentWillUnmount. Like this:

componentDidMount() {
  this._animatedValue.addListener(this._onAnimatedValueChange);
}

componentWillUnmount() {
  this._animatedValue.removeListener(this._onAnimatedValueChange);
}

_onAnimatedValueChange({ value }) {
  const {top, bottom} = this.props.draggableRange
  if (value === top) {
    this.setState({panel:'up'})
  }
  if (value === bottom) {
    this.setState({panel:'down'})
  }
}

removeListener accepts a string with animation ID. Accordingly, listener won't be removed.
it should be:

this._animatedValueListenerId = _animatedValue.addListener(this._onAnimatedValueChange);
...
_animatedValue.removeListener(this._animatedValueListenerId);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants