Использование виджета ColorFiltered в приложениях Flutter

Целевая аудитория: Новичок

Рецепт: Использование виджета ColorFiltered для обновления цвета фона экрана обратной связи карточки викторины.

Виджет фокуса: Виджет ColorFiltered

Цель: Обновите цвет фона виджета обратной связи BottomSheet, чтобы отразить статус правильного или неправильного ответа на вопрос викторины. Оттенок красного цвета генерируется с помощью цветного фильтра для неправильного выбора, а оттенок зеленого — для правильного ответа.

ПРИМЕЧАНИЕ: На данный момент виджет ColorFiltered аварийно завершает работу в Chrome. Пожалуйста, обратитесь к Эта проблема на Флаттер Гитхаб.

Страница викторины iOS:

ios-colorФильтрованный

Android QuizPage:

android-colorФильтрованный

Ознакомьтесь с сопутствующим видеоруководством здесь

Поехали!

Виджет ColorFilter добавляется к Выпуск флаттера 1.9. Этот виджет позволяет генерировать динамичные и яркие оттенки в зависимости от выбранных режимов наложения, часть dart.ui в фреймворке Flutter painting.dart файл. я использую BlendMode.hue режим для смешивания красного и зеленого цветов с QuizPageх Colors.lightBlueAccent цвет.

ПРИМЕЧАНИЕ: ColorFilter не работает в Интернете. Обратитесь к связанной проблеме здесь.

Запуск примера кода

Есть два способа, которыми вы можете опробовать пример кода в этом рецепте.

  1. Только бег QuizzieDemo: этот образец можно запускать независимо. Убедитесь, что у вас есть void main() => runApp(QuizzieDemo()); в верхней части quizze_demo.dart файл.

  2. Запуск как часть приложения рецептов кода: если вы выберете эту опцию, вы сможете увидеть другие рецепты кода, перечисленные на домашней странице.

Структура кода

Есть два файла:

  1. quizze_demo.dart: Содержит точку входа в рецепт примера кода.
import 'package:flutter/material.dart';
import 'package:flutter_widgets/quizzie/quizze_page.dart';

//Note: Use code below to just run this demo.
// OR comment it out if you want to run it on Web as part of recipe sample app
void main() => runApp(QuizzieDemo());

class QuizzieDemo extends StatefulWidget {
  @override
  _QuizzieDemoState createState() => _QuizzieDemoState();
}

class _QuizzieDemoState extends State<QuizzieDemo> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: QuizPage(),
    );
  }
}

  1. quizze_page.dart: содержит код, относящийся к QuizPage, и ColorFilter для обновления цвета фона виджета обратной связи: Нижний лист.

Давайте исследовать QuizPage Виджет без состояния в деталях. Есть три части, чтобы QuizPage интерфейс: Image виджет для вопроса викторины. Text виджет для описания вопроса. * Expanded виджет для переноса вариантов ответа. мы используем Expanded виджет, чтобы заполнить доступное пространство на экране. Все варианты ответов будут добавлены как child под Expanded виджет. QuizOptions() виджет инкапсулирует варианты/варианты ответов на тест.

Проверить код QuizPage виджет ниже:

class QuizPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Column(
        children: <Widget>[
          Container(
            padding: EdgeInsets.only(top: 50, left: 20, right: 20, bottom: 20),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Image.asset(
                  "assets/images/tomato.jpg",
                ),
                Text(
                  "Is tomato a fruit or vegetable ?",
                  style: TextStyle(
                    color: Colors.lightBlueAccent,
                    fontWeight: FontWeight.bold,
                    fontSize: 30,
                  ),
                ),
              ],
            ),
          ),
          SizedBox(
            height: 20,
          ),
          Expanded(
            child: Container(
              decoration: BoxDecoration(
                color: Colors.lightBlueAccent,
                borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(20),
                    topRight: Radius.circular(20)),
              ),
              child: QuizOptions(),
            ),
          )
        ],
      ),
    );
  }
}

Теперь пришло время построить QuizOptions виджет для вариантов викторины. Одновременно может быть выбран только один ответ, поэтому имеет смысл использовать RadioListTile представить каждый вариант ответа. QuizOptions должен быть StatefulWidget так как он будет отображать обратную связь с пользователем в зависимости от состояния выбора выбора.

