将百分比宽度的记录设置为父级堆栈,其宽度取决于其他子元素。

huangapple go评论66阅读模式
英文:

Set percentage width recording to parent stack, whose width depends on other child

问题

I am having a Stack with two child elements. The second element is some Text and the first element is a Container with some blue background color. I want to have the height of the Container match the height of the Stack given by the height of the Text-Widget. And the width of my Container should be set dynamically with a percentage of the width of the Stack which also comes from the Text widget.

In other words: I want to build a progress indicator, that I can set dynamically. Altough the width of my parent is not known before build-time. And this width should be givene by the text-child-widget.

How can I achieve that?

英文:

I am having a Stack with two child elements. The second element is some Text and the first element is a Container with some blue background color. I want to have the height of the Container match the height of the Stack given by the height of the Text-Widget. And the width of my Container should be set dynamically with a percentage of the width of the Stack which also comes from the Text widget.

In other words: I want to build a progress indicator, that I can set dynamically. Altough the width of my parent is not known before build-time. And this width should be givene by the text-child-widget.

How can I achieve that?

将百分比宽度的记录设置为父级堆栈,其宽度取决于其他子元素。

Stack(
  alignment: Alignment.centerLeft,
  clipBehavior: Clip.none,
  children: [
    Container(
        width: 50,
        height: 20,
        color: const Color(0xffa0a4fc),
    ),
    Padding(
      padding: const EdgeInsets.symmetric(horizontal: 25),
      child: Text(
        "some text",
        style: const TextStyle(
          color: Colors.black,
          fontWeight: FontWeight.bold,
          fontSize: 22,
        ),
      ),
    ),
)

答案1

得分: 1

下面是您要翻译的代码部分:

你需要计算文本宽度:

final TextPainter myTextPainter = TextPainter(
      text:
          TextSpan(text: myText, style: Theme.of(context).textTheme.labelLarge),
      textDirection: TextDirection.ltr,
    )..layout(maxWidth: MediaQuery.of(context).size.height, minWidth: 0.0);

final myTextSize = myTextPainter.size;

完整代码供您参考:

import 'package:flutter/material.dart';

class Example extends StatefulWidget {
  const Example({super.key});

  @override
  State<Example> createState() => _ExampleState();
}

class _ExampleState extends State<Example> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  String myText = 'loading.. please wait';
  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(vsync: this, duration: const Duration(seconds: 3));
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final TextPainter myTextPainter = TextPainter(
      text:
          TextSpan(text: myText, style: Theme.of(context).textTheme.labelLarge),
      textDirection: TextDirection.ltr,
    )..layout(maxWidth: MediaQuery.of(context).size.height, minWidth: 0.0);

    final myTextSize = myTextPainter.size;

    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        ElevatedButton(
            onPressed: () {
              if (!_animationController.isAnimating) {
                setState(() {
                  myText = 'loading.. please wait';
                });
                _animationController.reset();
                _animationController.forward().then((value) {
                  setState(() {
                    myText = 'loading.. completed';
                  });
                });
              }
            },
            child: const Text("Start Animating")),
        SizedBox(
          width: MediaQuery.of(context).size.width,
          height: 10.0,
        ),
        Container(
          decoration: BoxDecoration(border: Border.all(color: Colors.blue)),
          child: Padding(
            padding: const EdgeInsets.all(10.0),
            child: Stack(
              fit: StackFit.loose,
              children: [
                AnimatedBuilder(
                    animation: _animationController,
                    builder: (context, _) {
                      return Container(
                        color: Colors.blue,
                        height: myTextSize.height,
                        width: (_animationController.value * myTextSize.width),
                      );
                    }),
                Text(
                  myText,
                  style: Theme.of(context).textTheme.labelLarge,
                )
              ],
            ),
          ),
        )
      ],
    );
  }
}

请注意,这是您提供的代码的翻译版本。如果您有任何其他问题或需要进一步的帮助,请随时告诉我。

