Flutter-PageController错误:“页面值仅在建立内容尺寸后才可用." [英] Flutter - PageController error: `Page value is only available after content dimensions are established.`

查看:46
本文介绍了Flutter-PageController错误:“页面值仅在建立内容尺寸后才可用."的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使PageView内的一些小部件动画化,并创建了一个自定义AnimatedWidget,该动画使用了PageView也使用的PageController.这个想法是当用户在幻灯片上滑动时,使一些文本动画化.下面的代码将在第一个渲染器上引发错误,一旦我开始向左/向右滑动,一切正常,但是最初出现红色屏幕时出现错误.我试图通过检查controller.hasClients进行辩护,但控制器中已经有1页,并且错误来自PageView页getter中的断言.我还有其他道具可以检查以在第一个渲染后延迟动画设置吗?

I'm trying to animate some widgets inside PageView and created a custom AnimatedWidget which uses PageController also used by PageView. The idea is to animate some text up as user swipes through slides. The code below will throw error on the first render, once I start swiping left/right everything works but I get red screen with error initially. I tried to defend by checking controller.hasClients but there is already 1 page in the controller and error comes from assertion in PageView page getter. Is there any other prop I can check to delay animating after the first render?

import 'dart:math' as math;

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class MySlider extends StatelessWidget {
  final _controller = new PageController();

  final List<String> _pages = [
    'Create your football profile',
    'Your team, your players, your line-up',
    'Track the stats that matter and share with others'
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          PageView.builder(
            controller: _controller,
            itemBuilder: (_, index) => Slide(
              controller: _controller,
              position: index,
              heading: _pages[index],
            ),
            itemCount: _pages.length,
            physics: AlwaysScrollableScrollPhysics(),
          ),
        ]
      )
    );
  }
}

class Slide extends AnimatedWidget {

  final PageController controller;
  final String heading;
  final int position;

  Slide({
    this.controller,
    this.heading,
    this.position
  }) : super(listenable: controller);

  @override
  Widget build(BuildContext context) {

    final screenHeight = MediaQuery.of(context).size.height;
    final textYOffset = controller.hasClients
        ? screenHeight * (controller.page - position)
        : 0;

    final opacity = controller.hasClients
        ? 1.0 - math.max(0, controller.page - position)
        : 1.0;

    return Stack(
        alignment: Alignment.topCenter,
        children: [
          Positioned(
              bottom: 120,
              left: 16,
              right: 16,
              child: Transform.translate(
                  offset: Offset(0, -textYOffset),
                  child: Opacity(
                      opacity: opacity,
                      child: Text(heading)
                  ),
              ),
          )
        ],
    );
  }
}

控制台中的异常:

════════小部件库捕获到异常═════════════════════════════════════════════

════════ Exception caught by widgets library ═════════════════════════════════════════════

构建Slide(动画:

The following assertion was thrown building Slide(animation:

PageController#c35ec(一个客户端,偏移量0.0),脏,依赖项:[MediaQuery],状态:_AnimatedState#05ff4):

PageController#c35ec(one client, offset 0.0), dirty, dependencies: [MediaQuery], state: _AnimatedState#05ff4):

页面值仅在建立内容尺寸之后才可用.'package:flutter/src/widgets/page_view.dart':

Page value is only available after content dimensions are established. 'package:flutter/src/widgets/page_view.dart':

断言失败:第373行pos 7行:'pixels == null ||(minScrollExtent!= null&& maxScrollExtent!= null)'

Failed assertion: line 373 pos 7: 'pixels == null || (minScrollExtent != null &&maxScrollExtent != null)'

此时

minScrollExtent maxScrollExtent

推荐答案

考虑到实现幻灯片的方式以及由于内容尺寸不可用而导致的错误,但我认为丑陋的解决方案是在尝试使用控制器之前检查尺寸是否可用:

Taking into account the way you implemented the slide and the error you are getting about the content dimensions not being available a possible, but I think ugly, solution would be to check if the dimensions are available before trying to use the controller:

if(controller.position.haveDimensions){
  final screenHeight = MediaQuery.of(context).size.height;
  final textYOffset = controller.hasClients
      ? screenHeight * (controller.page - position)
      : 0;

  final opacity = controller.hasClients
      ? 1.0 - math.max(0, controller.page - position)
      : 1.0;

  return Stack(
    alignment: Alignment.topCenter,
    children: [
      Positioned(
        bottom: 120,
        left: 16,
        right: 16,
        child: Transform.translate(
          offset: Offset(0, -textYOffset),
          child: Opacity(
              opacity: opacity,
              child: Text(heading)
          ),
        ),
      )
    ],
  );
} else {
  return SizedBox();
}

尽管此修复"了您得到的错误,但是无论我进行了什么更改,最后一页仍然有错误.您可能想要更好地实现动画,但是我还没有弄清楚.

Despite this "fixing" the error you get displayed, you still have an error on the last page, regardless of my changes. There might be a better implementation of the animation you want to have, but I haven't figured it out yet.

这篇关于Flutter-PageController错误:“页面值仅在建立内容尺寸后才可用."的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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