Flutter-RadioListTile的title內(nèi)容顯示不開換行的解決方案

1.問題

最近在做一個類似答題問卷的功能,利用RadioListTile來實現(xiàn)單選。這個需求和方案本身是沒有什么問題的,本來想實現(xiàn)的效果如下所示。


最終效果圖

好的,開始碼代碼。

      Row(
            children: <Widget>[
              Flexible(
                child: RadioListTile<String>(
                    title: Text('無'),
                    groupValue: this.value,
                    value: AnswerType.none.toString(),
                    onChanged: onChange),
              ),
              Flexible(
                child: RadioListTile<String>(
                    title: Text(
                      '有一點',
                    ),
                    groupValue: this.value,
                    value: AnswerType.little.toString(),
                    onChanged: onChange),
              ),
              Flexible(
                child: RadioListTile<String>(
                    title: Text('多'),
                    groupValue: this.value,
                    value: AnswerType.more.toString(),
                    onChanged: onChange),
              ),
              Flexible(
                child: RadioListTile<String>(
                    title: Text('很多'),
                    groupValue: this.value,
                    value: AnswerType.lot.toString(),
                    onChanged: onChange),
              ),
            ],
          )

走你。我尼瑪!?


結(jié)果

2.解決過程

我嘗試了各種方法,比如把字體變小,尋找別的屬性修改都不行。


image.png

從圖上看我們需要解決的問題有兩個,1是調(diào)整選中框的內(nèi)邊距;2是調(diào)整選中框和文本之間的間距。沒辦法只能從RadioListTile源碼入手了。

const RadioListTile({
    Key? key,
    required this.value,
    required this.groupValue,
    required this.onChanged,
    this.toggleable = false,
    this.activeColor,
    this.title,
    this.subtitle,
    this.isThreeLine = false,
    this.dense,
    this.secondary,
    this.selected = false,
    this.controlAffinity = ListTileControlAffinity.platform,
    this.autofocus = false,
    this.contentPadding,
    this.shape,
    this.tileColor,
    this.selectedTileColor,
  })
2.1 解決第一個問題

看了一圈只有contentPadding這個屬性有用,他的作用是Defines the insets surrounding the contents of the tile.意思大概是控制上圖灰色背景也就是整個控件里面內(nèi)容的內(nèi)邊距。默認(rèn)是EdgeInsets.symmetric(horizontal: 16.0),我這里設(shè)置了contentPadding: EdgeInsets.all( 0.0)之后解決了第一個問題,這個時候三個字的選項還是顯示不開。

2.2 解決第二個問題

繼續(xù)研究,發(fā)現(xiàn)RadioListTile里面實際上的child是ListTile,而ListTile有個屬性是horizontalTitleGap。這個屬性的意思指的是The horizontal gap between the titles and the leading/trailing widgets.,大概意思就是說我們的文本和Radio之間的間隙,leading/trailing 指的是Radio在內(nèi)容 前/后。

    return MergeSemantics(
      child: ListTileTheme.merge(
        selectedColor: activeColor ?? Theme.of(context).accentColor,
        child: ListTile(//子類是這個Widget
          leading: leading,
          title: title,
          subtitle: subtitle,
          trailing: trailing,
          isThreeLine: isThreeLine,
          dense: dense,
          enabled: onChanged != null,
          shape: shape,
          tileColor: tileColor,
          selectedTileColor: selectedTileColor,
          onTap: onChanged != null ? () {
            if (toggleable && checked) {
              onChanged!(null);
              return;
            }
            if (!checked) {
              onChanged!(value);
            }
          } : null,
          selected: selected,
          autofocus: autofocus,
          contentPadding: contentPadding,
        ),
      ),
    );

但是RadioListTile屬性里沒有horizontalTitleGap,不能直接對它進行修改,于是需要重寫RadioListTile源碼。我們把RadioListTile的源碼復(fù)制出來改名為RadioListTileSuper,然后將修改為0,就搞定了。

3.總結(jié)

這里把源碼完整的放出來。這里需要注意的是如果你的environment: sdk: '>=2.7.0 <3.0.0'這里沒有>2.12.0你需要把源碼里的?和!都刪除掉。

