npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sdcx/keyboard-insets

v0.6.0

Published

A Keyboard Avoiding View for React Native.

Downloads

241

Readme

KeyboardInsetsView

KeyboardInsetsView 是一个 React Native 原生 UI 组件,用于处理软键盘遮挡输入框的问题。

KeyboardInsetsView 使用简单,自动模式下不需要额外代码来处理键盘。

| 自动模式 | 手动模式 | | --------------------------------------------------------- | ----------------------------------------------------- | | README-2023-02-02-15-56-36 | README-2023-02-18-21-36-20 |

本库主要依据 Android 官方指南 Synchronize animation with the software keyboard 来实现,同时参考了 react-native-keyboard-controller。因为该库不是很符合我的需求,所以我自己写了一个。

Installation

yarn add @sdcx/keyboard-insets

iOS

cd ios
pod install

Android

开启 edge-to-edge。 这将使得 APP 的 UI 撑满整个屏幕,而不是被系统 UI(譬如虚拟导航键)遮挡,从而实现更摩登的 UI 效果。

// MainActivity.java
import androidx.core.view.WindowCompat;

public class MainActivity extends ReactActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(null);
        // enable Edge-to-Edge
        WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
    }
}

为了更好的向后(Android 10 以前)兼容, 在 AndroidManifest 中设置 android:windowSoftInputMode="adjustResize"

<!-- AndroidManifest.xml -->
<activity
  android:name=".MainActivity"
    ...
  android:windowSoftInputMode="adjustResize">
  <intent-filter>
    ...
  </intent-filter>
</activity>

开启 Edge-to-Edge 后,你的 UI 会撑满整个屏幕,可使用 react-native-safe-area-context 来处理和系统 UI (譬如虚拟导航键) 重叠的部分。

可参考以下代码进行全局处理,也可以每个页面单独处理,以实现更美观更摩登的 UI 效果。

import { Platform } from 'react-native'
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'

function App() {
  return (
    <SafeAreaProvider>
      <NavigationContainer>...</NavigationContainer>
      {Platform.OS === 'android' && <SafeAreaView mode="margin" edges={['bottom']} />}
    </SafeAreaProvider>
  )
}

如果使用 hybrid-navigation 作为导航组件,则不需要做任何事情,因为它已经帮你处理好了。

Usage

使用 KeyboardInsetsView 代替 View 作为容器,或者使用 KeyboardInsetsViewScrollView 包裹起来。当键盘显示或隐藏时,KeyboardInsetsView 会自动调整自身的位置,以保证输入框不被键盘遮挡。

import { KeyboardInsetsView } from '@sdcx/keyboard-insets'

function MyComponent() {
  return (
    <KeyboardInsetsView extraHeight={16} style={{ flex: 1 }}>
      <ScrollView>
        ...
        <TextInput />
        ...
      </ScrollView>
    </KeyboardInsetsView>
  )
}

Support Nested.

import { KeyboardInsetsView } from '@sdcx/keyboard-insets'

function MyComponent() {
  return (
    <KeyboardInsetsView extraHeight={16} style={{ flex: 1 }}>
      ...
      <KeyboardInsetsView extraHeight={8}>
        <TextInput />
      </KeyboardInsetsView>
      ...
    </KeyboardInsetsView>
  )
}

KeyboardInsetsView 本质上是个 View,所以你可以使用 View 的所有属性,也可以和 View 互相替换。

KeyboardInsetsView 仅有少量几个属性:

  • extraHeight:自动模式下,键盘总是紧贴着输入框的下边缘,这个属性设置输入框距离键盘的额外高度。KeyboardInsetsView 的最大偏移受键盘高度限制,若加入额外高度后,KeyboardInsetsView 偏移距离大于键盘高度,将产生截断,此时 KeyboardInsetsView 偏移距离等于键盘高度,底部将与键盘顶部相贴

  • explicitly:仅对 iOS 生效,自动模式下,是否显式地跟随键盘位置变化。默认为 false,通过隐式动画来处理。

  • onKeyboard:是个回调函数,一旦设置,就进入手动模式,KeyboardInsetsView 不会帮你调整输入框的位置。你需要利用这个回调函数实现自己想要的效果。

    onKeyboard 的参数声明如下:

    interface KeyboardState {
      height: number // 键盘的高度,不会因为键盘隐藏而变为 0
      shown: boolean // 当键盘将隐已隐时,这个值为 false;当键盘将显已显时,这个值为 true
      transitioning: boolean // 键盘是否正在显示或隐藏
      position: Animated.Value // 键盘的位置,从 0 到 height,可以用来实现动画效果
    }

API

  • useKeyboard

    为了方便用户编写 onKeyboard 回调,keyboard-insets 提供了一个 useKeyboard hook,使用方法如下:

    import { useKeyboard } from '@sdcx/keyboard-insets'
    
    function MyComponent() {
      const { keyboard, onKeyboard } = useKeyboard()
    
      console.log(keyboard.height), // 键盘的高度
    
      return (
        <KeyboardInsetsView onKeyboard={onKeyboard}>
          <TextInput />
        </KeyboardInsetsView>
      )
    }
  • getEdgeInsetsForView

    有时候你需要知道某个 View 距离屏幕四边的距离,这个时候就可以使用 getEdgeInsetsForView 方法。

    import { getEdgeInsetsForView } from '@sdcx/keyboard-insets'
    
    function MyComponent() {
      const inputRef = useRef<TextInput>(null)
    
      const onLayout = useCallback(() => {
        const viewTag = findNodeHandle(inputRef.current)
        if (viewTag === null) {
          return
        }
    
        // 获得 TextInput 距离屏幕四边的距离
        getEdgeInsetsForView(viewTag, insets => {
          console.log('insets', insets)
        })
      }, [])
    
      return (
        <View>
          <TextInput ref={inputRef} onLayout={onLayout} />
        </View>
      )
    }

Caution

如果你在项目中同时使用了react-native-bars,那么在初始化它的时候,需要把它内置的键盘处理逻辑关闭:

// in MainActivity.java

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    // ...other code
    super.onCreate(savedInstanceState);
    RNBars.init(this, "dark-content", false); // <- 第三个参数必须要设置为false
    // ...other code
  }