skip to Main Content

I am building a Flutter app with a full screen page view.

Each page has an image and text at the bottom. I have some code to animate the page swipe animation where the next page feels like it’s appearing from behind the current page.

Everything works great, except the next page has a smaller width than the current page which increases and fits the screen as the current page is being swiped away. When the next page has a smaller width, the inner text rearranges to accommodate the smaller width, which I don’t want to happen.

Any way I can scale the text size based on width?

Here is the widget:

@override
  Widget build(BuildContext context) {
    launchURL(String readMoreURL) async {
      await FlutterWebBrowser.openWebPage(url: readMoreURL);
    }

    cardModel.read = true;

    return Container(
        color: Colors.white,
        child: Column(
          children: [
            Expanded(
              flex: 35,
              child: Image.network(
                cardModel.imageUrl,
                fit: BoxFit.cover,
                errorBuilder: (context, error, stackTrace) {
                  return Container(
                      color: const Color(0xFFF3D2BB),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          const Icon(
                            Icons.error_outline,
                            color: Color(0xFFB42D1E),
                            size: 50,
                          ),
                          const SizedBox(height: 10),
                          Text(
                            'Failed to load image',
                            style: GoogleFonts.sarabun(
                                fontSize: 16, color: const Color(0xFFB42D1E)),
                          ),
                        ],
                      ));
                },
              ),
            ),
            Expanded(
              flex: 65,
              child: Padding(
                padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    Text(
                      cardModel.title,
                      style: GoogleFonts.sarabun(
                          fontSize: 20, fontWeight: FontWeight.bold, height: 1.4),
                    ),
                    const SizedBox(height: 5),
                    Text(
                      cardModel.body,
                      style: GoogleFonts.sarabun(fontSize: 19, height: 1.4),
                    ),
                    const SizedBox(height: 10),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: [
                        Text(
                          cardModel.formattedTimestamp,
                          style: const TextStyle(
                            fontSize: 14,
                            color: Colors.grey,
                          ),
                        ),
                        const Text(
                          " • ",
                          style: TextStyle(
                            fontSize: 14,
                            color: Colors.grey,
                          ),
                        ),
                        InkWell(
                          onTap: () => launchURL(cardModel.url),
                          child: const Text(
                            "Source",
                            style: TextStyle(
                                fontSize: 14,
                                color: Colors.blue,
                                decoration: TextDecoration.underline,
                                decorationColor: Colors.blue),
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ],
        ));
  }

Here is what this looks like:
GIF

I tried wrapping the text column in FittedBox, but this is what it looks like:
FittedBox

2

Answers


  1. You could provide a width inside the FittedBox. If your text is always in a full screen you can use MediaQuery.sizeOf(context).width.

    However, for best practice, use Transform.scale() to scale the page during swipe animation instead of changing its constraint.

    class MyWidget extends StatelessWidget {
      const MyWidget({super.key});
    
      @override
      Widget build(BuildContext context) {
        return FittedBox(
          child: SizedBox(
            width: MediaQuery.sizeOf(context).width,
            child: Text(
              "Flutter is an open source framework by Google for building beautiful, "
              "natively compiled, multi-platform applications from a single codebase.",
              style: TextStyle(fontSize: 40),
            ),
          ),
        );
      }
    }
    
    Login or Signup to reply.
  2. you can use auto_size_text package. It is convenient. Following is an example with custom widget function:

    Widget buildDataText(String data,
    {double scaleFactor = 1.06,
    int? maxLines = 1,
    FontWeight? fontWeight = FontWeight.w600}) {
    
      return AutoSizeText(
        data,
        textScaleFactor: scaleFactor,
        softWrap: true,
        style: TextStyle(fontWeight: fontWeight, color: Colors.white),
        maxLines: maxLines,
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search