Flutter:Text.Rich小部件是RECTREVER RECERS,如果您添加阿拉伯语文本

发布于 2025-02-04 22:30:36 字数 1425 浏览 2 评论 0原文

请有人帮助我吗? text.Rich小部件与阿拉伯文本无法成功使用。文本方向存在问题。 让我们举个例子 当我运行应用程序时,以下代码中容器的顺序反向发生 对我来说这是一个大问题

Text.rich(
                TextSpan(
                  children: [
                    TextSpan(text: 'بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
                    WidgetSpan(
                      child: Container(
                        width: 30,
                        height: 30,
                        color: Colors.green,child:Text('1'),
                      ),
                    ),
                    TextSpan(text: 'ٱلۡحَمۡدُ لِلَّهِ رَبِّ ٱلۡعَٰلَمِينَ'),
                    WidgetSpan(
                      child: Container(
                        width: 30,
                        height: 30,
                        color: Colors.blue,child:Text('2'),
                      ),
                    ),
                    TextSpan(text: 'ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
                    WidgetSpan(
                      child: Container(
                        width: 30,
                        height: 30,
                        color: Colors.red,child:Text('3'),
                      ),
                    ),
                  ],
                ),
                textDirection: TextDirection.rtl,
              )

the green container is should be in the red and there is in the green.please can any one help me?
Text.rich widget does not work successfully with arabic text. there are a problem with the text direction.
lets give an example
when i run the app the order of the container in the below code is come reverse
that is a big problem for me

Text.rich(
                TextSpan(
                  children: [
                    TextSpan(text: 'بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
                    WidgetSpan(
                      child: Container(
                        width: 30,
                        height: 30,
                        color: Colors.green,child:Text('1'),
                      ),
                    ),
                    TextSpan(text: 'ٱلۡحَمۡدُ لِلَّهِ رَبِّ ٱلۡعَٰلَمِينَ'),
                    WidgetSpan(
                      child: Container(
                        width: 30,
                        height: 30,
                        color: Colors.blue,child:Text('2'),
                      ),
                    ),
                    TextSpan(text: 'ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
                    WidgetSpan(
                      child: Container(
                        width: 30,
                        height: 30,
                        color: Colors.red,child:Text('3'),
                      ),
                    ),
                  ],
                ),
                textDirection: TextDirection.rtl,
              )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风苍溪 2025-02-11 22:30:36

有时,最困难的问题可以通过非常简单的事情来解决。
解决这个问题可能有许多漫长而困难的方法。

[https://github.com/flutter/flutter/issues/54400#issuecomment-662558160] [1]

但是我发现的最简单方法是

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Quran',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Quran Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
   List<Widget> wrapList(List m) {
    List<Widget> myList = [];
    for (var i in m) {
      String a = i['text'] as String;
      int b = i['num'];
      List l2 = a.split(' ');
      myList.addAll(List.generate(l2.length, (e) {
        return Text(
          e == l2.length - 1 ? '${l2[e]}' : '${l2[e]} ',
          style: const TextStyle(fontSize: 18),
        );
      }));
      myList.add(
        Container(
          alignment: Alignment.center,
          width: 20,
          height: 20,
          child: Text("$b"),
          decoration: const BoxDecoration(
            color: Colors.green,
          ),
        ),
      );
    }
    return myList;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Wrap(
        children: wrapList([
          {'text': 'بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ', 'num': 1},
          {'text': 'ٱلۡحَمۡدُ لِلَّهِ رَبِّ ٱلۡعَٰلَمِينَ', 'num': 2},
          {'text': 'ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ', 'num': 3},
          {'text': 'مَٰلِكِ يَوۡمِ ٱلدِّينِ', 'num': 4},
          {'text': 'إِيَّاكَ نَعۡبُدُ وَإِيَّاكَ نَسۡتَعِينُ', 'num': 5},
          {'text': 'ٱهۡدِنَا ٱلصِّرَٰطَ ٱلۡمُسۡتَقِيمَ', 'num': 6},
          {
            'text':
                'صِرَٰطَ ٱلَّذِينَ أَنۡعَمۡتَ عَلَيۡهِمۡ غَيۡرِ ٱلۡمَغۡضُوبِ عَلَيۡهِمۡ وَلَا ٱلضَّآلِّينَ',
            'num': 7
          },
        ]),
        textDirection: TextDirection.rtl,
        crossAxisAlignment: WrapCrossAlignment.center,
      ),
      ),
    );
  }
}

Sometimes the most difficult problems can be solved by very simple things.
There may be many long and difficult ways to solve this problem.

[https://github.com/flutter/flutter/issues/54400#issuecomment-662558160][1]

But the simplest way that i found is

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Quran',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Quran Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
   List<Widget> wrapList(List m) {
    List<Widget> myList = [];
    for (var i in m) {
      String a = i['text'] as String;
      int b = i['num'];
      List l2 = a.split(' ');
      myList.addAll(List.generate(l2.length, (e) {
        return Text(
          e == l2.length - 1 ? '${l2[e]}' : '${l2[e]} ',
          style: const TextStyle(fontSize: 18),
        );
      }));
      myList.add(
        Container(
          alignment: Alignment.center,
          width: 20,
          height: 20,
          child: Text("$b"),
          decoration: const BoxDecoration(
            color: Colors.green,
          ),
        ),
      );
    }
    return myList;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Wrap(
        children: wrapList([
          {'text': 'بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ', 'num': 1},
          {'text': 'ٱلۡحَمۡدُ لِلَّهِ رَبِّ ٱلۡعَٰلَمِينَ', 'num': 2},
          {'text': 'ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ', 'num': 3},
          {'text': 'مَٰلِكِ يَوۡمِ ٱلدِّينِ', 'num': 4},
          {'text': 'إِيَّاكَ نَعۡبُدُ وَإِيَّاكَ نَسۡتَعِينُ', 'num': 5},
          {'text': 'ٱهۡدِنَا ٱلصِّرَٰطَ ٱلۡمُسۡتَقِيمَ', 'num': 6},
          {
            'text':
                'صِرَٰطَ ٱلَّذِينَ أَنۡعَمۡتَ عَلَيۡهِمۡ غَيۡرِ ٱلۡمَغۡضُوبِ عَلَيۡهِمۡ وَلَا ٱلضَّآلِّينَ',
            'num': 7
          },
        ]),
        textDirection: TextDirection.rtl,
        crossAxisAlignment: WrapCrossAlignment.center,
      ),
      ),
    );
  }
}
甜妞爱困 2025-02-11 22:30:36