英文:

将百分比宽度的记录设置为父级堆栈,其宽度取决于其他子元素。

you need to calculate text width :

final TextPainter myTextPainter = TextPainter(
text:
TextSpan(text: myText, style: Theme.of(context).textTheme.labelLarge),
textDirection: TextDirection.ltr,
)..layout(maxWidth: MediaQuery.of(context).size.height, minWidth: 0.0);
final myTextSize = myTextPainter.size;

full code for your reference :

import &#39;package:flutter/material.dart&#39;;
class Example extends StatefulWidget {
const Example({super.key});
@override
State&lt;Example&gt; createState() =&gt; _ExampleState();
}
class _ExampleState extends State&lt;Example&gt; with SingleTickerProviderStateMixin {
late AnimationController _animationController;
String myText = &#39;loading.. please wait&#39;;
@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: const Duration(seconds: 3));
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final TextPainter myTextPainter = TextPainter(
text:
TextSpan(text: myText, style: Theme.of(context).textTheme.labelLarge),
textDirection: TextDirection.ltr,
)..layout(maxWidth: MediaQuery.of(context).size.height, minWidth: 0.0);
final myTextSize = myTextPainter.size;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
if (!_animationController.isAnimating) {
setState(() {
myText = &#39;loading.. please wait&#39;;
});
_animationController.reset();
_animationController.forward().then((value) {
setState(() {
myText = &#39;loading.. completed&#39;;
});
});
}
},
child: const Text(&quot;Start Animating&quot;)),
SizedBox(
width: MediaQuery.of(context).size.width,
height: 10.0,
),
Container(
decoration: BoxDecoration(border: Border.all(color: Colors.blue)),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Stack(
fit: StackFit.loose,
children: [
AnimatedBuilder(
animation: _animationController,
builder: (context, _) {
return Container(
color: Colors.blue,
height: myTextSize.height,
width: (_animationController.value * myTextSize.width),
);
}),
Text(
myText,
style: Theme.of(context).textTheme.labelLarge,
)
],
),
),
)
],
);
}
}

答案2

得分: 0

根据Stack文档

> Stack小部件的每个子部件都是定位或非定位的(...). 堆栈会自动调整大小以包含所有非定位的子部件(...). 然后,根据它们的top、right、bottom和left属性,定位的子部件相对于堆栈放置。

因此,在Positioned内部使用FractionallySizedBox,然后让Text确定Stack的大小将起到作用:

Stack(
  children: [
    Positioned.fill(
      child: FractionallySizedBox(
        alignment: Alignment.centerLeft,
        widthFactor: factor,
        child: ...,
      ),
    ),
    Text(...),
  ],
)

在您的情况下,使用TextPainter计算Stack内容的大小也是正确的解决方案,但它有一些缺点:

  • 对于内容不仅仅是单个Text的更复杂情况(如上面的演示),它不起作用。
  • 它略微性能较差,因为它需要两次计算Text的大小。
英文:

Per the Stack documentation:

> Each child of a Stack widget is either positioned or non-positioned (...). The stack sizes itself to contain all the non-positioned children, (...). The positioned children are then placed relative to the stack according to their top, right, bottom, and left properties.

So, using FractionallySizedBox inside Positioned and then having the Text determine the Stack size would do the trick:

Stack(
children: [
Positioned.fill(
child: FractionallySizedBox(
alignment: Alignment.centerLeft,
widthFactor: factor,
child: ...,
),
),
Text(...),
],
)

See a demo on dartpad.dev

Using a TextPainter to calculate size of Stack's contents is also correct solution for your case but it has some drawbacks:

  • It won't work for more advanced cases where the content of the loader is something other than just single Text (as in the demo above).
  • It's slightly less performant because it needs to calculate Text's size twice.

huangapple
  • 本文由 发表于 2023年4月19日 21:50:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76055336.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定