Flutter:根据当前子项调整PageView / Horizo​​ntal ListView的高度 [英] Flutter: adjust height of PageView/Horizontal ListView based on current child

查看:347
本文介绍了Flutter:根据当前子项调整PageView / Horizo​​ntal ListView的高度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建高度可变的轮播。当使用PageView或ListView进行水平滚动时,我需要给它一个恒定的高度,例如:

I'm trying to create a carousel with items of variable heights. When using PageView or ListView with horizontal scrolling, I need to give it a constant height, like this:

class CarouselVariableHightState extends State<CarouselVariableHight> {
  double height = 200;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Carousel')),
      body: ListView(
        children: <Widget>[
          Text('My Carousel'),
          Container(
            height: height,
            child: PageView(
              children: <Widget>[
                _buildCarouselItem(),
                _buildCarouselItem(),
                _buildCarouselItem(),
                _buildCarouselItem(),
              ],
            ),
          ),
          Text('end of List')
        ],
      ),
    );
  }

  Widget _buildCarouselItem() {
    return Column(
      children: [
        Container(
          color: Colors.red,
          height: Random().nextInt(200).toDouble(),
          child: Text('Text with random length')
        )
      ]
    );
  }
}

但是我的商品包含文字,我不知道它的长度。我不想限制CarouselItem的高度,因为它可能会截断文本。我怎么能像PageView这样的东西根据当前显示的项目调整其自身的大小?

But my items contain text and I don't know the length of it. I don't wan't to limit the height of a CarouselItem because it might cut off the text. How could I have something like a PageView, that adjust its own size based on the currently shown item?

我认为一个解决方案是提高CarouselItem的高度,然后将其设置为PageView的高度。但是我想不出一种方法来提高我当前的轮播项目的高度。

I thought a solution could be to get the height of the CarouselItem and then set it to the height of the PageView. However I couldn't figure out a way to get the height my current Carousel item.

任何想法?

推荐答案

有2种可能的解决方案:一种是正确的,一种是hacky。

There are 2 possible solutions: right one and hacky one.


  1. 正确的解决方案:
    因为PageView试图获取所有可能的高度,所以我们不能在没有高度的任何小部件内使用它。因此,如果我们没有高度,则需要使用其他小部件,例如StackWidget并重新创建PageView行为:滑动,动画等。如果您只想制作简单的东西,而不会比我猜大概有200-300行。

  1. The Right solution: Because PageView is trying to get all posible height, we can't use it inside of any widget, that dont' have height. So if we don't have height we need to use another widget, for example StackWidget and re-create PageView behavior: swipes, animations etc. It won't be a big library, if you want to make just simple things, less than 200-300 lines I guess.

有问题的解决方案是在构建PageView小部件之前检查所有元素的高度。构建PageView时,不能更改元素的高度。因此,如果您需要例如在渲染转盘之前发出服务器请求。

The hacky solution is to check the height of all elements before you build the PageView widget. You cannot change the height of the elements when PageView is build. So if you need to have for example a server request make it before you render the carusel.

获取高度,则使用IndexedStack更容易,因为它具有最高元素的高度,但只显示第一个元素(默认情况下)。

To get the height, it easier to use IndexedStack, becouse it has the height of the highest element, but show only the first one (by default).


  • 使用键来获取IndexedStack的高度

  • 使用setState保存它。

  • 将获得的高度用作PageView的高度。

class CarouselVariableHight extends StatefulWidget {
  @override
  CarouselVariableHightState createState() => CarouselVariableHightState();
}

final widgetHeights = <double>[
  Random().nextInt(300).toDouble(),
  Random().nextInt(300).toDouble(),
  Random().nextInt(300).toDouble(),
  Random().nextInt(300).toDouble(),
];

class CarouselVariableHightState extends State<CarouselVariableHight> {
  double height;
  GlobalKey stackKey = GlobalKey();
  bool widgetHasHeigh;

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
    super.initState();
  }

  _afterLayout(_) {
    final RenderBox renderBoxRed = stackKey.currentContext.findRenderObject();
    final sizeRed = renderBoxRed.size;
    setState(() {
      height = sizeRed.height;
    });
  }

  final caruselItems = widgetHeights
      .map((height) => Column(children: [
            Container(
                color: Colors.red,
                height: Random().nextInt(300).toDouble(),
                child: Text('Text with random length'))
          ]))
      .toList();

  _buildStack() {
    Widget firstElement;
    if (height == null) {
      firstElement = Container();
    } else {
      firstElement = Container(
        height: height,
        child: PageView(
          children: caruselItems,
        ),
      );
    }

    return IndexedStack(
      key: stackKey,
      children: <Widget>[
        firstElement,
        ...caruselItems,
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Carousel')),
      body: ListView(
        children: <Widget>[
          Text('My Carousel'),
          _buildStack(),
          Text('end of List'),
        ],
      ),
    );
  }
}

这篇关于Flutter:根据当前子项调整PageView / Horizo​​ntal ListView的高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