Flutter键盘检测插件keyboard_detection的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter键盘检测插件keyboard_detection的使用

Keyboard Detection

此插件为您提供了一种简单的方法来检测键盘是否可见。它通过底部视图内边距(inset)的调整来检查键盘的可见性,因此它是Flutter原生支持的功能。

Alt Text

简单用法

您只需像下面这样将Scaffold包裹在KeyboardDetection中,并监听onChanged值。

@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: KeyboardDetection(
      controller: KeyboardDetectionController(
        onChanged: (value) {
          print('Keyboard visibility onChanged: $value');
          setState(() {
            keyboardState = value;
            stateAsBool = keyboardDetectionController.stateAsBool();
            stateAsBoolWithParamTrue =
                keyboardDetectionController.stateAsBool(true);
          });
        },
      ),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Keyboard Detection'),
        ),
        body: Center(
          child: Column(
            children: [
              Text('State: $keyboardState'),
              Text(
                  'State as bool (includeTransitionalState = false): $stateAsBool'),
              Text(
                  'State as bool (includeTransitionalState = true): $stateAsBoolWithParamTrue'),
              const TextField(),
            ],
          ),
        ),
      ),
    ),
  );
}

onChanged将以枚举KeyboardState的形式返回(unknown:未知, visibling:显示中, visible:已显示, hiding:隐藏中, hidden:已隐藏)。

使用控制器

您可以像下面这样在build方法外部声明controller

late KeyboardDetectionController keyboardDetectionController;

@override
void initState() {
  keyboardDetectionController = KeyboardDetectionController(
    onChanged: (value) {
      print('Keyboard visibility onChanged: $value');
      setState(() {
        keyboardState = value;
        stateAsBool = keyboardDetectionController.stateAsBool();
        stateAsBoolWithParamTrue =
            keyboardDetectionController.stateAsBool(true);
      });
    },
  );

  // Listen to the stream
  _sub = keyboardDetectionController.stream.listen((state) {
    print('Listen to onChanged with Stream: $state');
  });

  // One time callback
  keyboardDetectionController.addCallback((state) {
    print('Listen to onChanged with one time Callback: $state');

    // End this callback by returning false
    return false;
  });

  // Looped callback
  keyboardDetectionController.addCallback((state) {
    print('Listen to onChanged with looped Callback: $state');

    // This callback will be looped
    return true;
  });

  // Looped with future callback
  keyboardDetectionController.addCallback((state) async {
    await Future.delayed(const Duration(milliseconds: 100));
    print('Listen to onChanged with looped future Callback: $state');

    // This callback will be looped
    return true;
  });

  super.initState();
}

并在build方法内部添加到controller:

@Override
Widget build(BuildContext context) {
  return KeyboardDetection(
    controller: keyboardDetectionController,
    child: Scaffold(
      appBar: AppBar(
        title: const Text('Keyboard Detection'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(12.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('State: $keyboardState'),
              Text('State as bool (includeTransitionalState = false): $stateAsBool'),
              Text('State as bool (includeTransitionalState = true): $stateAsBoolWithParamTrue'),
              FutureBuilder(
                future: keyboardDetectionController.ensureSizeLoaded,
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Text(
                        'Keyboard size is loaded with size: ${keyboardDetectionController.size}');
                  }

                  return const Text('Keyboard size is still loading');
                },
              ),
              const TextField(),
              ElevatedButton(
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (_) => const MyApp(),
                    ),
                  );
                },
                child: const Text('Navigate to another page'),
              ),
              ElevatedButton(
                onPressed: () {
                  Navigator.pushAndRemoveUntil(
                      context,
                      MaterialPageRoute(
                        builder: (_) => const MyApp(),
                      ),
                      (_) => false);
                },
                child: const Text('Move to another page'),
              )
            ],
          ),
        ),
      ),
    ),
  );
}

您可以使用以下方式获取当前键盘可见性的状态:

  • keyboardDetectionController.state: 返回当前键盘可见性的状态,以枚举KeyboardState的形式(unknown:未知, visibling:显示中, visible:已显示, hiding:隐藏中, hidden:已隐藏)。
  • keyboardDetectionController.stateAsBool([bool includeTransitionalState = false]): 返回当前键盘可见性的状态,以bool?的形式(null:未知, true:可见, false:隐藏)。如果includeTransitionalStatetrue,那么即使状态是visibling时也会返回true,当状态是hiding时会返回false
  • keyboardDetectionController.addCallback(callback):添加一个回调,在键盘状态改变时调用。如果回调返回true,则每次键盘改变时都会调用;如果返回false,则会被忽略。这个callback也支持Future方法。
  • keyboardDetectionController.stream:监听键盘可见性变化事件,以KeyboardState的形式。
  • keyboardDetectionController.size:获取键盘大小。请注意,这个值可能在键盘状态为可见时仍返回0,因为键盘需要时间完全显示。因此,您应该调用keyboardDetectionController.isSizeLoaded来检查键盘大小是否已经加载。从版本0.5.0开始,您可以通过await keyboardDetectionController.ensureSizeLoaded等待这个值。

