Flutter - AnimatedBuilder, ошибка анимации / виджета при первой загрузке - PullRequest
0 голосов
/ 28 января 2020

когда я загружаю сборщик в первый раз, все мои карты имеют одинаковый размер за секунду до перехода к правильным размерам и пропорциям, кто-нибудь знает, как я могу настроить это так, чтобы они были в правильных размерах от get go?

Как ни странно, когда я заменяю свой виджет Padding & Card просто контейнером с изображениями, кажется, он появляется в правильных размерах, однако мне нужно, чтобы они были картами для моего позже layout.

(я также планирую бросить все это в класс виджетов вместо того, чтобы помещать весь этот код в основную часть и просто возвращать CustomScroller.)

Пожалуйста, проверьте следующие Gif-файлы:

Gif Of Animation Glitch Gif of Animation работает нормально, когда используется только контейнер

Любая помощь в исправлении начальной загрузки была бы крайне полезной! :)

import 'package:flutter/material.dart';
import 'package:blink/widget/customScroller.dart';


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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  PageController pageController;

  List<String> images = [
    "https://iso.500px.com/wp-content/uploads/2014/07/big-one.jpg",
    "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXRfe-GzBFRQzv8udHMCshqQGAj2JD5SGsR7CoyWP_HqFapJCYSA&s",
    "https://ichef.bbci.co.uk/wwfeatures/live/976_549/images/live/p0/7w/b9/p07wb9xk.jpg",
    "https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-1.2.1&w=1000&q=80"
  ];

  @override
  void initState() {
    // TODO: implement initState
    pageController = PageController(initialPage: 1, viewportFraction: 0.77);
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: PageView.builder(
          controller: pageController,
            itemCount: images.length,
            itemBuilder: (context,position){
            return customScroller(position);
            }),);
  }

  customScroller(int index) {
    return AnimatedBuilder(
      animation: pageController,
      builder: (context, widget) {
        double val = 1;

        if(pageController.position.haveDimensions){
          val = pageController.page - index;
        val = 1 - (val.abs()*0.3).clamp(0.0,1.0);}

        return Center(
          child: SizedBox(
            height: Curves.easeInOut.transform(val) *300,
              width: Curves.easeInOut.transform(val) *400,
            child: widget,
          ),
        );
      },
//      child: Container(
//        margin: EdgeInsets.all(10),
//        child: Image.network(images[index],fit:BoxFit.cover),
//      ),
// When I use the above code as the child instead of the padding with the card in it seems to spawn correctly
        child: Padding(
          padding: EdgeInsets.fromLTRB(0, 15, 0, 15),
          child: Container(
            child: Card(
              color: Colors.white70,
              elevation: 9,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(20.0),
              ),
              clipBehavior: Clip.antiAlias,
              child: Container(
                color: Colors.white,
                padding: EdgeInsets.all(5),
                child: Row(
                  children: <Widget>[
                    Expanded(
                      flex: 2,
                      child: Container(
                        height: double.infinity,
                        child: ClipRRect(
                          borderRadius: BorderRadius.only(
                              topLeft: Radius.circular(20.0),
                              topRight: Radius.circular(0.0),
                              bottomRight: Radius.circular(0.0),
                              bottomLeft: Radius.circular(20.0)),
                          child: new Image.network(
                            images[index],
                            fit: BoxFit.cover,
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        )

    );
  }
}

1 Ответ

0 голосов
/ 28 января 2020

Что вам не хватает, так это то, что метод сборки AnimatedBuilder запускается только при наличии анимации. Не в самом начале. Вот почему размер изменяется, если вы прокручиваете, а не раньше.

Ваш дочерний виджет не оборачивается виджетом-трансформером (или блоком размера), поэтому он остается одинаковым для всех индексов (в начале - строитель еще не бегал). В моем примере я также обернул дочерний элемент с помощью SizedBox и дал val некоторое начальное значение.

Рабочий пример:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  PageController pageController;

  List<String> images = [
    "https://iso.500px.com/wp-content/uploads/2014/07/big-one.jpg",
    "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXRfe-GzBFRQzv8udHMCshqQGAj2JD5SGsR7CoyWP_HqFapJCYSA&s",
    "https://ichef.bbci.co.uk/wwfeatures/live/976_549/images/live/p0/7w/b9/p07wb9xk.jpg",
    "https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-1.2.1&w=1000&q=80"
  ];

  @override
  void initState() {
    // TODO: implement initState
    pageController = PageController(initialPage: 1, viewportFraction: 0.77);
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: PageView.builder(
          controller: pageController,
          itemCount: images.length,
          itemBuilder: (context, position) {
            return customScroller(position);
          }),
    );
  }

  customScroller(int index) {
    Widget child = Padding(
      padding: EdgeInsets.fromLTRB(0, 15, 0, 15),
      child: Container(
        child: Card(
          color: Colors.white70,
          elevation: 9,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20.0),
          ),
          clipBehavior: Clip.antiAlias,
          child: Container(
            color: Colors.white,
            padding: EdgeInsets.all(5),
            child: Row(
              children: <Widget>[
                Expanded(
                  flex: 2,
                  child: Container(
                    height: double.infinity,
                    child: ClipRRect(
                      borderRadius: BorderRadius.only(
                          topLeft: Radius.circular(20.0),
                          topRight: Radius.circular(0.0),
                          bottomRight: Radius.circular(0.0),
                          bottomLeft: Radius.circular(20.0)),
                      child: new Image.network(
                        images[index],
                        fit: BoxFit.cover,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
    double val = (index == 1)?1:0.7;

    return AnimatedBuilder(
        animation: pageController,
        builder: (context, widget) {
          if (pageController.position.haveDimensions) {
            val = pageController.page - index;
            val = 1 - (val.abs() * 0.3).clamp(0.0, 1.0);
          }
          print("val: $val; index: $index");
          return _getTransformedSizedBox(val, widget);
        },
//      child: Container(
//        margin: EdgeInsets.all(10),
//        child: Image.network(images[index],fit:BoxFit.cover),
//      ),
// When I use the above code as the child instead of the padding with the card in it seems to spawn correctly
        child: _getTransformedSizedBox(val, child));
  }

  _getTransformedSizedBox(double val, Widget widget) {
    return Center(
      child: SizedBox(
        height: Curves.easeInOut.transform(val) * 300,
        width: Curves.easeInOut.transform(val) * 400,
        child: widget,
      ),
    );
  }
}
...