那是因为您是widgetSpan textspan s之间的 s毁灭textDirection,因为widgetspan不遵循方向性,< br>
您可以用textspan替换widgetspan,它将工作我测试ID

Text.rich(
    TextSpan(
        children: [
            TextSpan(text: 'بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
            TextSpan(text: ' 1 ', style: TextStyle(
                backgroundColor: Colors.green,
            )),
            TextSpan(text: 'ٱلۡحَمۡدُ لِلَّهِ رَبِّ ٱلۡعَٰلَمِينَ'),
            TextSpan(text: ' 2 ', style: TextStyle(
               backgroundColor: Colors.blue,
            )),
            TextSpan(text: 'ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
            TextSpan(text: ' 3 ', style: TextStyle(
              backgroundColor: Colors.red,
            )),
        ],
    ),
    style: TextStyle(
        fontFamily: 'UthmanicHafs1'
    ),
    textDirection: TextDirection.rtl,
),

That's because you are WidgetSpans between TextSpans which ruins the TextDirection because WidgetSpan does not follow the directionality,
you can replace the WidgetSpan with a TextSpan and it will work I tested id

Text.rich(
    TextSpan(
        children: [
            TextSpan(text: 'بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
            TextSpan(text: ' 1 ', style: TextStyle(
                backgroundColor: Colors.green,
            )),
            TextSpan(text: 'ٱلۡحَمۡدُ لِلَّهِ رَبِّ ٱلۡعَٰلَمِينَ'),
            TextSpan(text: ' 2 ', style: TextStyle(
               backgroundColor: Colors.blue,
            )),
            TextSpan(text: 'ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
            TextSpan(text: ' 3 ', style: TextStyle(
              backgroundColor: Colors.red,
            )),
        ],
    ),
    style: TextStyle(
        fontFamily: 'UthmanicHafs1'
    ),
    textDirection: TextDirection.rtl,
),
怎言笑 2025-02-11 22:30:36
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

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

class App extends StatelessWidget {
  const App({super.key});

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

double _getYOffsetOf(GlobalKey key) {
  final box = key.currentContext!.findRenderObject() as RenderBox;

  return box.localToGlobal(Offset.zero).dy;
}

double _getXOffsetOf(GlobalKey key) {
  final box = key.currentContext!.findRenderObject() as RenderBox;
  return box.localToGlobal(Offset.zero).dx;
}

void _resolveSameRow(List<GlobalKey<_WidgetSpanWrapperState>> keys) {
  var middle = (keys.length / 2.0).floor();
  for (int i = 0; i < middle; i++) {
    var a = keys[i];
    var b = keys[keys.length - i - 1];
    var left = _getXOffsetOf(a);
    var right = _getXOffsetOf(b);
    a.currentState!.updateXOffset(right - left);
    b.currentState!.updateXOffset(left - right);
  }
}

class TestWidgetSpans extends StatelessWidget {
  const TestWidgetSpans({super.key});

  @override
  Widget build(BuildContext context) {
    final keys = <GlobalKey<_WidgetSpanWrapperState>>[];
    nextKey() {
      var key = GlobalKey<_WidgetSpanWrapperState>();
      keys.add(key);
      return key;
    }

    SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
      List<GlobalKey<_WidgetSpanWrapperState>>? sameRow;
      GlobalKey<_WidgetSpanWrapperState> prev = keys.removeAt(0);
      for (var key in keys) {
        if (_getYOffsetOf(key) == _getYOffsetOf(prev)) {
          sameRow ??= [prev];
          sameRow.add(key);
        } else if (sameRow != null) {
          _resolveSameRow(sameRow);
          sameRow = null;
        }
        prev = key;
      }
      if (sameRow != null) {
        _resolveSameRow(sameRow);
      }
    });
    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: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.red, order: 1),
                  ),
                ),
                const TextSpan(text: ' و '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.orange, order: 2),
                  ),
                ),
                const TextSpan(text: ' ثم '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.yellow, order: 3),
                  ),
                ),
                const TextSpan(text: ' ، لكنه معطل'),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.green, order: 4),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.blue, order: 5),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.purple, order: 6),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.pink, order: 7),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.lime, order: 8),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.teal, order: 9),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class WidgetSpanWrapper extends StatefulWidget {
  const WidgetSpanWrapper({super.key, required this.child});

  final Widget child;

  @override
  State<WidgetSpanWrapper> createState() => _WidgetSpanWrapperState();
}