class QuizOptions extends StatefulWidget { @override \_QuizOptionsState createState() =\> \_QuizOptionsState();
}

Управление состоянием происходит в _QuizOptionsState учебный класс. Все варианты упакованы ListView. С использованием enum за Options упростить использование в коде.

enum Options { fruit, veggie, none }

_QuizOptionsState:

class _QuizOptionsState extends State<QuizOptions> {
  Options selection = Options.none;

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        RadioListTile(
          title: Text(
            "Fruit",
            style:
                TextStyle(fontSize: 30, color: Colors.white, letterSpacing: 3),
          ),
          value: Options.fruit,
          groupValue: selection,
          onChanged: (Options value) =>
              setState(() => showAnswer(context, value)),
        ),
        RadioListTile(
          title: Text(
            "Vegetable",
            style:
                TextStyle(fontSize: 30, color: Colors.white, letterSpacing: 3),
          ),
          value: Options.veggie,
          groupValue: selection,
          onChanged: (Options value) =>
              setState(() => showAnswer(context, value)),
        )
      ],
    );
  }

...
}

Когда выбор сделан, RadioListTile‘с’onChanged вызывается метод и передает текущий выбор в showAnswer метод, как показано ниже. showAnswer обновляет текущий выбор до переданного значения параметра и использует showModalBottomSheet чтобы показать модальный нижний лист Material Design.

...
void showAnswer(BuildContext context, Options value) {
  selection = value;
  showModalBottomSheet(context: context, builder: buildBottomSheet);
}
...

showModalBottomSheet выбирает объяснение для текущего выбора и использует ColorFiltered виджет для применения цветового фильтра на основе правильного и неправильного выбора. ColorFiltered использование виджета FeedbackWidget как его child для отображения сообщения обратной связи. ColorFilter.mode(...) использует BlendMode.hue и исходный цвет ответа (Colors.greenAccent за правильный ответ и Colors.redAccent за неправильный ответ). Его дочерний виджет FeedbackWidget имеет Colors.lightBlueAccent — цвет назначения. ColorFiltered виджет может применять фильтры на основе его colorFilter атрибут. Он может смешивать исходный цвет с целевым цветом на основе BlendModeкоторый BlendMode.hue в нашем случае.

Widget buildBottomSheet(BuildContext context) {
  String explanation = "";
  if (selection == Options.fruit) {
    explanation = "You got it! Tomato is a fruit since it has seeds in it.";

    return ColorFiltered(
      colorFilter: ColorFilter.mode(Colors.greenAccent, BlendMode.hue),
      child: FeedbackWidget(explanation: explanation),
    );
  } else {
    explanation =
        "While many people believe a tomato is a vegetable, a tomato has seeds and thus is actually a fruit.";

    return ColorFiltered(
      colorFilter: ColorFilter.mode(Colors.redAccent, BlendMode.hue),
      child: FeedbackWidget(explanation: explanation),
    );
  }
}

FeedbackWidget является StatelessWidget. Он показывает текстовое сообщение обратной связи в Container виджет с BoxDecoration цвет как Colors.lightBlueAccent.

class FeedbackWidget extends StatelessWidget {
  const FeedbackWidget({
    Key key,
    @required this.explanation,
  }) : super(key: key);

  final String explanation;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 150,
      decoration: BoxDecoration(
          color: Colors.lightBlueAccent,
          //optional radius
          borderRadius: BorderRadius.only(
              topRight: Radius.circular(10), topLeft: Radius.circular(10))),
      child: Padding(
        padding:
            const EdgeInsets.only(top: 10, left: 10, right: 10, bottom: 10),
        child: Text(
          explanation,
          style:
          TextStyle(
              fontSize: 25,
              color: Colors.white,
              wordSpacing: 5,
              letterSpacing: 1),
        ),
      ),
    );
  }
}

И вы сделали !

Репозиторий исходного кода: Исходный код рецепта доступен здесь

Использованная литература:

  1. Примечания к выпуску Flutter 1.9
  2. Образец цветового фильтра Flutter
  3. Виджет ColorFiltered
  4. Расширенный виджет

Удачной готовки с Flutter 😃

Понравилась статья? Не нашли интересующую вас тему? Пожалуйста, оставьте комментарии или напишите мне о темах, которые вы хотели бы, чтобы я написал Кстати, я люблю и кексы, и кофе :)

Следуй за мной в твиттер

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *