Пользовательский виджет переключения для принятия Политики конфиденциальности в приложениях Flutter

кредиты изображения

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

Рецепт: Внедрение виджета Custom Switch для принятия политики конфиденциальности на экране настроек.

Виджет фокуса: Переключить виджет

Цель: В нашем демонстрационном приложении мы реализуем пользовательский виджет без сохранения состояния. HyperlinkedLabelSwitch. Он будет состоять из двух основных визуальных частей:

  1. Ярлык «Политика конфиденциальности» выровнен по началу. Нажатие/нажатие на эту метку откроет URL-адрес в WebView. Я буду использовать Google Doc в качестве примера политики конфиденциальности, доступной по гиперссылке.

  2. Тумблер выровнен по краю экрана. Включение означает, что политика конфиденциальности принята. Этот принятый статус обновляется как «Политика конфиденциальности (принято)» в левой метке. Переключение этого переключателя в положение «Выкл.» Обновляет текстовую метку обратно на «Политика конфиденциальности».

Политика конфиденциальности №1

Скриншот политики конфиденциальности, загруженной в WebView:

Политика конфиденциальности №1

Скриншот обновленной текстовой метки после принятия политики конфиденциальности:

Политика конфиденциальности №1

Посмотрите сопутствующий видеоурок:здесь

Реализация виджета пользовательского переключателя: HyperlinkedLabelSwitch

Мы создадим собственный виджет переключателя с интерактивной текстовой меткой и переключателем. Скриншот пользовательского виджета в выключенном режиме (конфиденциальность не принимается):

Политика конфиденциальности №4

Скриншот пользовательского виджета в режиме «включено» (конфиденциальность принимается):

Политика конфиденциальности №4

Шаг 1. Создать класс HyperlinkedLabelSwitch расширение StatelessWidget. Этот виджет имеет следующие элементы:

  • label: текст, отображающий «Политика конфиденциальности».
  • hyperlink: веб-ссылка (url) на документ о политике конфиденциальности.
  • selected: логическое значение, определяющее, принимается политика или нет.
  • onChange: Функция, которая будет назначена Switch виджет onChanged: имущество.
  • padding: это отступ вокруг пользовательского виджета. Возможность передать это значение (довольно жесткое кодирование) от родителя делает пользовательский виджет многоразовым.
class HyperlinkedLabelSwitch extends StatelessWidget {
  final String label;
  final String hyperlink;
  final bool selected;
  final Function onChange;
  final EdgeInsets padding;
}

Теперь давайте создадим пользовательский виджет, который содержит интерактивную метку и тумблер. Нам нужен отступ вокруг этого виджета для визуальной привлекательности. Мы будем использовать заполнение, переданное от родителя, как padding параметр. я использую Row виджет, чтобы поместить метку и тумблер рядом друг с другом. Кликабельная метка остается в начале экрана, поэтому она будет первой дочерней. Switch виджет размещается как второй дочерний элемент Row виджет. Поскольку метка состоит из текста и обновляется, когда пользователь принимает политику конфиденциальности, нам нужно, чтобы этот виджет оставался гибким. Нам нужно позволить ему расшириться, чтобы занять доступное пространство. Вот почему мы будем использовать Expand виджет, чтобы претендовать на пустую область.

@override
Widget build(BuildContext context) {
  return Padding(
    padding: padding,
    child: Row(
      children: <Widget>[
        Expanded(),
        Switch()
      ],
    ),
  );
}

я воспользуюсь RichText виджет для создания интерактивной текстовой метки. TextSpan виджет — отличный выбор для рендеринга не только обычного текста. Это recognizer свойство можно использовать для более подходящей реакции на жесты. В этом случае я буду использовать TapGestureRecognizer как распознаватель. TapGestureRecognizer помогает отличить жесты от других потенциальных жестов. Нажатие / нажатие на ссылку откроет URL-адрес в WebView. В этом примере это Google Doc с образцом текста политики конфиденциальности. Давайте соберем все это вместе в виде кода ниже:

Expanded(
  child: RichText(
      text: TextSpan(
          text: label,
          style: TextStyle(
              color: Colors.redAccent,
              decoration: TextDecoration.underline,
              fontSize: 20.0),
          //TapGestureRecognizer helps to disambiguate gestures from other potential gestures
          recognizer: TapGestureRecognizer()
            ..onTap = () {
              //open hyperlink in webview
              Navigator.pushNamed(context, WEBVIEW,
                  arguments:
                      WebViewArguments(title: label, url: hyperlink));
            })),
),

Далее идет Switch виджет. Это довольно просто. Виджет value, onChanged атрибутам присваиваются значения из родительского виджета. selected логическое значение присваивается valueа также onChange() назначается onChanged атрибут, как показано ниже:

Switch(
  value: selected,
  onChanged: (bool v) {
    onChange(v);
  },
)

