Пользовательский виджет переключения для принятия Политики конфиденциальности в приложениях Flutter
Целевая аудитория: Новичок
Рецепт: Внедрение виджета Custom Switch для принятия политики конфиденциальности на экране настроек.
Виджет фокуса: Переключить виджет
Цель: В нашем демонстрационном приложении мы реализуем пользовательский виджет без сохранения состояния. HyperlinkedLabelSwitch
. Он будет состоять из двух основных визуальных частей:
Ярлык «Политика конфиденциальности» выровнен по началу. Нажатие/нажатие на эту метку откроет URL-адрес в
WebView
. Я буду использовать Google Doc в качестве примера политики конфиденциальности, доступной по гиперссылке.Тумблер выровнен по краю экрана. Включение означает, что политика конфиденциальности принята. Этот принятый статус обновляется как «Политика конфиденциальности (принято)» в левой метке. Переключение этого переключателя в положение «Выкл.» Обновляет текстовую метку обратно на «Политика конфиденциальности».
Скриншот политики конфиденциальности, загруженной в WebView:
Скриншот обновленной текстовой метки после принятия политики конфиденциальности:
Посмотрите сопутствующий видеоурок:здесь
Реализация виджета пользовательского переключателя: HyperlinkedLabelSwitch
Мы создадим собственный виджет переключателя с интерактивной текстовой меткой и переключателем. Скриншот пользовательского виджета в выключенном режиме (конфиденциальность не принимается):
Скриншот пользовательского виджета в режиме «включено» (конфиденциальность принимается):
Шаг 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
имеет два параметра:
accepted
: логический флаг для отслеживания статуса принятия политики конфиденциальности.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);
},
)
],
),
);
}
}
Репозиторий исходного кода: Исходный код рецепта доступен здесь
Использованная литература:
Удачной готовки с Flutter
Понравилась статья? Не нашли интересующую вас тему? Пожалуйста, оставьте комментарии или напишите мне о темах, которые вы хотели бы, чтобы я написал
Следуй за мной в твиттер