Home > front end >  Flutter: how to scale a widget so that it aligns its vertical line to the other widget
Flutter: how to scale a widget so that it aligns its vertical line to the other widget

Time:12-27

I believe it is related to the origin parameter but I didn't manage to get it working:

enter image description here

Here is my code (and its dart pad right there: https://dartpad.dev/?id=1ef23afddb2d4f73744941b1d5493047):

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Scale the scene to the red line'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

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

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  final double originRatio = 1/4;

  Widget scene({required Size size, required Color color}) {
    return Stack(children:[
        Positioned(left:0,top:0, child: SizedBox(
          width: size.width,
          height: size.height, child: Container(color: color))
        ),
        Positioned(left:size.width*originRatio,top:0, child: SizedBox(
          width: 10,
          height: size.height, child: Container(color: Colors.red))
        ),
      ]);
  }

  @override
  Widget build(BuildContext context) {
    
    const sceneSize = Size(400,200);
    const scale = 0.8;
    final origin = Offset(-sceneSize.width*originRatio*scale,0);
    
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Stack(children: [
     
        // == Scaled
        Transform.scale(
          scale: scale,
          origin: origin,
          child: scene(size: sceneSize, color: Colors.brown)
        ),
        
        // == Not scaled
        scene(size: sceneSize, color: Colors.amber)
      ])
    );
  }
}

CodePudding user response:

I am using Positioned widget to align Transform widget. The Left calculation I am using,

  double getLeftP() {
    return sceneSize.width * (1 - scale) * originRatio  
        (10 * .5 * (1 - scale)); //10 for red width
  }

And it seems working quite perfect.

Default Stack and Transform.scale are aligned to center, I am also changing it to left. And Stack widget requires size, while you've already defined scene size I am using it and to check responsiveness I needed to add another slider to check it.

Run on dartPad.

class MyHomePage extends StatefulWidget {
  final String title;

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

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final double originRatio = 1 / 4;

  Widget scene({required Size size, required Color color}) {
    return SizedBox(
      width: size.width,
      height: size.height,
      child: Stack(alignment: Alignment.centerLeft, children: [
        Positioned(
          left: 0,
          top: 0,
          child: SizedBox(
            width: size.width,
            height: size.height,
            child: Container(color: color),
          ),
        ),
        Positioned(
          left: size.width * originRatio,
          top: 0,
          child: SizedBox(
            width: 10,
            height: size.height,
            child: Container(color: Colors.red),
          ),
        ),
      ]),
    );
  }

  final sceneSize = const Size(400, 200);

  double scale = 0.3;

  double getLeftP() {
    return sceneSize.width * (1 - scale) * originRatio  
        (10 * .5 * (1 - scale)); //10 for red width
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: [
          Slider(
            value: scale,
            onChanged: (value) {
              setState(() {
                scale = value;
              });
            },
          ),
          SizedBox(
            height: sceneSize.height,
            width: sceneSize.width,
            child: Stack(
              alignment: Alignment.centerLeft,
              children: [
                // == Not scaled
                scene(size: sceneSize, color: Colors.amber),

                // == Scaled
                Positioned(
                  left: getLeftP(),
                  child: Transform.scale(
                    alignment: Alignment.centerLeft,
                    scale: scale,
                    child: scene(
                      size: sceneSize,
                      color: Colors.brown,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
  • Related