Search code examples
flutterabstract-classrichtext

Flutter Fill in Blank with RichText


I am almost done with fill in blanks implementation for my app but unfortunately I keep running into layout issues.

However as I keep solving the issues I am almost done with it, this is the code so far:

                        RichText(
                            text: TextSpan(
                                text: "dummy",
                                style: TextStyle(
                                    color: Colors.white,
                                    fontSize: 20,
                                    height: 1.5,
                                    fontWeight: FontWeight.bold),
                                children: <InlineSpan>[
                                  TextSpan(
                                      text:
                                          ' to  to  to  to gdfgdfgdf to  to  to  to  to  to  to  ',
                                      style: TextStyle(
                                          height: 1.0,
                                          color: Colors.grey,
                                          fontSize: 20,
                                          fontWeight: FontWeight.bold)),
                                  WidgetSpan(
                                    alignment: PlaceholderAlignment.middle,
                                    child: SecretWord("turtle"),
                                  ),
                                  TextSpan(
                                      text:
                                          ' to  to  to  to gdfgdfgdf to  to  to  to  to  to  to  ',
                                      style: TextStyle(
                                          height: 1.0,
                                          color: Colors.grey,
                                          fontSize: 20,
                                          fontWeight: FontWeight.bold)),
                            )

And my SecretWord class:

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';

class SecretWord extends StatelessWidget {

    final String answer;
    int answerLength;
    String answerHint;
    double answerWidth;

    SecretWord(this.answer){
        this.answerLength = answer.length;
        this.answerHint = '.' * answerLength;
        this.answerWidth = this.answerLength * 15.0;
    }

    String value = "";

    @override
    Widget build(BuildContext context) {
        return Container(
            //alignment: Alignment.bottomCenter,
            width: answerWidth,
            height: null,

          //  margin: const EdgeInsets.only(right: 10, left: 10),
            child: TextFormField(
                maxLines: null,
                cursorColor: Colors.cyanAccent,
                cursorRadius: Radius.circular(12.0),
                cursorWidth: 2.0,
                style: TextStyle(
                    color: (value == answer) ? Colors.amberAccent : Colors.lightGreenAccent,
                    fontWeight: FontWeight.bold,
                    fontSize: 20,
                    letterSpacing: 3,
                  //  height: 0.5,
                ),
                //textAlign: TextAlign.left,
                autofocus: false,
                maxLength: answerLength,
                onChanged: (text) {
                    value = text;

                },

                decoration: new InputDecoration(

                    //labelText: 'Name *',
                    border: InputBorder.none,
                    focusedBorder: InputBorder.none,
                    enabledBorder: InputBorder.none,
                    errorBorder: InputBorder.none,
                    disabledBorder: InputBorder.none,
                    counterText: '',
                    hintText: answerHint,
                    hintStyle: TextStyle(

                        color: Colors.lightGreenAccent,
                        fontWeight: FontWeight.bold,
                        letterSpacing: 4,
                       // height: 0.5,
                    ),
                )
            )
        );
    }
}

Unfortunately this create some issues: the container height of SecretWord is superior to TextSpan, how could I succeed to reduce the height of the Container with TextFormField to match the height of TextSpan ?

enter image description here

Notice that the second line has more space with first and third line than what I was expecting, it is because SecretWord is considered to take more space vertically. I know the cause but not how to solve it.


Solution

  • Hello I've come up with a solution to reduce the inner padding of TextField/TextFormField which looks like your problem.

    Setting these values for the InputDecoration of the TextField should remove the vertical padding:

         TextFormField(
              decoration: InputDecoration(
              isDense: true,
              contentPadding: const EdgeInsets.symmetric(vertical: -5),
              counterText: '',
            ),
          )
    

    isDense=true makes the input is part of dense form (i.e., uses less vertical /// space).

    setting contentPadding: const EdgeInsets.symmetric(vertical: -5) will reduce the vertical padding

    As you already did in your example counterText: '' will prevent the counter text being shown.

    So here is your new SecretWordClass with the changes. I also moved the properties under the build method since stateless widgets are immutable and their properties should be final.

    import 'dart:ui';
    import 'package:flutter/material.dart';
    import 'package:flutter/painting.dart';
    
    class SecretWord extends StatelessWidget {
      final String answer;
    
      SecretWord(this.answer);
    
      @override
      Widget build(BuildContext context) {
        String value = "";
        int answerLength = answer.length;
        String answerHint = '.' * answerLength;
        double answerWidth = answerLength * 15.0;
        return Container(
          width: answerWidth,
          height: null,
          child: TextFormField(
            maxLines: null,
            cursorColor: Colors.cyanAccent,
            cursorRadius: Radius.circular(12.0),
            cursorWidth: 2.0,
            style: TextStyle(
              color:
                  (value == answer) ? Colors.amberAccent : Colors.lightGreenAccent,
              fontWeight: FontWeight.bold,
              fontSize: 20,
              letterSpacing: 3,
            ),
            autofocus: false,
            maxLength: answerLength,
            onChanged: (text) {
              value = text;
            },
            decoration: new InputDecoration(
              isDense: true,
              contentPadding: const EdgeInsets.symmetric(vertical: -5),
              counterText: '',
              border: InputBorder.none,
              focusedBorder: InputBorder.none,
              enabledBorder: InputBorder.none,
              errorBorder: InputBorder.none,
              disabledBorder: InputBorder.none,
              hintText: answerHint,
              hintStyle: TextStyle(
                color: Colors.lightGreenAccent,
                fontWeight: FontWeight.bold,
                letterSpacing: 4,
              ),
            ),
          ),
        );
      }
    }
    

    Here are the results: enter image description here