3.1 修改源碼
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';


class RadioListTileSuper<T> extends StatelessWidget {
  const RadioListTileSuper({
    Key key,
    this.value,
    this.groupValue,
    this.onChanged,
    this.toggleable = false,
    this.activeColor,
    this.title,
    this.subtitle,
    this.isThreeLine = false,
    this.dense,
    this.secondary,
    this.selected = false,
    this.controlAffinity = ListTileControlAffinity.platform,
    this.autofocus = false,
    this.contentPadding,
    this.shape,
    this.tileColor,
    this.selectedTileColor,
  }) : assert(toggleable != null),
        assert(isThreeLine != null),
        assert(!isThreeLine || subtitle != null),
        assert(selected != null),
        assert(controlAffinity != null),
        assert(autofocus != null),
        super(key: key);
  final T value;
  final T groupValue;
  final ValueChanged<T> onChanged;
  final bool toggleable;
  final Color activeColor;
  final Widget title;
  final Widget subtitle;
  final Widget secondary;
  final bool isThreeLine;
  final bool dense;
  final bool selected;
  final ListTileControlAffinity controlAffinity;
  final bool autofocus;
  final EdgeInsetsGeometry contentPadding;
  bool get checked => value == groupValue;
  final ShapeBorder shape;
  final Color tileColor;
  final Color selectedTileColor;

  @override
  Widget build(BuildContext context) {
    final Widget control = Radio<T>(
      value: value,
      groupValue: groupValue,
      onChanged: onChanged,
      toggleable: toggleable,
      activeColor: activeColor,
      materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
      autofocus: autofocus,
    );
    Widget leading, trailing;
    switch (controlAffinity) {
      case ListTileControlAffinity.leading:
      case ListTileControlAffinity.platform:
        leading = control;
        trailing = secondary;
        break;
      case ListTileControlAffinity.trailing:
        leading = secondary;
        trailing = control;
        break;
    }
    return MergeSemantics(
      child: ListTileTheme.merge(
        selectedColor: activeColor ?? Theme.of(context).accentColor,
        child: ListTile(
          leading: leading,
          title: title,
          subtitle: subtitle,
          trailing: trailing,
          horizontalTitleGap:0,//和源碼的區(qū)別就是加了一個這個
          isThreeLine: isThreeLine,
          dense: dense,
          enabled: onChanged != null,
          shape: shape,
          tileColor: tileColor,
          selectedTileColor: selectedTileColor,
          onTap: onChanged != null ? () {
            if (toggleable && checked) {
              onChanged(null);
              return;
            }
            if (!checked) {
              onChanged(value);
            }
          } : null,
          selected: selected,
          autofocus: autofocus,
          contentPadding: contentPadding,
        ),
      ),
    );
  }
}
3.2 替換RadioListTileSuper
 Row(
            children: <Widget>[
              Flexible(
                child: RadioListTileSuper<String>(
                    title: Text('無'),
                    groupValue: this.value,
                    contentPadding: EdgeInsets.symmetric(horizontal: 10.0),//這里根據(jù)文本的內(nèi)容靈活處理文本距離左邊的距離
                                                                           //,因為有的字多有的字短顯示長短不一致 不美觀
                    value: AnswerType.none.toString(),
                    onChanged: onChange),
              ),
              Flexible(
                child: RadioListTileSuper<String>(
                    title: Text('有一點',),
                    groupValue: this.value,
                    contentPadding: EdgeInsets.symmetric(horizontal: 0.0),
                    value: AnswerType.little.toString(),
                    onChanged: onChange),
              ),
              Flexible(
                child: RadioListTileSuper<String>(
                    title: Text('多'),
                    groupValue: this.value,
                    contentPadding: EdgeInsets.symmetric(horizontal: 10.0),
                    value: AnswerType.more.toString(),
                    onChanged: onChange),
              ),
              Flexible(
                child: RadioListTileSuper<String>(
                    title: Text('很多'),
                    groupValue: this.value,
                    contentPadding: EdgeInsets.symmetric(horizontal: 0.0),
                    value: AnswerType.lot.toString(),
                    onChanged: onChange),
              ),
            ],
          )
3.3 最終效果圖
最終效果圖
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容