class _WidgetSpanWrapperState extends State<WidgetSpanWrapper> {
  Offset offset = Offset.zero;

  void updateXOffset(double xOffset) {
    setState(() {
      offset = Offset(xOffset, 0);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Transform.translate(
      offset: offset,
      child: widget.child,
    );
  }
}

class TestWidgetSpan extends StatelessWidget {
  final Color color;
  final int order;

  const TestWidgetSpan({super.key, required this.color, required this.order});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color.withOpacity(0.5),
      width: 40,
      child: Center(child: Text(order.toString())),
    );
  }
}
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

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

class App extends StatelessWidget {
  const App({super.key});

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

double _getYOffsetOf(GlobalKey key) {
  final box = key.currentContext!.findRenderObject() as RenderBox;

  return box.localToGlobal(Offset.zero).dy;
}

double _getXOffsetOf(GlobalKey key) {
  final box = key.currentContext!.findRenderObject() as RenderBox;
  return box.localToGlobal(Offset.zero).dx;
}

void _resolveSameRow(List<GlobalKey<_WidgetSpanWrapperState>> keys) {
  var middle = (keys.length / 2.0).floor();
  for (int i = 0; i < middle; i++) {
    var a = keys[i];
    var b = keys[keys.length - i - 1];
    var left = _getXOffsetOf(a);
    var right = _getXOffsetOf(b);
    a.currentState!.updateXOffset(right - left);
    b.currentState!.updateXOffset(left - right);
  }
}

class TestWidgetSpans extends StatelessWidget {
  const TestWidgetSpans({super.key});

  @override
  Widget build(BuildContext context) {
    final keys = <GlobalKey<_WidgetSpanWrapperState>>[];
    nextKey() {
      var key = GlobalKey<_WidgetSpanWrapperState>();
      keys.add(key);
      return key;
    }

    SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
      List<GlobalKey<_WidgetSpanWrapperState>>? sameRow;
      GlobalKey<_WidgetSpanWrapperState> prev = keys.removeAt(0);
      for (var key in keys) {
        if (_getYOffsetOf(key) == _getYOffsetOf(prev)) {
          sameRow ??= [prev];
          sameRow.add(key);
        } else if (sameRow != null) {
          _resolveSameRow(sameRow);
          sameRow = null;
        }
        prev = key;
      }
      if (sameRow != null) {
        _resolveSameRow(sameRow);
      }
    });
    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: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.red, order: 1),
                  ),
                ),
                const TextSpan(text: ' و '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.orange, order: 2),
                  ),
                ),
                const TextSpan(text: ' ثم '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.yellow, order: 3),
                  ),
                ),
                const TextSpan(text: ' ، لكنه معطل'),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.green, order: 4),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.blue, order: 5),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.purple, order: 6),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.pink, order: 7),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.lime, order: 8),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
                WidgetSpan(
                  child: WidgetSpanWrapper(
                    key: nextKey(),
                    child: const TestWidgetSpan(color: Colors.teal, order: 9),
                  ),
                ),
                const TextSpan(text: ' اختبارات '),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class WidgetSpanWrapper extends StatefulWidget {
  const WidgetSpanWrapper({super.key, required this.child});

  final Widget child;

  @override
  State<WidgetSpanWrapper> createState() => _WidgetSpanWrapperState();
}

class _WidgetSpanWrapperState extends State<WidgetSpanWrapper> {
  Offset offset = Offset.zero;

  void updateXOffset(double xOffset) {
    setState(() {
      offset = Offset(xOffset, 0);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Transform.translate(
      offset: offset,
      child: widget.child,
    );
  }
}

class TestWidgetSpan extends StatelessWidget {
  final Color color;
  final int order;

  const TestWidgetSpan({super.key, required this.color, required this.order});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color.withOpacity(0.5),
      width: 40,
      child: Center(child: Text(order.toString())),
    );
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文