flutterdartflutter-layoutflutter-android

What is the relation between MediaQuery.of(context) and TextField cursor position in Flutter?


This is screen code:

import 'package:flutter/material.dart';

class Model {
  String? text;

  Model(this.text);
}

class TempDialog extends StatefulWidget {

  TempDialog({Key? key}) : super(key: key);

  @override
  State<TempDialog> createState() => _TempDialogState();
}

class _TempDialogState extends State<TempDialog> {

  final model = Model("This is test text");

  @override
  Widget build(BuildContext context) {
    var textController = TextEditingController(text: model.text);
    return AlertDialog(
      content: Container(
        width: MediaQuery
            .of(context)
            .size
            .width - 50,
        height: MediaQuery
            .of(context)
            .size
            .height - 300,
        child: Column(
          children: [
            TextField(
              textAlign: TextAlign.left,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.all(10.0),
              ),
              keyboardType: TextInputType.multiline,
              maxLines: null,
              minLines: 4,
              controller: textController,
            )
          ],
        ),
      ),
    );
  }
}

class TempScreen extends StatefulWidget {

  TempScreen({Key? key}) : super(key: key);

  @override
  State<TempScreen> createState() => _TempScreenState();
}

class _TempScreenState extends State<TempScreen> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Temp screen"),
      ),
      body: Column(
        children: [
          TextButton(
              onPressed: (){
                showDialog(
                    context: context,
                    builder: (BuildContext context) {
                      return TempDialog();
                    }
                );
              },
              child: Text("Tap me"))
        ],
      ),
    );
  }
}

And this is the result:

Untitled

As you see although a user taps somewhere in the middle of the text, after keyboard appears cursor moves to start (home). The problem is in these lines:

        width: MediaQuery
            .of(context)
            .size
            .width - 50,
        height: MediaQuery
            .of(context)
            .size
            .height - 300,

If we replace them with these :

        width: 200,
        height: 200,

everything works as expected.

Could anyone explain this relation between MediaQuery.of(context) and TextField cursor position?


Solution

  • I've created the same issue on web, calling setState and requesting new focus on TextField. The solution is to use textController outside the build method.

      final model = Model("This is test text");
      final FocusNode focusNode = FocusNode();
      late TextEditingController textController = TextEditingController.fromValue(
        TextEditingValue(text: model.text ?? ""),
      );