ReactNative: 使用鍵盤避免視圖KeyboardAvoidingView組件實現鍵盤自適應


一、簡介

在前面使用了TextInput實現了文本輸入和搜索功能,一般情況下,我們會通過樣式設置把控鍵盤彈起后與視圖的間距,以至於不會擋住某些視圖。但是,如果視圖上的組件比較多,鍵盤的彈起覆蓋某些視圖幾乎是無法避免的。ReactNative中就提供了一個KeyboardAvoidingView組件來解決這個問題。使用了這個組件后,它會幫助自動完成鍵盤的自適應,通過偏移避免其他組件被鍵盤遮蓋。

 

二、API

KeyboardAvoidingView組件提供了3個比較重要的屬性,分別是behavior、contentContainerStyle、keyboardVerticalOffset。behavior譯為行為,這里指鍵盤避免視圖組件的位移焦點。contentContainerStyle是該組件內部視圖的樣式布局。keyboardVerticalOffset則是鍵盤的豎直偏移距離。如下:

//位移的參照焦點有三種:height:以高度為焦點  position:以位置為焦點  padding:以邊距為焦點
behavior: PropTypes.oneOf(['height', 'position', 'padding']),

//組件內容視圖樣式布局,只有采用‘ position’為焦點時,才會創建出這個內容視圖
contentContainerStyle: ViewPropTypes.style,

//這是用戶屏幕頂部與應用視圖的距離,可以利用這個屬性來補償修正這段距離
keyboardVerticalOffset: PropTypes.number.isRequired,

KeyboardAvoidingView組件也提供了幾個常用的方法,可以使用這幾個方法手動來調整鍵盤的偏移。如下:

//鍵盤的相對高度
relativeKeyboardHeight(keyboardFrame: ScreenRect): number

//鍵盤改變時的回調
onKeyboardChange(event: ?KeyboardChangeEvent)

//鍵盤布局時的回調
onLayout(event: LayoutEvent)

//這個幾個方法用到的對象如下
type Rect = {
  x: number,
  y: number,
  width: number,
  height: number,
};

type ScreenRect = {
  screenX: number,
  screenY: number,
  width: number,
  height: number,
};

type KeyboardChangeEvent = {
  startCoordinates?: ScreenRect, //起始位置
  endCoordinates: ScreenRect,    //終止位置 
  duration?: number,             //動畫時間 
  easing?: string,          
};

type LayoutEvent = {
  nativeEvent: {
    layout: Rect,
  }
};

 

三、拓展

使用KeyboardAvoidingView組件時,可以搭配鍵盤組件Keyboard組件一起完成開發。鍵盤彈起和隱藏的過程,都可以使用鍵盤組件Keyboard進行監聽。它提供了常用的幾個監聽名稱和鍵盤相關數據,如下所示:

//監聽名稱
type KeyboardEventName =
     | 'keyboardWillShow'
     | 'keyboardDidShow'
     | 'keyboardWillHide'
     | 'keyboardDidHide'
     | 'keyboardWillChangeFrame'
     | 'keyboardDidChangeFrame';

//鍵盤數據
type KeyboardEventData = {
     endCoordinates: { 
        width: number,
        height: number,
        screenX: number,
        screenY: number,},
    };    

提供的幾個方法比較簡單,如下所示:

//給鍵盤添加監聽
addListener(eventName: KeyboardEventName, callback: KeyboardEventListener)

//給鍵盤移除監聽
removeListener(eventName: KeyboardEventName, callback: Function)

//移除鍵盤所有監聽
removeAllListeners(eventName: KeyboardEventName)

//關閉鍵盤
dismiss()

 

四、使用

現在使用KeyboardAvoidingView組件來調節輸入框的位置,示例如下:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';

import {
    AppRegistry,
    StyleSheet,
    View,
    TextInput,
    Dimensions,
    Keyboard,
    KeyboardAvoidingView
} from 'react-native';

let {height} = Dimensions.get('window');

export default class ReactNativeDemo extends Component {

    componentWillMount() {
        this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow',(KeyboardEventData)=>{

            console.log('Keyboard Shown');
            console.log(KeyboardEventData.endCoordinates.screenY);

            // KeyboardAvoidingView實例的方法,可以在監聽事件中調用
            // const avoidingView = this.refs.KeyboardAvoidingView;
            // avoidingView.onKeyboardChange(KeyboardChangeEvent);
            // avoidingView.onLayout(LayoutEvent);
            // avoidingView.relativeKeyboardHeight(keyboardFrame);
        });

        this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', (KeyboardEventData)=>{

            console.log('Keyboard Hidden');
            console.log(KeyboardEventData.endCoordinates.screenY);

            // KeyboardAvoidingView實例的方法,可以在監聽事件中調用
            // const avoidingView = this.refs.KeyboardAvoidingView;
            // avoidingView.onKeyboardChange(KeyboardChangeEvent);
            // avoidingView.onLayout(LayoutEvent);
            // avoidingView.relativeKeyboardHeight(keyboardFrame);
        });
    }

    componentWillUnmount() {
        this.keyboardDidShowListener.remove();
        this.keyboardDidHideListener.remove();
    }

    render() {
        return (
            <View style={[styles.flex,styles.bgColor]}>
                <KeyboardAvoidingView ref={'KeyboardAvoidingView'}
                                      behavior={'position'}
                                      keyboardVerticalOffset={10}
                                      contentContainerStyle={styles.avoidingView}>
                    <TextInput
                        style={styles.inputView}
                        placeholder='請輸入關鍵字'
                        placeholderTextColor="black"
                        returnKeyType='search'
                        clearButtonMode='while-editing'
                        enablesReturnKeyAutomatically={true}
                    />
                </KeyboardAvoidingView>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    flex: {
        flex: 1
    },
    bgColor: {
      backgroundColor: 'white'
    },
    center: {
        alignItems: 'center',
        justifyContent: 'center',
    },
    font: {
        fontSize: 30,
        color: 'purple',
        textAlign: 'center'
    },
    avoidingView: {
        backgroundColor:'#DDD'
    },
    inputView:{
        height:100,
        borderWidth: 1,
        marginTop: height-111,
        marginRight:5,
        marginLeft: 5,
        paddingLeft: 5,
        borderColor:'red',
        borderRadius: 4
    },
});

AppRegistry.registerComponent('ReactNativeDemo', () => ReactNativeDemo);

打印結果如下:

2020-01-02 17:22:55.793 [info][tid:com.facebook.react.JavaScript] Keyboard Shown
2020-01-02 17:22:55.794 [info][tid:com.facebook.react.JavaScript] 407
2020-01-02 17:23:05.852 [info][tid:com.facebook.react.JavaScript] Keyboard Shown
2020-01-02 17:23:05.853 [info][tid:com.facebook.react.JavaScript] 407
2020-01-02 17:23:08.470 [info][tid:com.facebook.react.JavaScript] Keyboard Hidden
2020-01-02 17:23:08.470 [info][tid:com.facebook.react.JavaScript] 667

截圖結果如下:1圖為初始狀態、2圖為不使用KeyboardAvoidingView組件時輸入框被鍵盤遮蓋、圖3使用了KeyboardAvoidingView組件時不會遮蓋正常使用。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM