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

Keyboard hiding popUp

Open AishwaryaSurana opened this issue 6 years ago • 17 comments

Is there a way to change pop-up position when KeyBoard is up?

Right now my pop-Up is hiding behind keyboard, or is there any way to change the position of dialog?

AishwaryaSurana avatar Oct 05 '17 06:10 AishwaryaSurana

@sainath13 I have gone through this link already. No help

AishwaryaSurana avatar Nov 07 '17 09:11 AishwaryaSurana

works for me perfectly.

sainath13 avatar Nov 09 '17 16:11 sainath13

@AishwaryaSurana for android you need to use KeyboardAvoidingView. something like this. Make sure that your popup is visible after some event like clicking a button etc before doing this change.

render() {
    if (Platform.OS === 'ios') {
      return (
        <KeyboardAwareScrollView
          resetScrollToCoords={{
          x: 0,
          y: 0
        }}
          contentContainerStyle={styles.container}
          scrollEnabled={false}
          style={{
          flex: 1
        }}>
          <StatusBar backgroundColor="#6563A4" barStyle="dark-content"/>
          <UpdateInfoPageComponent {...this.props}> </UpdateInfoPageComponent>
        </KeyboardAwareScrollView>
      );
    } else {
      return (
        <KeyboardAvoidingView
          {...this.props}
          behavior="padding"
          keyboardVerticalOffset={-1000}
          style={{
          flex: 1
        }}>
          <ScrollView style={{
            flex: 1
          }}>
            <StatusBar backgroundColor="#43416d" barStyle="dark-content"/>
            <UpdateInfoPageComponent {...this.props}></UpdateInfoPageComponent>

          </ScrollView>
        </KeyboardAvoidingView>
      )

sainath13 avatar Jan 10 '18 15:01 sainath13

you can use a KeyboardSpacer

yarn add react-native-keyboard-spacer

import KeyboardSpacer from 'react-native-keyboard-spacer';

    <PopupDialog
      dialogTitle={<DialogTitle title="Dialog Title" />}
      ref={(popupDialog) => { this.popupDialog = popupDialog; }}
      dialogStyle={{ backgroundColor: null, height: 'auto' }}
    >
      <View>
        <TextInput/>
      </View>
      <KeyboardSpacer />
    </PopupDialog>

daniel-lucas-silva avatar Apr 23 '18 20:04 daniel-lucas-silva

@daniel-lucas-silva Have you tried? It don't work for a bit of complex layout.

jinzunyue avatar Jun 06 '18 16:06 jinzunyue

Same problem here :( The dialog doesn't respond to keyboard opening. Could you add this feature? it's a must have for this library

michelebombardi avatar Jul 05 '18 08:07 michelebombardi

any update on this issue?

faisal-93 avatar Aug 13 '18 07:08 faisal-93

Having the same problem...

alake2 avatar Aug 15 '18 22:08 alake2

@faisal2173 @alake2 @bm-software have you guys tried using KeyboardAvoidingView for android? I have been using it for months now. It works like a charm. If you did what problems are you facing?

sainath13 avatar Aug 19 '18 05:08 sainath13

Hi everyone, I "solved" this problem by adding a listener to the keyboard and changing the dialog style like this:

const { width, height } = Dimensions.get('window')

...

componentDidMount() {
      Keyboard.addListener('keyboardDidShow', this._keyboardDidShow)
      Keyboard.addListener('keyboardDidHide', this._keyboardDidHide)
  }

  _keyboardDidShow = () => {
      this.setState({
          dialogStyle: {
              top: -1 * (width / 4),
              borderRadius: 20,
              padding: 10,
              overflow: 'hidden',
          },
      })
  }

  _keyboardDidHide = () => {
      this.setState({
          dialogStyle: {
              borderRadius: 20,
              padding: 10,
              overflow: 'hidden',
          },
      })
  }

...
<PopupDialog
dialogStyle={this.state.dialogStyle}
> {this.props.children}
</PopupDialog>

I hope it helps!

brunon80 avatar Aug 20 '18 00:08 brunon80

@sainath13 I'm also using expo with tab navigation and for some reason KeyboardAvoidingView does nothing (I've spent hours trying to get it to work).

alake2 avatar Aug 20 '18 19:08 alake2

const { width, height } = Dimensions.get('window')

thanks alot bro, it really helped me.

ShooterArk avatar Nov 24 '18 19:11 ShooterArk

@brunon80 can you please share a full example ?

souhaiebtar avatar Apr 18 '19 09:04 souhaiebtar

Here is my wrapper KeyboardAvoidingDialog, it uses react-native-keyboard-spacer.

// KeyboardAvoidingDialog.js
import React, { memo, useState, useEffect } from 'react';
import { View } from 'react-native';
import { Dialog, Colors } from 'react-native-paper';
import KeyboardSpacer from 'react-native-keyboard-spacer';

export default memo(({ children, ...rest }) => {
  const [keyboardSpace, setKeyboardSpace] = useState(440);
  const [topSpacing, setTopSpacing] = useState(-440);
  const [height, setHeight] = useState(0);

  const onLayout = ({nativeEvent: { layout: {height : _height}}}) => {
    if (!height && height !== _height) {
      setHeight(_height);
    }
  };

  const onToggle = (keyboardState, _keyboardSpace) => {
    if (keyboardState
      && _keyboardSpace > 100
      && _keyboardSpace !== keyboardSpace
      && _keyboardSpace > keyboardSpace
    ) {
      setKeyboardSpace(_keyboardSpace);
    }
  };

  useEffect(() => {
    const newTopSpacing = - keyboardSpace + (height / 2);
    setTopSpacing(newTopSpacing + 50);
  }, [keyboardSpace, height])

  return (
    <Dialog
      {...rest}
      style={{ backgroundColor: 'transparent' }}
    >
      <View onLayout={onLayout} style={{ backgroundColor: Colors.white }}>
        {children}
      </View>
      <KeyboardSpacer topSpacing={topSpacing} onToggle={onToggle} />
    </Dialog>
  );
});

Then you can simply import this and use as :

import { Dialog } from 'react-native-paper';
import KeyboardAwareDialog from <path to KeyboardAwareDialog.js>;

<KeyboardAwareDialog
  dismissable={false}
  visible={visible}>
   <Dialog.Title>{'Hellow'}</Dialog.Title>
</KeyboardAwareDialog>

fawaz-ahmed avatar Dec 29 '19 09:12 fawaz-ahmed

Hi everyone, I "solved" this problem by adding a listener to the keyboard and changing the dialog style like this:

const { width, height } = Dimensions.get('window')

...

componentDidMount() {
      Keyboard.addListener('keyboardDidShow', this._keyboardDidShow)
      Keyboard.addListener('keyboardDidHide', this._keyboardDidHide)
  }

  _keyboardDidShow = () => {
      this.setState({
          dialogStyle: {
              top: -1 * (width / 4),
              borderRadius: 20,
              padding: 10,
              overflow: 'hidden',
          },
      })
  }

  _keyboardDidHide = () => {
      this.setState({
          dialogStyle: {
              borderRadius: 20,
              padding: 10,
              overflow: 'hidden',
          },
      })
  }

...
<PopupDialog
dialogStyle={this.state.dialogStyle}
> {this.props.children}
</PopupDialog>

I hope it helps!

@brunon80 thank you man your solution works, nothing else worked I tried everything I could find in the issues. For anyone using this solution with hooks; it works when I call keyboard listen once at the start

  const [dialogStyle, setDialogStyle] = useState({ borderRadius: 20, padding: 10, overflow: 'hidden'});
  const [keyboardListenAdded, setKeyboardListenAdded] = useState(false);

  const  _keyboardDidShow = () => {
    setDialogStyle({ top: -1 * (width / 4), borderRadius: 20, padding: 10, overflow: 'hidden'})
  }

  const _keyboardDidHide = () => {
    setDialogStyle({ borderRadius: 20, padding: 10, overflow: 'hidden'})
  }
  useEffect(() => {
    if (!keyboardListenAdded) {
      Keyboard.addListener('keyboardDidShow', _keyboardDidShow)
      Keyboard.addListener('keyboardDidHide', _keyboardDidHide)
      setKeyboardListenAdded(true)
    }
  }, [
    _keyboardDidShow,
    _keyboardDidHide,
    setKeyboardListenAdded
  ]);

      <Modal
        width={0.9}
        visible={notesModal}
        rounded
        style={dialogStyle}
        actionsBordered
        footer={
          <View>
            <ModalFooter>
              <ModalButton
                text={t('sale.add_note')}
                bordered
                onPress={() => handleApplyNote()}
                key="button-1"
              />
              <ModalButton
                text={t('sale.cancel')}
                bordered
                onPress={() => toggleNotesModal()}
                key="button-3"
              />
            </ModalFooter>
          </View>
        }
        modalTitle={ <ModalTitle title={t('sale.add_note')}/>}
      >
        <ModalContent style={{ backgroundColor: '#fff', paddingTop: 24 }} >
          <Textarea
            rowSpan={4}
            bordered={true}
            value={cartNote}
            placeholder={t('sale.add_note_exp')}
            name="cartNotesTextarea"
            onChange={e => setCartNote(e.target.value)}
            value={cartNote}
          />
        </ModalContent>
      </Modal>

ghost avatar Jul 15 '20 18:07 ghost

@canercak Is it a good solution? Because I tried it and the popup jumps without any transition and it can be really weird to a user.

LauraBeatris avatar Jul 21 '20 16:07 LauraBeatris