Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

auto text direction (based on the entered text) in flutter text and text field widgets

Tags:

flutter

I'm make a multi language application in flutter (ar/en), so i want to display my content in these languages, my problem is the text direction is based on the ui language, i want to change the direction dynamically based on the content if ar should be rtl, other wise ltr.

My current view My current view

desired effect desired effect

class ArticleCard extends StatelessWidget {
  const ArticleCard({
    Key key,
    @required this.article,
    @required this.isAuthor,
    @required this.onDelete,
    @required this.onEdit,
    this.allowComments = true,
  }) : super(key: key);
  final ArticleModel article;
  final bool isAuthor;
  final bool allowComments;
  final VoidCallback onDelete;
  final VoidCallback onEdit;

  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.only(bottom: 10),
      child: Column(
        children: <Widget>[
          InkWell(
            onTap: () {
              ExtendedNavigator.ofRouter<Router>().pushNamed(
                Routes.article,
                arguments: ArticleScreenArguments(article: article),
              );
            },
            child: Column(
              children: <Widget>[
                ListTile(
                  leading: CircleAvatar(
                    backgroundImage:
                        CachedNetworkImageProvider(article.owner.avatar),
                  ),
                  title: Text(article.title),
                  subtitle: Text(
                    article.owner.name,
                    textScaleFactor: .75,
                  ),
                  trailing: Text(
                    '${DateFormat('d, MMMM y  h:mm a', 'ar').format(article.createdAt)}',
                    textScaleFactor: .7,
                  ),
                ),
                SizedBox(
                  width: MediaQuery.of(context).size.width,
                  child: Padding(
                    padding: EdgeInsets.symmetric(horizontal: 8),
                    child: Text(
                      article.content,
                      textAlign: TextAlign.start,
                    ),
                  ),
                ),
              ],
            ),
          ),
          SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              FavoriteButton(
                isFavorite: article.isFavorite,
                count: article.favoriteCount,
                type: FavoriteType.article,
                targetId: article.id,
              ),
              _buildLabeledIcon(
                icon: Icon(Icons.message),
                label: '${article.commentsCount}',
              ),
              _buildLabeledIcon(
                icon: Icon(Icons.share),
                label: '${article.shares}',
              ),
              _buildLabeledIcon(
                icon: Icon(Icons.remove_red_eye),
                label: '${article.views}',
              ),
            ],
          ),
          SizedBox(height: 10),
          Container(
            height: 1.5,
            color: Colors.black12,
          ),
          if (isAuthor)
            _buildAuthorRow(),
          // Divider(),
          if (allowComments) ...[
            SizedBox(height: 10),
            _buildCommentsSection(context),
          ]
        ],
      ),
    );
  }

  Row _buildAuthorRow() {
    return Row(
      children: <Widget>[
        Expanded(
          child: InkWell(
            onTap: onEdit,
            child: Container(
              height: 50,
              alignment: Alignment.center,
              child: Text(
                'تعديل',
                style: TextStyle(
                  color: appTheme.accentColor,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
          ),
        ),
        Container(
          width: 1.5,
          height: 50,
          color: Colors.black12,
        ),
        Expanded(
          child: InkWell(
            onTap: onDelete,
            child: Container(
              height: 50,
              alignment: Alignment.center,
              child: Text(
                'حذف',
                style: TextStyle(
                  color: appTheme.errorColor,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }

  Row _buildLabeledIcon({Widget icon, String label}) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.end,
      children: <Widget>[
        icon,
        SizedBox(width: 5),
        Text(
          label,
          textScaleFactor: .75,
        ),
      ],
    );
  }

  Widget _buildCommentsSection(BuildContext context) {
    return Column(
      children: [
        if (article.comments.isNotEmpty)
          CommentTile(comment: article.comments.first),
        _buildCommentTextInput(context),
      ],
    );
  }

  Widget _buildCommentTextInput(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Row(
        children: <Widget>[
          IconButton(
            icon: Icon(FontAwesomeIcons.paperPlane),
            onPressed: () {},
          ),
          Flexible(
            child: TextField(
              decoration: InputDecoration(
                hintText: 'كتابة تعليق',
                filled: true,
                fillColor: Color(0xFFEFEFEF),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.all(Radius.circular(50)),
                  borderSide: BorderSide.none,
                ),
                contentPadding: EdgeInsets.all(12),
              ),
              onSubmitted: (_) {},
              onTap: () {},
            ),
          ),
        ],
      ),
    );
  }
}

class CommentTile extends StatelessWidget {
  final CommentModel comment;

  const CommentTile({Key key, this.comment}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        ListTile(
          leading: CircleAvatar(
            backgroundImage: CachedNetworkImageProvider(comment.user.avatar),
          ),
          title: Text(comment.user.name),
          subtitle: Text(
            DateFormat.yMEd().format(comment.createdAt),
            textScaleFactor: .75,
          ),
        ),
        SizedBox(
          width: MediaQuery.of(context).size.width,
          child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 8),
            child: Text(
              comment.text,
              textAlign: TextAlign.end,
            ),
          ),
        ),
      ],
    );
  }
}
like image 416
XgamersX xd Avatar asked Jun 20 '20 12:06

XgamersX xd


2 Answers

You must add intl package to your project, and use this code as AppTextField whole of your app:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart' as intl;

class AppTextField extends StatefulWidget {
  final int maxLines;
  final String title;
  final TextInputType? textInput;
  final bool autoFocus;
  final TextInputAction inputAction;

  AppTextField(this.title,
      {this.maxLines: 1,
      this.textInput,
      this.autoFocus: false,
      this.inputAction: TextInputAction.next});

  @override
  State<StatefulWidget> createState() => AppTextFieldSate();
}

class AppTextFieldSate extends State<AppTextField> {
  String? text = '';

  bool isRTL(String text) {
    return intl.Bidi.detectRtlDirectionality(text);
  }

  @override
  Widget build(BuildContext context) => Container(
      margin: EdgeInsets.symmetric(vertical: 10),
      child: TextField(
          textDirection: isRTL(text!) ? TextDirection.rtl : TextDirection.ltr,
          textInputAction: widget.inputAction,
          keyboardType: widget.textInput,
          autofocus: widget.autoFocus,
          maxLines: widget.maxLines,
          decoration: InputDecoration(
            labelText: widget.title,
          ),
          onChanged: (value) {
            setState(() {
              text = value;
            });
          }));
}

I hope it is useful :)

like image 146
Ehsan Kalali Avatar answered Nov 15 '22 05:11

Ehsan Kalali


  • If you have no way of detecting the current language the user of the app is using, you can try the firebase ml lnaguage detection kit which will help you detect the language of the post

  • With that based on the detected language you set the textAlign property of the Text widget to TextAlign.left or TextAlign.right

i.e

Text("$content", textAlign: lang=='ar'?TextAlign.right:TextAlign.left )
like image 20
Mich25educ Avatar answered Nov 15 '22 06:11

Mich25educ