Вот и все. Мы готовы перейти к использованию этого виджета из другого виджета или страницы. Страница настроек — это один из примеров, где этот виджет можно использовать для создания кликабельной метки вместе с настройками переключателя.

Использование виджета пользовательского переключателя

Я создал образец страницы SwitchListTile1 чтобы продемонстрировать интеграцию нашего нового пользовательского виджета HyperlinkedLabelSwitch. SwitchListTile1 страница представляет собой StatefulWidget. Мы выбрали StatefulWidget, потому что хотим обновить значение тумблера, чтобы отразить статус принятия политики конфиденциальности. Как обычно, нам нужен State за StatefulWidgetсказать _SwitchListTileState как показано ниже:

class SwitchListTile1 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _SwitchListTileState();
  }
}

class _SwitchListTileState extends State<SwitchListTile1> {
}

_SwitchListTileState имеет два параметра:

  1. accepted: логический флаг для отслеживания статуса принятия политики конфиденциальности.
  2. privacyLabel: текстовое сообщение, отображаемое пользователю. По умолчанию это «Политика конфиденциальности». Оно меняется на «Политика конфиденциальности (принято)», когда accepted является true.

body этого образца страницы прост и состоит из одного Column виджет. Этот Column имеет только одного ребенка HyperlinkedLabelSwitch виджет.HyperlinkedLabelSwitch инициализируется значениями по умолчанию для privacyLabel а также accepted. Значение hyperlink остается постоянным и, следовательно, жестко привязанным, поскольку мы не допускаем частого изменения местоположения политики конфиденциальности. setState(){} вызывается всякий раз, когда изменяется значение переключателя. privacyLabelзначение обновляется, чтобы включить (Accepted) когда accepted является true.

body: Column(
  children: <Widget>[
    HyperlinkedLabelSwitch(
      padding:
          const EdgeInsets.symmetric(horizontal: 20.0, vertical: 50.0),
      label: privacyLabel,
      hyperlink:
          '
      selected: accepted,
      onChange: (bool v) {
        setState(() {
          accepted = v;
          if (accepted) {
            privacyLabel="Privacy Policy (Accepted)";
          } else {
            privacyLabel="Privacy Policy";
          }
        });
      },
    )
  ],
)

и мы закончили!

В следующем разделе приведен полный пример кода для удобства.

Полный пример кода

Этот раздел содержит полный пример кода для справки. Есть несколько зависимостей, таких как webview.dart, router.dart. Они предназначены для включения в целях навигации по приложению и отображения документов политики конфиденциальности в веб-представлении. Пожалуйста, обратитесь к Репозиторий Github для доступа к полному коду.

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_widgets/menus/webview.dart';
import 'package:flutter_widgets/router.dart';

class SwitchListTile1 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _SwitchListTileState();
  }
}

class _SwitchListTileState extends State<SwitchListTile1> {
  bool accepted = false;
  String privacyLabel="Privacy Policy";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("SwitchListTile: Clickable label"),
      ),
      body: Column(
        children: <Widget>[
          HyperlinkedLabelSwitch(
            padding:
                const EdgeInsets.symmetric(horizontal: 20.0, vertical: 50.0),
            label: privacyLabel,
            hyperlink:
                '
            selected: accepted,
            onChange: (bool v) {
              setState(() {
                accepted = v;
                if (accepted) {
                  privacyLabel="Privacy Policy (Accepted)";
                } else {
                  privacyLabel="Privacy Policy";
                }
              });
            },
          )
        ],
      ),
    );
  }
}

class HyperlinkedLabelSwitch extends StatelessWidget {
  final String label;
  final String hyperlink;
  final bool selected;
  final Function onChange;
  final EdgeInsets padding;


  const HyperlinkedLabelSwitch(
      {Key key,
      this.label,
      this.selected,
      this.onChange,
      this.padding,
      this.hyperlink});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: padding,
      child: Row(
        children: <Widget>[
          //1. First widget in row is for label
          //Expanded widget claims the empty area
          Expanded(
            child: RichText(
                text: TextSpan(
                    text: label,
                    style: TextStyle(
                        color: Colors.redAccent,
                        decoration: TextDecoration.underline,
                        fontSize: 20.0),
                    //TapGestureRecognizer helps to disambiguate gestures from other potential gestures
                    recognizer: TapGestureRecognizer()
                      ..onTap = () {
                        //open hyperlink in webview
                        Navigator.pushNamed(context, WEBVIEW,
                            arguments:
                                WebViewArguments(title: label, url: hyperlink));
                      })),
          ),

          //2. Next comes the switch to save the user's selection
          Switch(
            value: selected,
            onChanged: (bool v) {
              onChange(v);
            },
          )
        ],
      ),
    );
  }
}

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

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

  1. Переключить виджет
  2. Расширенный виджет
  3. TextSpan
  4. TapGestureRecognizer

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

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

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

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

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

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