Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Add to App] Physical keyboard doesn't work on iOS simulator #92997

@samandmoore

Description

@samandmoore

Steps to Reproduce

We just upgraded from flutter 2.2.2 to flutter 2.5.3 and we're seeing the following issue.

(Using flutter stable 2.5.3 not an issue on 2.2.2)

  1. Clone https://github.com/flutter/samples
  2. cd add_to_app/plugin/flutter_module_using_plugin
  3. Run flutter pub get
  4. Modify the main.dart to add a TextFormField (or paste in the code sample below)
  5. cd add_to_app/plugin/ios_using_plugin
  6. Run pod install
  7. open IOSUsingPlugin.xcworkspace in Xcode
  8. Run on iOS simulator
  9. Tap to launch flutter view controller
  10. Tap into the text field
  11. Type on hardward keyboard

Expected results:
Typed characters show up.

Actual results:
Nothing shows up.

Code sample
// Copyright 2019 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart' as launcher;

import 'cell.dart';

/// The entrypoint for the flutter module.
void main() {
  // This call ensures the Flutter binding has been set up before creating the
  // MethodChannel-based model.
  WidgetsFlutterBinding.ensureInitialized();

  final model = CounterModel();

  runApp(
    ChangeNotifierProvider.value(
      value: model,
      child: const MyApp(),
    ),
  );
}

/// This is on alternate entrypoint for this module to display Flutter UI in
/// a (multi-)view integration scenario.
// This is unfortunately in this file due to
// https://github.com/flutter/flutter/issues/72630.
void showCell() {
  runApp(const Cell());
}

/// A simple model that uses a [MethodChannel] as the source of truth for the
/// state of a counter.
///
/// Rather than storing app state data within the Flutter module itself (where
/// the native portions of the app can't access it), this module passes messages
/// back to the containing app whenever it needs to increment or retrieve the
/// value of the counter.
class CounterModel extends ChangeNotifier {
  CounterModel() {
    _channel.setMethodCallHandler(_handleMessage);
    _channel.invokeMethod<void>('requestCounter');
  }

  final _channel = const MethodChannel('dev.flutter.example/counter');

  int _count = 0;

  int get count => _count;

  void increment() {
    _channel.invokeMethod<void>('incrementCounter');
  }

  Future<dynamic> _handleMessage(MethodCall call) async {
    if (call.method == 'reportCounter') {
      _count = call.arguments as int;
      notifyListeners();
    }
  }
}

/// The "app" displayed by this module.
///
/// It offers two routes, one suitable for displaying as a full screen and
/// another designed to be part of a larger UI.
class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Module Title',
      routes: {
        '/': (context) => const FullScreenView(),
        '/mini': (context) => const Contents(),
      },
    );
  }
}

/// Wraps [Contents] in a Material [Scaffold] so it looks correct when displayed
/// full-screen.
class FullScreenView extends StatelessWidget {
  const FullScreenView({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Full-screen Flutter with plugin'),
      ),
      body: const Contents(showExit: true),
    );
  }
}

/// The actual content displayed by the module.
///
/// This widget displays info about the state of a counter and how much room (in
/// logical pixels) it's been given. It also offers buttons to increment the
/// counter, opening the Flutter documentation via the url_launcher plugin, and
/// (optionally) close the Flutter view.
class Contents extends StatelessWidget {
  final bool showExit;

  const Contents({this.showExit = false, Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final mediaInfo = MediaQuery.of(context);

    return SizedBox.expand(
      child: Stack(
        children: [
          Positioned.fill(
            child: DecoratedBox(
              decoration: BoxDecoration(
                color: Theme.of(context).scaffoldBackgroundColor,
              ),
            ),
          ),
          const Positioned.fill(
            child: Opacity(
              opacity: .25,
              child: FittedBox(
                fit: BoxFit.cover,
                child: FlutterLogo(),
              ),
            ),
          ),
          Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Window is ${mediaInfo.size.width.toStringAsFixed(1)} x '
                  '${mediaInfo.size.height.toStringAsFixed(1)}',
                  style: Theme.of(context).textTheme.headline5,
                ),
                const SizedBox(height: 16),
                Consumer<CounterModel>(
                  builder: (context, model, child) {
                    return Text(
                      'Taps: ${model.count}',
                      style: Theme.of(context).textTheme.headline5,
                    );
                  },
                ),
                const SizedBox(height: 16),
                Consumer<CounterModel>(
                  builder: (context, model, child) {
                    return ElevatedButton(
                      onPressed: () => model.increment(),
                      child: const Text('Tap me!'),
                    );
                  },
                ),
                TextFormField(),
                ElevatedButton(
                  onPressed: () async {
                    // Use the url_launcher plugin to open the Flutter docs in
                    // a browser.
                    const url = 'https://flutter.dev/docs';
                    if (await launcher.canLaunch(url)) {
                      launcher.launch(url);
                    }
                  },
                  child: const Text('Open Flutter Docs'),
                ),
                if (showExit) ...[
                  const SizedBox(height: 16),
                  ElevatedButton(
                    onPressed: () => SystemNavigator.pop(),
                    child: const Text('Exit this screen'),
                  ),
                ],
              ],
            ),
          ),
        ],
      ),
    );
  }
}
Logs
Would this be helpful here? The issue occurs when running via Xcode, so I'm not sure how to achieve this.
Nothing to report.
[✓] Flutter (Channel stable, 2.5.3, on macOS 11.6 20G165 darwin-x64, locale en-US)
    • Flutter version 2.5.3 at /Users/sammoore/fvm/versions/2.5.3
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 18116933e7 (3 weeks ago), 2021-10-15 10:46:35 -0700
    • Engine revision d3ea636dc5
    • Dart version 2.14.4

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /Users/sammoore/Library/Android/sdk
    • Platform android-30, build-tools 30.0.2
    • ANDROID_SDK_ROOT = /Users/sammoore/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 13.0, Build version 13A233
    • CocoaPods version 1.10.0

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2020.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)

[✓] VS Code (version 1.61.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.27.0

[✓] Connected device (3 available)
    • iPhone 13 (mobile) • 4A108E15-B8E8-446B-AD4E-D0E39DC46DD6 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-15-0 (simulator)
    • macOS (desktop)    • macos                                • darwin-x64     • macOS 11.6 20G165 darwin-x64
    • Chrome (web)       • chrome                               • web-javascript • Google Chrome 95.0.4638.69

• No issues found!

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: existing-appsIntegration with existing apps via the add-to-app flowa: text inputEntering text in a text field or keyboard related problemsc: regressionIt was better in the past than it is nowengineflutter/engine related. See also e: labels.found in release: 2.5Found to occur in 2.5found in release: 2.6Found to occur in 2.6has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-iosiOS applications specificallyr: fixedIssue is closed as already fixed in a newer version

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions