8

I need a text field which changes its direction based on user input.

for example, I have a text field that gets the user input but this input can be sometimes an english text with left-to-right direction and sometimes an arabic text with right-to-left direction. I want text field direction to change depended on input language direction

What I have

  • Suppose I have a normal text field
class MyDynamicTextField extends StatelessWidget {
  const MyDynamicTextField({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 40),
          child: TextField(),
        ),
      ),
    );
  }
}

what i have

What I need

How can I mimic WhatsApp chat textfield or chrome textfield text-direction behavior while entering text with different languages and text directions?

e.g: Text Direction of text field changes depended on user input language (in Chrome)

Excpection

Sajad Abdollahi
  • 1,593
  • 1
  • 7
  • 19

2 Answers2

4

The solution is to change text direction based on the first input character

Create a function that recognizes right-to-left characters using their code units (utf-16) and returns a TextDirection representing the text direction of input language

TextDirection getDirection(String v) {
  final string = v.trim();
  if (string.isEmpty) return TextDirection.ltr;
  final firstUnit = string.codeUnitAt(0);
  if (firstUnit > 0x0600 && firstUnit < 0x06FF ||
      firstUnit > 0x0750 && firstUnit < 0x077F ||
      firstUnit > 0x07C0 && firstUnit < 0x07EA ||
      firstUnit > 0x0840 && firstUnit < 0x085B ||
      firstUnit > 0x08A0 && firstUnit < 0x08B4 ||
      firstUnit > 0x08E3 && firstUnit < 0x08FF ||
      firstUnit > 0xFB50 && firstUnit < 0xFBB1 ||
      firstUnit > 0xFBD3 && firstUnit < 0xFD3D ||
      firstUnit > 0xFD50 && firstUnit < 0xFD8F ||
      firstUnit > 0xFD92 && firstUnit < 0xFDC7 ||
      firstUnit > 0xFDF0 && firstUnit < 0xFDFC ||
      firstUnit > 0xFE70 && firstUnit < 0xFE74 ||
      firstUnit > 0xFE76 && firstUnit < 0xFEFC ||
      firstUnit > 0x10800 && firstUnit < 0x10805 ||
      firstUnit > 0x1B000 && firstUnit < 0x1B0FF ||
      firstUnit > 0x1D165 && firstUnit < 0x1D169 ||
      firstUnit > 0x1D16D && firstUnit < 0x1D172 ||
      firstUnit > 0x1D17B && firstUnit < 0x1D182 ||
      firstUnit > 0x1D185 && firstUnit < 0x1D18B ||
      firstUnit > 0x1D1AA && firstUnit < 0x1D1AD ||
      firstUnit > 0x1D242 && firstUnit < 0x1D244) {
    return TextDirection.rtl;
  }
  return TextDirection.ltr;
}

Now wrap the TextField inside a ValueListenableBuilder<TextDirection> and change the text direction when changing text in text field:


class MyDynamicTextField extends StatelessWidget {
  MyDynamicTextField({Key? key}) : super(key: key);

  final ValueNotifier<TextDirection> _textDir =
      ValueNotifier(TextDirection.ltr);

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 40),
          child: ValueListenableBuilder<TextDirection>(
            valueListenable: _textDir,
            builder: (context, value, child) => 

              TextField(
                textDirection: value,
                onChanged: (input) {
                  if (input.trim().length < 2) {
                    final dir = getDirection(input);
                    if (dir != value) _textDir.value = dir;
                  }
                },
              ),
            
          ),
        ),
      ),
    );
  }
}
Sajad Abdollahi
  • 1,593
  • 1
  • 7
  • 19
  • Tried this and the typing direction changes as required, but the direction rightmost word in the text does not start from the right-most side of a text widget. – ASAD HAMEED Oct 20 '21 at 07:34
  • Sorry i didn't get it, Can you make it more clear? – Sajad Abdollahi Oct 20 '21 at 14:04
  • When I started typing in Urdu the typing direction was as required ( right to left), but the first word did not appear in the right corner of the Text widget. – ASAD HAMEED Oct 21 '21 at 10:46
  • Thank you. For places that you might revisit, something like this might be useful: ```_textDir.value = getDirection(controller.text);``` Otherwise, the text field will become LTR again when initiated. – Sina Seirafi May 18 '22 at 05:26
3

there is a built in function to determine the direction of the text.

import 'package:intl/intl.dart' as intl;

final isRTL = intl.Bidi.detectRtlDirectionality("some text")
avs
  • 46
  • 4
  • Cool thing, I didn't know it or maybe it was not implemented when I posted this answer. I'm accepting your answer since it's a better way – Sajad Abdollahi Mar 14 '23 at 18:31