局限性

  • 此包使用底部内边距来检测键盘可见性,因此不适用于浮动键盘(Issue #1

完整示例代码

// ignore_for_file: avoid_print

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:keyboard_detection/keyboard_detection.dart';

void main() {
  runApp(const MaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  KeyboardState keyboardState = KeyboardState.unknown;
  bool? stateAsBool;
  bool? stateAsBoolWithParamTrue;

  StreamSubscription<KeyboardState>? _sub;

  late KeyboardDetectionController keyboardDetectionController;

  @override
  void initState() {
    keyboardDetectionController = KeyboardDetectionController(
      onChanged: (value) {
        print('Keyboard visibility onChanged: $value');
        setState(() {
          keyboardState = value;
          stateAsBool = keyboardDetectionController.stateAsBool();
          stateAsBoolWithParamTrue =
              keyboardDetectionController.stateAsBool(true);
        });
      },
    );

    _sub = keyboardDetectionController.stream.listen((state) {
      print('Listen to onChanged with Stream: $state');
    });

    // One time callback
    keyboardDetectionController.addCallback((state) {
      print('Listen to onChanged with one time Callback: $state');

      // End this callback by returning false
      return false;
    });

    // Looped callback
    keyboardDetectionController.addCallback((state) {
      print('Listen to onChanged with looped Callback: $state');

      // This callback will be looped
      return true;
    });

    // Looped with future callback
    keyboardDetectionController.addCallback((state) async {
      await Future.delayed(const Duration(milliseconds: 100));
      print('Listen to onChanged with looped future Callback: $state');

      // This callback will be looped
      return true;
    });

    super.initState();
  }

  @override
  void dispose() {
    _sub?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return KeyboardDetection(
      controller: keyboardDetectionController,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Keyboard Detection'),
        ),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(12.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('State: $keyboardState'),
                Text(
                    'State as bool (includeTransitionalState = false): $stateAsBool'),
                Text(
                    'State as bool (includeTransitionalState = true): $stateAsBoolWithParamTrue'),
                FutureBuilder(
                  future: keyboardDetectionController.ensureSizeLoaded,
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      return Text(
                          'Keyboard size is loaded with size: ${keyboardDetectionController.size}');
                    }

                    return const Text('Keyboard size is still loading');
                  },
                ),
                const TextField(),
                ElevatedButton(
                  onPressed: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (_) => const MyApp(),
                      ),
                    );
                  },
                  child: const Text('Navigate to another page'),
                ),
                ElevatedButton(
                  onPressed: () {
                    Navigator.pushAndRemoveUntil(
                        context,
                        MaterialPageRoute(
                          builder: (_) => const MyApp(),
                        ),
                        (_) => false);
                  },
                  child: const Text('Move to another page'),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter键盘检测插件keyboard_detection的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter键盘检测插件keyboard_detection的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用keyboard_detection插件的代码示例。这个插件可以帮助你检测键盘的显示和隐藏状态,以便你可以根据这些状态调整你的UI布局。

步骤 1: 添加依赖

首先,你需要在你的pubspec.yaml文件中添加keyboard_detection插件的依赖。

dependencies:
  flutter:
    sdk: flutter
  keyboard_detection: ^0.5.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

步骤 2: 导入插件

在你的Dart文件中(通常是main.dart或者一个特定的页面文件),导入keyboard_detection插件。

import 'package:keyboard_detection/keyboard_detection.dart';

步骤 3: 使用插件

你可以使用KeyboardVisibilityBuilder小部件来检测键盘的显示和隐藏状态,并根据这些状态执行不同的操作。下面是一个简单的示例,展示如何根据键盘的显示状态来调整底部内边距。

import 'package:flutter/material.dart';
import 'package:keyboard_detection/keyboard_detection.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Keyboard Detection Example'),
        ),
        body: Padding(
          padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
          child: KeyboardVisibilityBuilder(
            builder: (context, isVisible) {
              return Column(
                children: [
                  TextField(
                    decoration: InputDecoration(
                      hintText: 'Type something...',
                    ),
                  ),
                  SizedBox(height: 20),
                  Text(
                    'Keyboard is ${isVisible ? 'visible' : 'not visible'}',
                    style: TextStyle(fontSize: 20),
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

解释

  1. KeyboardVisibilityBuilder:这是一个小部件,它接受一个builder函数,该函数返回一个小部件,并传递一个布尔值isVisible,指示键盘是否可见。

  2. MediaQuery.of(context).viewInsets.bottom:这是Flutter提供的一个方法,用于获取屏幕底部被键盘遮挡的部分的尺寸。通过将其设置为底部内边距,你可以确保你的内容不会被键盘遮挡。

  3. TextField:一个简单的输入框,用于触发键盘的显示。

  4. Text:显示键盘的可见性状态。

这个示例展示了如何使用keyboard_detection插件来检测键盘的显示状态,并根据这个状态调整UI布局。你可以根据需要进一步自定义和扩展这个示例。

回到顶部