Skip to content

WidgetSpans in RTL text laying out LTR if they occur on the same line #54400

Closed

Description

@mimbrown

Related issue: #111381

Steps to Reproduce

Run the following app:

import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Widget Test',
      home: TestWidgetSpans(),
    );
  }
}

class TestWidgetSpans extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        body: Center(
          child: Text.rich(
            TextSpan(
              text: 'هذا اختبار',
              style: TextStyle(
                backgroundColor: Colors.grey.withOpacity(0.5),
                fontSize: 30,
              ),
              children: [
                WidgetSpan(
                  child: Container(
                    width: 30.0,
                    color: Colors.blue.withOpacity(0.5),
                    child: Center(
                      child: Text('1'),
                    ),
                  ),
                ),
                TextSpan(text: ' و '),
                WidgetSpan(
                  child: Container(
                    width: 50.0,
                    color: Colors.red.withOpacity(0.5),
                    child: Center(
                      child: Text('2'),
                    ),
                  ),
                ),
                TextSpan(text: ' ثم '),
                WidgetSpan(
                  child: Container(
                    width: 70.0,
                    color: Colors.green.withOpacity(0.5),
                    child: Center(
                      child: Text('3'),
                    ),
                  ),
                ),
                TextSpan(text: ' ، لكنه معطل'),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Expected results:
The 1, 2, and 3 widgets laid out RTL.

Image

Actual results:
Screenshot_1586469450

Logs
[√] Flutter (Channel stable, v1.12.13+hotfix.9, on Microsoft Windows [Version 10.0.18362.720], locale en-US)
    • Flutter version 1.12.13+hotfix.9 at C:\src\flutter
    • Framework revision f139b11009 (10 days ago), 2020-03-30 13:57:30 -0700
    • Engine revision af51afceb8
    • Dart version 2.7.2


[√] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    • Android SDK at C:\Users\mimbr\AppData\Local\Android\Sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.3
    • ANDROID_HOME = C:\Users\mimbr\AppData\Local\Android\Sdk
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)
    • All Android licenses accepted.

[√] Android Studio (version 3.5)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 44.0.1
    • Dart plugin version 191.8593
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)

[√] VS Code (version 1.44.0)
    • VS Code at C:\Users\mimbr\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.9.1

[√] Connected device (1 available)
    • sdk gphone x86 • emulator-5554 • android-x86 • Android R (API 29) (emulator)

• No issues found!

Activity

  1. iapicca commented on Apr 13, 2020

    @iapicca

    Hi @mimbrown
    from the docs lines 98 - 108
    I have the impression that the text textDirection still needs to be set like in this sample.

    Does this solve the issue?
    thank you

  2. added
    in triagePresently being triaged by the triage team
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Apr 13, 2020
  3. mimbrown commented on Apr 13, 2020

    @mimbrown
    Author

    Hi @iapicca, thanks for your response. I tried what you suggested and it did not resolve the problem. Text.rich just builds the RichText internally, and from what I see in the source (lines 5103-5117, line 5164 here), RichText defaults to the ambient directionality if none is passed, which in this case would be RTL. I think it may be an issue with how placeholder slots are filled after the the paragraph is layed out?

  4. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Apr 13, 2020
  5. TahaTesser commented on Apr 14, 2020

    @TahaTesser
    Contributor

    For some reason uneven layout

    flutter_01

    flutter doctor -v
    [✓] Flutter (Channel dev, v1.18.0-dev.5.0, on Mac OS X 10.15.4 19E287, locale
        en-GB)
        • Flutter version 1.18.0-dev.5.0 at /Users/taha/Code/flutter_dev
        • Framework revision 7f56b53de4 (2 days ago), 2020-04-12 12:00:01 -0400
        • Engine revision beb8a7ec48
        • Dart version 2.8.0 (build 2.8.0-dev.20.0 89b0f67261)
     
    [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
        • Android SDK at /Users/taha/Code/sdk
        • Platform android-29, build-tools 29.0.3
        • ANDROID_HOME = /Users/taha/Code/sdk
        • Java binary at: /Applications/Android
          Studio.app/Contents/jre/jdk/Contents/Home/bin/java
        • Java version OpenJDK Runtime Environment (build
          1.8.0_212-release-1586-b4-5784211)
        • All Android licenses accepted.
    [✓] Xcode - develop for iOS and macOS (Xcode 11.4)
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Xcode 11.4, Build version 11E146
        • CocoaPods version 1.9.1
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    [✓] Android Studio (version 3.6)
        • Android Studio at /Applications/Android Studio.app/Contents
        • Flutter plugin version 45.1.1
        • Dart plugin version 192.7761
        • Java version OpenJDK Runtime Environment (build
          1.8.0_212-release-1586-b4-5784211)
    [✓] VS Code (version 1.44.0)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.9.1
    [✓] Connected device (4 available)
        • SM M305F   • 32003c30dc19668f • android-arm64  • Android 10 (API 29)
        • macOS      • macOS            • darwin-x64     • Mac OS X 10.15.4 19E287
        • Chrome     • chrome           • web-javascript • Google Chrome
          81.0.4044.92
        • Web Server • web-server       • web-javascript • Flutter Tools
    • No issues found!
    
  6. added
    a: internationalizationSupporting other languages or locales. (aka i18n)
    a: qualityA truly polished experience
    a: typographyText rendering, possibly libtxt
    frameworkflutter/packages/flutter repository. See also f: labels.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    and removed
    in triagePresently being triaged by the triage team
    on Apr 14, 2020
  7. AhmedNourJamalElDin commented on Apr 27, 2020

    @AhmedNourJamalElDin

    Have you found any solution to this, @mimbrown ?
    I'm also facing this issue

  8. mimbrown commented on Apr 27, 2020

    @mimbrown
    Author

    Hi @AhmedNourJamalElDin, I ended up splitting my text on spaces and wrapping each individual word in its own Text widget, then laying out the paragraphs with a Wrap widget. It solved all the layout issues I was facing, but it kills the ability to effectively put LTR text inside RTL and is slower, probably because it's creating so many widgets.

  9. 55 remaining items

  10. molchanovia commented on Oct 6, 2026

    @molchanovia
    Contributor

    Hi, I fixed this behavior here and this is already in the main branch.

    No changes to hit testing or ordering are required on the Flutter side. I'm adding tests for coverage here, although it might not be necessary since the changes were only in Skia #193894

    Before After
    Image Image

    I’d like some input from the Flutter team: this change explicitly corrects the order of spans, which could be a breaking change for users building apps with RTL languages. Should we highlight this in the changelog?

    Open to discussion.

  11. Renzo-Olivares commented on Oct 16, 2026

    @Renzo-Olivares
    Contributor

    Hi @meg4cyberc4t, thank you for resolving this long standing issue!

    I think we should definitely highlight this in the changelog! Since this fix targets long-standing buggy behavior that has been worked around / compensated for years(from 2020, and the Transform.translate swap from this thread now re-introduces the bug on 3.50), I'd suggest we treat it as a courtesy breaking change per Tree-hygiene. No contributed tests broke, but this is the "we can nonetheless imagine reasonable scenarios where developers would be affected negatively" case: c: API break label, an announcement, and a short migration guide. One note is that our compatibility policy points out we don't have a commitment to breaking changes in dependencies which Skia/SkParagraph are, but I think in this case it would be good to add visibility to this change given the age of the issue.

    I think the closest precedent is the Impeller GLES render-to-texture top-down change in 3.47 (#186556): an engine-level fix for a long-standing orientation inconsistency, no API change, where shader authors had compensated with a Y-flip that the fix then inverted. It shipped with a migration guide (opengles-render-to-texture-top-down) that scopes exactly who is affected, and shows before/after.

    I propose a small breaking change / migration guide using the standard template (under "Not yet released to stable", landed in 3.50.0‑0.1.pre), noting that WidgetSpans in RTL text now follow bidi visual order. The guidance would be: remove any compensation for the old source-order layout — Transform.translate/GlobalKey same-line swap hacks, reversed WidgetSpan source order for RTL, or mirrored placeholder-box x‑coordinates — since those now re-introduce the bug.

  12. added
    c: API breakBackwards-incompatible API changes
    r: fixedIssue is closed as already fixed in a newer version
    on Oct 16, 2026
  13. Renzo-Olivares commented on Oct 23, 2026

    @Renzo-Olivares
    Contributor

    Closing as fixed since flutter/website#13988 has landed. Thank you @meg4cyberc4t for the great migration guide!

  14. github-actions commented on Nov 6, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  15. locked as resolved and limited conversation to collaborators on Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: internationalizationSupporting other languages or locales. (aka i18n)a: qualityA truly polished experiencea: typographyText rendering, possibly libtxtc: API breakBackwards-incompatible API changesfound in release: 3.10Found to occur in 3.10found in release: 3.7Found to occur in 3.7frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-text-inputOwned by Text Input teamtriaged-text-inputTriaged by Text Input team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions