Как анимировать круг, который постепенно увеличивается, чтобы заполнить фон виджета? - PullRequest
0 голосов
/ 03 апреля 2020

Я новичок во Flutter и работаю над приложением для викторины с несколькими вариантами ответов. Каждый возможный ответ отображается в виде ListTile виджета:

return ListTile(
  title: Text(answer),
  onTap: hasAnswered ? () { _answer(answer); } : null,
);

Теперь, когда пользователь выбирает ответ, я хочу выделить правильный ответ зеленым цветом. Достаточно просто, мы обертываем его в Container:

return Container(
  color: isCorrectAnswer ? Colors.green : null,
  child: ListTile(
    title: Text(answer),
    onTap: hasAnswered ? () { _answer(answer); } : null,
  ),
);

. Следующий шаг - анимировать этот фон, заставляя его появляться постепенно. Мне бы хотелось, чтобы оно росло в виде круга, начиная с центра ListItem и увеличиваясь наружу, пока оно не покрывает весь виджет, во многом как собственные чернила ряби материала.

У меня есть Я не совсем понял структуру анимации Флаттера, но прежде чем я сделаю, давайте сделаем круг фиксированного размера. Easy peasy:

return Container(
  decoration: isCorrectAnswer ?
    BoxDecoration(shape: BoxShape.circle, color: Colors.green) :
    null,
  child: ListTile(
    title: Text(answer),
    onTap: hasAnswered ? () { _answer(answer); } : null,
  ),
);

Теперь круг плотно прилегает между верхним и нижним краем виджета. Как мне контролировать размер этого круга? Нет возможности установить радиус BoxShape.circle; в соответствии с документацией, «диаметр круга - это самое короткое измерение коробки, ширины или высоты, чтобы круг касался краев коробки».

Моя следующая мысль заключалась в использовании радиальный градиент:

return Container(
  decoration: isCorrectAnswer ?
    BoxDecoration(
      shape: BoxShape.rectangle,
      gradient: RadialGradient(
        radius: 0.5,
        colors: [color, color, Colors.transparent],
        stops: [0.0, 1.0, 1.0],
      ),
    ) :
    null,
  child: ListTile(
    title: Text(answer),
    onTap: hasAnswered ? () { _answer(answer); } : null,
  ),
);

Это позволяет мне контролировать radius. Но опять же, радиус относится к кратчайшему краю виджета, так как мне узнать радиус, который я должен использовать в качестве конечной точки моей анимации? Конечно, я мог бы просто анимировать radius от 0,0 до какого-то большого значения, например 10,0, но это хакерство, и анимация не улучшится должным образом.

Я попытался установить radius: 0.5 * context.size.longestSide / context.size.shortestSide, что должно точно покрыть виджет. Но это дает ошибку, потому что мне не разрешен доступ к size во время сборки.

Я также посмотрел на Ink, InkWell, InkRipple, InkFeature и InkResponse классы, чтобы увидеть, могу ли я каким-то образом использовать собственный код рисования пульсации материала, но я не могу понять, как вызвать его вручную.

Итак, как мне создать этот эффект таким образом, чтобы я мог красиво анимировать радиус от нуля до половины длины диагонали виджета?

...