浏览代码

Merge branch 'zgh/cupertino/fix' of github.com:Unity-Technologies/com.unity.uiwidgets into zxw/gallery

/zgh-devtools
xingweizhu 4 年前
当前提交
c6dc195e
共有 16 个文件被更改,包括 3143 次插入850 次删除
  1. 506
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_alert_demo.cs
  2. 135
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_buttons_demo.cs
  3. 518
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_picker_demo.cs
  4. 105
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_slider_demo.cs
  5. 117
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_switch_demo.cs
  6. 339
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_text_field_demo.cs
  7. 41
      com.unity.uiwidgets/Runtime/cupertino/route.cs
  8. 3
      com.unity.uiwidgets/Runtime/cupertino/tab_scaffold.cs
  9. 8
      com.unity.uiwidgets/Runtime/ui2/geometry.cs
  10. 5
      com.unity.uiwidgets/Runtime/widgets/heroes.cs
  11. 2
      com.unity.uiwidgets/Runtime/widgets/navigator.cs
  12. 237
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_refresh_demo.cs
  13. 151
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_segmented_control_demo.cs
  14. 343
      com.unity.uiwidgets/Runtime/cupertino/refresh.cs
  15. 616
      com.unity.uiwidgets/Runtime/cupertino/segmented_control.cs
  16. 867
      com.unity.uiwidgets/Runtime/cupertino/sliding_segmented_control.cs

506
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_alert_demo.cs


using Unity.UIWidgets.widgets;
namespace UIWidgetsGallery.gallery {
class CupertinoAlertDemo : StatefulWidget {
public static string routeName = "/cupertino/alert";
public class CupertinoAlertDemo : StatefulWidget {
public static string routeName = "/cupertino/alert";
public override State createState() {
return new _CupertinoAlertDemoState();
}
public override State createState()
{
return new _CupertinoAlertDemoState();
}
public class _CupertinoAlertDemoState : State<CupertinoAlertDemo> {
string lastSelectedValue;
void showDemoDialog(BuildContext context = null, Widget child = null) {
CupertinoRouteUtils.showCupertinoDialog<string>(
context: context,
builder: (BuildContext context1) => child
).then_((string value) =>{
if (value != null) {
setState(()=> { lastSelectedValue = value; });
}
class _CupertinoAlertDemoState : State<CupertinoAlertDemo> {
string lastSelectedValue;
void showDemoDialog(
BuildContext context = null,
Widget child = null
) {
CupertinoRouteUtils.showCupertinoDialog(
context: context,
builder: (BuildContext _context) => child
).then((object value) => {
if (value != null) {
setState(() => { lastSelectedValue = value as string; });
}
});
});
}
void showDemoActionSheet(BuildContext context = null, Widget child = null) {
CupertinoRouteUtils.showCupertinoModalPopup<string>(
context: context,
builder: (BuildContext context1) => child
).then_((string value) =>{
if (value != null) {
setState(()=> { lastSelectedValue = value; });
}
});
}
public override Widget build(BuildContext context)
{
List<Widget> createWidgets(BuildContext context1)
{
List<Widget> widgets = new List<Widget>();
widgets.Add(new CupertinoScrollbar(
child: new ListView(
// Add more padding to the normal safe area.
padding: EdgeInsets.symmetric(vertical: 24.0f, horizontal: 72.0f)
+ MediaQuery.of(context1).padding,
children: new List<Widget>
{
CupertinoButton.filled(
child: new Text("Alert"),
onPressed: () => _onAlertPress(context1)
),
new Padding(padding: EdgeInsets.all(8.0f)),
CupertinoButton.filled(
child: new Text("Alert with Title"),
padding: EdgeInsets.symmetric(vertical: 16.0f, horizontal: 36.0f),
onPressed: () => _onAlertWithTitlePress(context1)
),
new Padding(padding: EdgeInsets.all(8.0f)),
CupertinoButton.filled(
child: new Text("Alert with Buttons"),
padding: EdgeInsets.symmetric(vertical: 16.0f, horizontal: 36.0f),
onPressed: () => _onAlertWithButtonsPress(context1)
),
new Padding(padding: EdgeInsets.all(8.0f)),
CupertinoButton.filled(
child: new Text("Alert Buttons Only"),
padding: EdgeInsets.symmetric(vertical: 16.0f, horizontal: 36.0f),
onPressed: () =>
{
showDemoDialog(
context: context1,
child: new CupertinoDessertDialog()
);
}
),
new Padding(padding: EdgeInsets.all(8.0f)),
CupertinoButton.filled(
child: new Text("Action Sheet"),
padding: EdgeInsets.symmetric(vertical: 16.0f, horizontal: 36.0f),
onPressed: () => _onActionSheetPress(context1)
)
}
)
));
if (lastSelectedValue != null)
widgets.Add(new Positioned(
bottom: 32.0f,
child: new Text($"You selected: {lastSelectedValue}")
));
return widgets;
void showDemoActionSheet(
BuildContext context = null,
Widget child = null
) {
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
builder: (BuildContext _context) => child
).then((object value) => {
if (value != null) {
setState(() => { lastSelectedValue = value as string; });
}
});
}
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Alerts"),
previousPageTitle: "Cupertino"
//trailing: CupertinoDemoDocumentationButton(CupertinoAlertDemo.routeName)
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new Builder(
builder: (BuildContext context1) => {
return new Stack(
alignment: Alignment.center,
children: createWidgets(context1)
);
}
)
)
);
}
public override Widget build(BuildContext context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Alerts"),
previousPageTitle: "Cupertino"
//, trailing: new CupertinoDemoDocumentationButton(CupertinoAlertDemo.routeName)
),
child:
new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new Builder(
builder: (BuildContext _context) => {
List<Widget> stackChildren = new List<Widget> {
new ListView(
padding: EdgeInsets.symmetric(vertical: 24.0f, horizontal: 72.0f)
+ MediaQuery.of(_context).padding,
children: new List<Widget> {
CupertinoButton.filled(
child: new Text("Alert"),
onPressed: () => {
showDemoDialog(
context: _context,
child:
new CupertinoAlertDialog(
title: new Text("Discard draft?"),
actions: new List<Widget> {
new CupertinoDialogAction(
child: new Text("Discard"),
isDestructiveAction: true,
onPressed: () => { Navigator.pop(_context, "Discard"); }
),
new CupertinoDialogAction(
child: new Text("Cancel"),
isDefaultAction: true,
onPressed: () => { Navigator.pop(_context, "Cancel"); }
),
}
)
);
}
),
new Padding(padding: EdgeInsets.all(8.0f)),
CupertinoButton.filled(
child: new Text("Alert with Title"),
padding: EdgeInsets.symmetric(vertical: 16.0f, horizontal: 36.0f),
onPressed: () => {
showDemoDialog(
context: _context,
child: new CupertinoAlertDialog(
title: new Text(
"Allow \"Maps\" to access your location while you are using the app?")
,
content: new Text(
"Your current location will be displayed on the map and used \n" +
"for directions, nearby search results, and estimated travel times.")
,
actions: new List<Widget> {
new CupertinoDialogAction(
child: new Text("Don\"t Allow"),
onPressed: () => {
Navigator.pop(_context, "Disallow");
}
),
new CupertinoDialogAction(
child: new Text("Allow"),
onPressed: () => { Navigator.pop(_context, "Allow"); }
),
}
)
);
}
),
new Padding(padding: EdgeInsets.all(8.0f)),
CupertinoButton.filled(
child: new Text("Alert with Buttons"),
padding: EdgeInsets.symmetric(vertical: 16.0f, horizontal: 36.0f),
onPressed: () => {
showDemoDialog(
context: _context,
child: new CupertinoDessertDialog(
title: new Text("Select Favorite Dessert"),
content: new Text(
"Please select your favorite type of dessert from the \n" +
"list below. Your selection will be used to customize the suggested \n" +
"list of eateries in your area.")
)
);
}
),
new Padding(padding: EdgeInsets.all(8.0f)),
CupertinoButton.filled(
child: new Text("Alert Buttons Only"),
padding: EdgeInsets.symmetric(vertical: 16.0f, horizontal: 36.0f),
onPressed: () => {
showDemoDialog(
context: _context,
child: new CupertinoDessertDialog()
);
}
),
// TODO: FIX BUG
new Padding(padding: EdgeInsets.all(8.0f)),
CupertinoButton.filled(
child: new Text("Action Sheet"),
padding: EdgeInsets.symmetric(vertical: 16.0f, horizontal: 36.0f),
onPressed: () => {
showDemoActionSheet(
context: _context,
child: new CupertinoActionSheet(
title: new Text("Favorite Dessert"),
message: new Text(
"Please select the best dessert from the options below."),
actions: new List<Widget> {
new CupertinoActionSheetAction(
child: new Text("Profiteroles"),
onPressed: () => {
Navigator.pop(_context, "Profiteroles");
}
),
new CupertinoActionSheetAction(
child: new Text("Cannolis"),
onPressed: () => {
Navigator.pop(_context, "Cannolis");
}
),
new CupertinoActionSheetAction(
child: new Text("Trifle"),
onPressed: () => { Navigator.pop(_context, "Trifle"); }
)
},
cancelButton: new CupertinoActionSheetAction(
child: new Text("Cancel"),
isDefaultAction: true,
onPressed: () => { Navigator.pop(_context, "Cancel"); }
)
)
);
}
)
}
)
};
void _onAlertPress(BuildContext context) {
showDemoDialog(
context: context,
child: new CupertinoAlertDialog(
title: new Text("Discard draft?"),
actions: new List<Widget>{
new CupertinoDialogAction(
child: new Text("Discard"),
isDestructiveAction: true,
onPressed: () => Navigator.pop(context, "Discard")
),
new CupertinoDialogAction(
child: new Text("Cancel"),
isDefaultAction: true,
onPressed: () => Navigator.pop(context, "Cancel")
),
}
)
);
}
void _onAlertWithTitlePress(BuildContext context) {
showDemoDialog(
context: context,
child: new CupertinoAlertDialog(
title: new Text("Allow \"Maps\" to access your location while you are using the app?"),
content: new Text("Your current location will be displayed on the map and used " +
"for directions, nearby search results, and estimated travel times."),
actions: new List<Widget>{
new CupertinoDialogAction(
child: new Text("Don't Allow"),
onPressed: () => Navigator.pop(context, "Disallow")
),
new CupertinoDialogAction(
child: new Text("Allow"),
onPressed: () => Navigator.pop(context, "Allow")
),
}
)
);
}
if (lastSelectedValue != null) {
stackChildren.Add(
new Positioned(
bottom: 32.0f,
child: new Text($"You selected: {lastSelectedValue}")
)
);
}
void _onAlertWithButtonsPress(BuildContext context) {
showDemoDialog(
context: context,
child: new CupertinoDessertDialog(
title: new Text("Select Favorite Dessert"),
content: new Text("Please select your favorite type of dessert from the " +
"list below. Your selection will be used to customize the suggested " +
"list of eateries in your area.")
)
);
}
return new Stack(
alignment: Alignment.center,
children: stackChildren
);
}
)
)
);
}
void _onActionSheetPress(BuildContext context) {
showDemoActionSheet(
context: context,
child: new CupertinoActionSheet(
title: new Text("Favorite Dessert"),
message: new Text("Please select the best dessert from the options below."),
actions: new List<Widget>{
new CupertinoActionSheetAction(
child: new Text("Profiteroles"),
onPressed: () => Navigator.pop(context, "Profiteroles")
),
new CupertinoActionSheetAction(
child: new Text("Cannolis"),
onPressed: () => Navigator.pop(context, "Cannolis")
),
new CupertinoActionSheetAction(
child: new Text("Trifle"),
onPressed: () => Navigator.pop(context, "Trifle")
),
},
cancelButton: new CupertinoActionSheetAction(
child: new Text("Cancel"),
isDefaultAction: true,
onPressed: () => Navigator.pop(context, "Cancel")
)
)
);
}
class CupertinoDessertDialog : StatelessWidget {
public CupertinoDessertDialog(
Key key = null,
Widget title = null,
Widget content = null
) : base(key: key) {
this.title = title;
this.content = content;
}
public class CupertinoDessertDialog : StatelessWidget {
public CupertinoDessertDialog(Key key = null, Widget title = null, Widget content = null) : base(key: key)
{
this.title = title;
this.content = content;
}
public readonly Widget title;
public readonly Widget content;
public override Widget build(BuildContext context) {
return new CupertinoAlertDialog(
title: title,
content: content,
actions: new List<Widget> {
new CupertinoDialogAction(
child: new Text("Cheesecake"),
onPressed: () => { Navigator.pop(context, "Cheesecake"); }
),
new CupertinoDialogAction(
child: new Text("Tiramisu"),
onPressed: () => { Navigator.pop(context, "Tiramisu"); }
),
new CupertinoDialogAction(
child: new Text("Apple Pie"),
onPressed:
() => { Navigator.pop(context, "Apple Pie"); }
),
new CupertinoDialogAction(
child: new Text("Devil\"s food cake"),
onPressed:
() => { Navigator.pop(context, "Devil\"s food cake"); }
),
new CupertinoDialogAction(
child: new Text("Banana Split"),
onPressed:
() => { Navigator.pop(context, "Banana Split"); }
),
new CupertinoDialogAction(
child: new Text("Oatmeal Cookie"),
onPressed:
() => { Navigator.pop(context, "Oatmeal Cookies"); }
),
new CupertinoDialogAction(
child: new Text("Chocolate Brownie"),
onPressed:
() => { Navigator.pop(context, "Chocolate Brownies"); }
),
new CupertinoDialogAction(
child: new Text("Cancel"),
isDestructiveAction:
true,
onPressed:
() => { Navigator.pop(context, "Cancel"); }
),
}
);
}
public readonly Widget title;
public readonly Widget content;
public override Widget build(BuildContext context) {
return new CupertinoAlertDialog(
title: title,
content: content,
actions: new List<Widget>{
new CupertinoDialogAction(
child: new Text("Cheesecake"),
onPressed: () => {
Navigator.pop(context, "Cheesecake");
}
),
new CupertinoDialogAction(
child: new Text("Tiramisu"),
onPressed: () => {
Navigator.pop(context, "Tiramisu");
}
),
new CupertinoDialogAction(
child: new Text("Apple Pie"),
onPressed: () => {
Navigator.pop(context, "Apple Pie");
}
),
new CupertinoDialogAction(
child: new Text("Devil's food cake"),
onPressed: () => {
Navigator.pop(context, "Devil's food cake");
}
),
new CupertinoDialogAction(
child: new Text("Banana Split"),
onPressed: () => {
Navigator.pop(context, "Banana Split");
}
),
new CupertinoDialogAction(
child: new Text("Oatmeal Cookie"),
onPressed: () => {
Navigator.pop(context, "Oatmeal Cookies");
}
),
new CupertinoDialogAction(
child: new Text("Chocolate Brownie"),
onPressed: () => {
Navigator.pop(context, "Chocolate Brownies");
}
),
new CupertinoDialogAction(
child: new Text("Cancel"),
isDestructiveAction: true,
onPressed: () => {
Navigator.pop(context, "Cancel");
}
)
}
);
}
}

135
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_buttons_demo.cs


using Unity.UIWidgets.widgets;
namespace UIWidgetsGallery.gallery {
class CupertinoButtonsDemo : StatefulWidget {
public class CupertinoButtonsDemo : StatefulWidget {
public static string routeName = "/cupertino/buttons";
public override State createState() {

class _CupertinoButtonDemoState : State<CupertinoButtonsDemo> {
int _pressedCount = 0;
public class _CupertinoButtonDemoState : State<CupertinoButtonsDemo> {
int _pressedCount = 0;
public override Widget build(BuildContext context)
{
string timeStr = _pressedCount == 1 ? "" : "s";
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Buttons"),
public override Widget build(BuildContext context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Buttons"),
previousPageTitle: "Cupertino"
//, trailing: new CupertinoDemoDocumentationButton(CupertinoButtonsDemo.routeName)
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new SafeArea(
child: new Column(
children: new List<Widget> {
new Padding(
padding: EdgeInsets.all(16.0f),
child: new Text(
"iOS themed buttons are flat. They can have borders or backgrounds but only when necessary."
)
),
new Expanded(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: new List<Widget> {
new Text(_pressedCount > 0
? $"Button pressed {_pressedCount} time" +
(_pressedCount == 1 ? "" : "s")
: " "),
new Padding(padding: EdgeInsets.all(12.0f)),
new Align(
alignment: new Alignment(0.0f, -0.2f),
child:
new Row(
mainAxisSize: MainAxisSize.min,
children: new List<Widget> {
new CupertinoButton(
child: new Text("Cupertino Button"),
onPressed:
() => { setState(() => { _pressedCount += 1; }); }
),
new CupertinoButton(
child: new Text("Disabled"),
onPressed: null
)
}
)
),
new Padding(padding: EdgeInsets.all(12.0f)),
CupertinoButton.filled(
child: new Text("With Background"),
onPressed:
() => { setState(() => { _pressedCount += 1; }); }
),
new Padding(padding: EdgeInsets.all(12.0f)),
CupertinoButton.filled(
child: new Text("Disabled"),
onPressed: null
),
}
)
)
previousPageTitle: "Cupertino"
//trailing: CupertinoDemoDocumentationButton(CupertinoButtonsDemo.routeName),
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new SafeArea(
child: new Column(
children: new List<Widget>{
new Padding(
padding: EdgeInsets.all(16.0f),
child: new Text(
"iOS themed buttons are flat. They can have borders or backgrounds but " +
"only when necessary."
)
),
new Expanded(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: new List<Widget>
{
new Text(_pressedCount > 0
? $"Button pressed {_pressedCount} time{timeStr}"
: " "),
new Padding(padding: EdgeInsets.all(12.0f)),
new Align(
alignment: new Alignment(0.0f, -0.2f),
child: new Row(
mainAxisSize: MainAxisSize.min,
children: new List<Widget>
{
new CupertinoButton(
child: new Text("Cupertino Button"),
onPressed: () => { setState(() => { _pressedCount += 1; }); }
),
new CupertinoButton(
child: new Text("Disabled"),
onPressed: null
)
)
),
new Padding(padding: EdgeInsets.all(12.0f)),
CupertinoButton.filled(
child: new Text("With Background"),
onPressed: () => { setState(() => { _pressedCount += 1; }); }
),
new Padding(padding: EdgeInsets.all(12.0f)),
CupertinoButton.filled(
child: new Text("Disabled"),
onPressed: null
}
)
);
}
)
}
)
)
)
);
}
}

518
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_picker_demo.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.cupertino;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.service;

class CupertinoPickerDemoUtils {
public const float _kPickerSheetHeight = 216.0f;
public const float _kPickerItemHeight = 32.0f;
public static List<string> coolColorNames = new List<string>{
"Sarcoline", "Coquelicot", "Smaragdine", "Mikado", "Glaucous", "Wenge",
"Fulvous", "Xanadu", "Falu", "Eburnean", "Amaranth", "Australien",
"Banan", "Falu", "Gingerline", "Incarnadine", "Labrador", "Nattier",
"Pervenche", "Sinoper", "Verditer", "Watchet", "Zaffre",
};
class CupertinoPickerDemo : StatefulWidget {
public const string routeName = "/cupertino/picker";
public class CupertinoPickerDemo : StatefulWidget {
public const string routeName = "/cupertino/picker";
public override State createState() {
return new _CupertinoPickerDemoState();
}
public override State createState() {
return new _CupertinoPickerDemoState();
}
class _CupertinoPickerDemoState : State<CupertinoPickerDemo> {
int _selectedColorIndex = 0;
TimeSpan timer = new TimeSpan();
// Value that is shown in the date picker in date mode.
DateTime date = DateTime.Now;
// Value that is shown in the date picker in time mode.
DateTime time = DateTime.Now;
// Value that is shown in the date picker in dateAndTime mode.
DateTime dateTime = DateTime.Now;
Widget _buildMenu(List<Widget> children) {
return new Container(
decoration: new BoxDecoration(
color: CupertinoTheme.of(context).scaffoldBackgroundColor,
border: new Border(
top: new BorderSide(color: new Color(0xFFBCBBC1), width: 0.0f),
bottom: new BorderSide(color: new Color(0xFFBCBBC1), width: 0.0f)
)
),
height: 44.0f,
child: new Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0f),
child: new SafeArea(
top: false,
bottom: false,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: children
)
)
)
);
public class _CupertinoPickerDemoState : State<CupertinoPickerDemo> {
int _selectedColorIndex = 0;
TimeSpan timer = new TimeSpan();
DateTime date = DateTime.Now;
DateTime time = DateTime.Now;
DateTime dateTime = DateTime.Now;
Widget _buildColorPicker(BuildContext context) {
FixedExtentScrollController scrollController = new FixedExtentScrollController(initialItem: _selectedColorIndex);
List<Widget> widgets = new List<Widget>();
for (int i = 0; i < CupertinoPickerDemoUtils.coolColorNames.Count; i++)
{
widgets.Add(new Center(
child: new Text(CupertinoPickerDemoUtils.coolColorNames[i])
));
Widget _buildBottomPicker(Widget picker) {
return new Container(
height: CupertinoPickerDemoUtils._kPickerSheetHeight,
padding: EdgeInsets.only(top: 6.0f),
color: CupertinoColors.white,
child: new DefaultTextStyle(
style: new TextStyle(
color: CupertinoColors.black,
fontSize: 22.0f
),
child: new GestureDetector(
// Blocks taps from propagating to the modal sheet and popping.
onTap: () => { },
child: new SafeArea(
top: false,
child: picker
)
)
)
return new GestureDetector(
onTap: () => {
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
semanticsDismissible: true,
builder: (BuildContext context1) =>{
return new _BottomPicker(
child: new CupertinoPicker(
scrollController: scrollController,
itemExtent: CupertinoPickerDemoUtils._kPickerItemHeight,
backgroundColor: CupertinoColors.systemBackground.resolveFrom(context1),
onSelectedItemChanged: (int index)=> {
setState(() => _selectedColorIndex = index);
},
children: widgets
)
}
);
},
child: new _Menu(
children: new List<Widget>{
new Text("Favorite Color"),
new Text(
CupertinoPickerDemoUtils.coolColorNames[_selectedColorIndex],
style: new TextStyle(color: CupertinoDynamicColor.resolve(CupertinoColors.inactiveGray, context))
)
)
);
}
Widget _buildColorPicker(BuildContext context) {
FixedExtentScrollController scrollController =
new FixedExtentScrollController(initialItem: _selectedColorIndex);
List<Widget> generateList() {
var list = new List<Widget>();
foreach (var item in CupertinoNavigationDemoUtils.coolColorNames) {
list.Add(new Center(child:
new Text(item)
));
Widget _buildCountdownTimerPicker(BuildContext context) {
return new GestureDetector(
onTap: () =>{
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
semanticsDismissible: true,
builder: (BuildContext context1) =>{
return new _BottomPicker(
child: new CupertinoTimerPicker(
backgroundColor: CupertinoColors.systemBackground.resolveFrom(context1),
initialTimerDuration: timer,
onTimerDurationChanged: (newTimer) =>{
setState(() => timer = newTimer);
return list;
}
return new GestureDetector(
onTap: () => {
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
builder: (BuildContext _context) => {
return _buildBottomPicker(
new CupertinoPicker(
scrollController: scrollController,
itemExtent: CupertinoPickerDemoUtils._kPickerItemHeight,
backgroundColor: CupertinoColors.white,
onSelectedItemChanged: (int index) => {
setState(() => _selectedColorIndex = index);
},
children: generateList()
)
);
}
);
},
child: _buildMenu(new List<Widget> {
new Text("Favorite Color"),
new Text(
CupertinoNavigationDemoUtils.coolColorNames[_selectedColorIndex],
style: new TextStyle(
color: CupertinoColors.inactiveGray
)
)
}
)
)
}
);
},
child: new _Menu(
children: new List<Widget>{
new Text("Countdown Timer"),
new Text(
$"{timer.Hours}:" +
$"{(timer.Minutes % 60).ToString("00")}:" +
$"{(timer.Seconds % 60).ToString("00")}",
style: new TextStyle(color: CupertinoDynamicColor.resolve(CupertinoColors.inactiveGray, context))
),
)
);
}
Widget _buildCountdownTimerPicker(BuildContext context) {
return new GestureDetector(
onTap: () => {
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
builder: (BuildContext _context) => {
return _buildBottomPicker(
new CupertinoTimerPicker(
initialTimerDuration: timer,
onTimerDurationChanged: (TimeSpan newTimer) => {
setState(() => timer = newTimer);
}
)
);
}
);
},
child: _buildMenu(new List<Widget> {
new Text("Countdown Timer"),
new Text(
$"{timer.Hours}:" +
$"{(timer.Minutes % 60).ToString("00")}:" +
$"{(timer.Seconds % 60).ToString("00")}",
style: new TextStyle(color: CupertinoColors.inactiveGray)
)
}
)
Widget _buildDatePicker(BuildContext context)
{
return new GestureDetector(
onTap: () =>
{
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
semanticsDismissible: true,
builder: (BuildContext context1) =>
{
return new _BottomPicker(
child: new CupertinoDatePicker(
backgroundColor: CupertinoColors.systemBackground.resolveFrom(context1),
mode: CupertinoDatePickerMode.date,
initialDateTime: date,
onDateTimeChanged: (newDateTime) => { setState(() => date = newDateTime); }
)
}
);
},
child: new _Menu(
children: new List<Widget>{
new Text("Date"),
new Text(
date.ToString("MMMM dd, yyyy"),
style: new TextStyle(color: CupertinoDynamicColor.resolve(CupertinoColors.inactiveGray, context))
),
)
);
}
Widget _buildDatePicker(BuildContext context) {
return new GestureDetector(
onTap: () => {
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
builder: (BuildContext _context) => {
return _buildBottomPicker(
new CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
initialDateTime: date,
onDateTimeChanged: (DateTime newDateTime) => {
setState(() => date = newDateTime);
}
)
);
}
);
},
child: _buildMenu(new List<Widget> {
new Text("Date"),
new Text(
date.ToString("MMMM dd, yyyy"),
style: new TextStyle(color: CupertinoColors.inactiveGray)
)
}
)
Widget _buildTimePicker(BuildContext context) {
return new GestureDetector(
onTap: () =>{
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
semanticsDismissible: true,
builder: (BuildContext context1) =>{
return new _BottomPicker(
child: new CupertinoDatePicker(
backgroundColor: CupertinoColors.systemBackground.resolveFrom(context1),
mode: CupertinoDatePickerMode.time,
initialDateTime: time,
onDateTimeChanged: (newDateTime) => {
setState(() => time = newDateTime);
}
)
}
);
},
child:new _Menu(
children: new List<Widget>{
new Text("Time"),
new Text(
time.ToString("h:mm tt"),
style: new TextStyle(color: CupertinoDynamicColor.resolve(CupertinoColors.inactiveGray, context))
),
)
);
}
Widget _buildTimePicker(BuildContext context) {
return new GestureDetector(
onTap: () => {
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
builder: (BuildContext _context) => {
return _buildBottomPicker(
new CupertinoDatePicker(
mode: CupertinoDatePickerMode.time,
initialDateTime: time,
onDateTimeChanged: (DateTime newDateTime) => {
setState(() => time = newDateTime);
}
)
);
}
);
},
child: _buildMenu(new List<Widget> {
new Text("Time"),
new Text(
time.ToString("h:mm tt"),
style: new TextStyle(color: CupertinoColors.inactiveGray)
)
}
)
Widget _buildDateAndTimePicker(BuildContext context) {
return new GestureDetector(
onTap: ()=> {
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
semanticsDismissible: true,
builder: (BuildContext context1) =>{
return new _BottomPicker(
child: new CupertinoDatePicker(
backgroundColor: CupertinoColors.systemBackground.resolveFrom(context1),
mode: CupertinoDatePickerMode.dateAndTime,
initialDateTime: dateTime,
onDateTimeChanged: (newDateTime) => {
setState(() => dateTime = newDateTime);
}
)
}
);
},
child: new _Menu(
children:new List<Widget>{
new Text("Date and Time"),
new Text(
dateTime.ToString("MMMM dd, yyyy h:mm tt"),
style: new TextStyle(color: CupertinoDynamicColor.resolve(CupertinoColors.inactiveGray, context))
),
)
);
}
public override Widget build(BuildContext context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Picker"),
// We're specifying a back label here because the previous page is a
// Material page. CupertinoPageRoutes could auto-populate these back
// labels.
previousPageTitle: "Cupertino"
//trailing: CupertinoDemoDocumentationButton(CupertinoPickerDemo.routeName)
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new ListView(
children: new List<Widget>{
new Padding(padding: EdgeInsets.only(top: 32.0f)),
_buildColorPicker(context),
//_buildCountdownTimerPicker(context),
//_buildDatePicker(context),
//_buildTimePicker(context),
//_buildDateAndTimePicker(context),
}
)
)
);
}
}
}
Widget _buildDateAndTimePicker(BuildContext context) {
return new GestureDetector(
onTap: () => {
CupertinoRouteUtils.showCupertinoModalPopup(
context: context,
builder: (BuildContext _context) => {
return _buildBottomPicker(
new CupertinoDatePicker(
mode: CupertinoDatePickerMode.dateAndTime,
initialDateTime: dateTime,
onDateTimeChanged: (DateTime newDateTime) => {
setState(() => dateTime = newDateTime);
}
)
);
}
);
},
child: _buildMenu(new List<Widget> {
new Text("Date and Time"),
new Text(
dateTime.ToString("MMMM dd, yyyy h:mm tt"),
style: new TextStyle(color: CupertinoColors.inactiveGray)
)
}
)
);
}
public class _BottomPicker : StatelessWidget {
public _BottomPicker(
Key key = null,
Widget child = null
) : base(key: key){
D.assert(child != null);
this.child = child;
}
public readonly Widget child;
public override Widget build(BuildContext context) {
return new Container(
height: 216,
padding: EdgeInsets.only(top: 6),
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom
),
color: CupertinoColors.systemBackground.resolveFrom(context),
child: new DefaultTextStyle(
style: new TextStyle(
color: CupertinoColors.label.resolveFrom(context),
fontSize: 22
),
child: new GestureDetector(
// Blocks taps from propagating to the modal sheet and popping.
onTap: ()=> {},
child: new SafeArea(
top: false,
child: child
)
)
)
);
}
}
public class _Menu : StatelessWidget {
public _Menu(
Key key = null,
List<Widget> children = null
) :base(key: key) {
D.assert(children != null);
this.children = children;
}
public readonly List<Widget> children;
public override Widget build(BuildContext context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Picker"),
// We"re specifying a back label here because the previous page is a
// Material page. CupertinoPageRoutes could auto-populate these back
// labels.
previousPageTitle: "Cupertino"
//, trailing: new CupertinoDemoDocumentationButton(CupertinoPickerDemo.routeName)
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new DecoratedBox(
decoration: new BoxDecoration(
color: CupertinoTheme.of(context).brightness == Brightness.light
? CupertinoColors.extraLightBackgroundGray
: CupertinoColors.darkBackgroundGray
),
child: new SafeArea(
child: new ListView(
children: new List<Widget> {
new Padding(padding: EdgeInsets.only(top: 32.0f)),
_buildColorPicker(context),
_buildCountdownTimerPicker(context),
_buildDatePicker(context),
_buildTimePicker(context),
_buildDateAndTimePicker(context)
}
)
)
)
)
);
}
}
}
public override Widget build(BuildContext context) {
return new Container(
decoration: new BoxDecoration(
border: new Border(
top: new BorderSide(color: CupertinoColors.inactiveGray, width: 0),
bottom: new BorderSide(color: CupertinoColors.inactiveGray, width: 0)
)
),
height: 44,
child: new Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: children
)
)
);
}
}

105
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_slider_demo.cs


using Unity.UIWidgets.widgets;
namespace UIWidgetsGallery.gallery {
class CupertinoSliderDemo : StatefulWidget {
public class CupertinoSliderDemo : StatefulWidget {
public static string routeName = "/cupertino/slider";
public override State createState() {

class _CupertinoSliderDemoState : State<CupertinoSliderDemo> {
float _value = 25.0f;
float _discreteValue = 20.0f;
public class _CupertinoSliderDemoState : State<CupertinoSliderDemo> {
float _value = 25.0f;
float _discreteValue = 20.0f;
public override Widget build(BuildContext context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Sliders"),
previousPageTitle: "Cupertino"
//, trailing: new CupertinoDemoDocumentationButton(CupertinoSliderDemo.routeName)
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new SafeArea(
child: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: new List<Widget> {
new Column(
mainAxisSize: MainAxisSize.min,
children: new List<Widget> {
new CupertinoSlider(
value: _value,
min: 0.0f,
max: 100.0f,
onChanged: (float value) => {
setState(() => { _value = value; });
}
),
new Text($"Cupertino Continuous: {_value.ToString("F1")}"),
}
),
new Column(
mainAxisSize: MainAxisSize.min,
children: new List<Widget> {
new CupertinoSlider(
value: _discreteValue,
min: 0.0f,
max: 100.0f,
divisions: 5,
onChanged: (float value) => {
setState(() => { _discreteValue = value; });
}
),
new Text($"Cupertino Discrete: {_discreteValue}"),
}
),
}
)
)
)
)
);
}
public override Widget build(BuildContext context)
{
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Sliders"),
previousPageTitle: "Cupertino"
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new SafeArea(
child: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: new List< Widget >{
new Column(
mainAxisSize: MainAxisSize.min,
children: new List< Widget >{
new CupertinoSlider(
value: _value,
min: 0.0f,
max: 100.0f,
onChanged: (float value) => { setState(() => { _value = value; }); }
),
new Text($"Cupertino Continuous: {_value:F1}"),
}
),
new Column(
mainAxisSize: MainAxisSize.min,
children: new List< Widget >{
new CupertinoSlider(
value: _discreteValue,
min: 0.0f,
max: 100.0f,
divisions: 5,
onChanged: (float value) => { setState(() => { _discreteValue = value; }); }
),
new Text($"Cupertino Discrete: {_discreteValue}")
}
)
}
)
)
)
)
);
}
}

117
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_switch_demo.cs


}
class _CupertinoSwitchDemoState : State<CupertinoSwitchDemo> {
bool _switchValue = false;
public override Widget build(BuildContext context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Switch"),
previousPageTitle: "Cupertino"
//, trailing: new CupertinoDemoDocumentationButton(CupertinoSwitchDemo.routeName)
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new SafeArea(
child: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: new List<Widget> {
new Column(
children: new List<Widget> {
new CupertinoSwitch(
value: _switchValue,
onChanged: (bool value) => {
setState(() => { _switchValue = value; });
}
),
new Text(
"Enabled - " + (_switchValue ? "On" : "Off")
),
}
),
new Column(
children: new List<Widget> {
new CupertinoSwitch(
value: true,
onChanged: null
),
new Text(
"Disabled - On"
),
}
),
new Column(
children: new List<Widget> {
new CupertinoSwitch(
value: false,
onChanged: null
),
new Text(
"Disabled - Off"
),
}
),
}
)
)
bool _switchValue = false;
public override Widget build(BuildContext context)
{
string switchStr = _switchValue ? "On" : "Off";
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Switch"),
previousPageTitle: "Cupertino"
// trailing: CupertinoDemoDocumentationButton(CupertinoSwitchDemo.routeName),
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new SafeArea(
child: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: new List<Widget>{
new Column(
children: new List<Widget>{
new CupertinoSwitch(
value: _switchValue,
onChanged: (bool value)=> {
setState(()=> {
_switchValue = value;
});
}
),
new Text(
$"Enabled - {switchStr}"
)
}
),
new Column(
children: new List<Widget>{
new CupertinoSwitch(
value: true,
onChanged: null
),
new Text(
"Disabled - On"
),
}
),
new Column(
children: new List<Widget>{
new CupertinoSwitch(
value: false,
onChanged: null
),
new Text(
"Disabled - Off"
),
}
}
);
}
)
)
)
);
}
}

339
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_text_field_demo.cs


}
class _CupertinoTextFieldDemoState : State<CupertinoTextFieldDemo> {
TextEditingController _chatTextController;
TextEditingController _locationTextController;
TextEditingController _chatTextController;
TextEditingController _locationTextController;
public override void initState() {
base.initState();
_chatTextController = new TextEditingController();
_locationTextController = new TextEditingController(text: "Montreal, Canada");
}
public override void initState() {
base.initState();
_chatTextController = new TextEditingController();
_locationTextController = new TextEditingController(text: "Montreal, Canada");
}
Widget _buildChatTextField() {
return new CupertinoTextField(
controller: _chatTextController,
textCapitalization: TextCapitalization.sentences,
placeholder: "Text Message",
decoration: new BoxDecoration(
border: Border.all(
width: 0.0f,
color: CupertinoColors.inactiveGray
),
borderRadius: BorderRadius.circular(15.0f)
),
maxLines: null,
keyboardType: TextInputType.multiline,
prefix: new Padding(padding: EdgeInsets.symmetric(horizontal: 4.0f)),
suffix:
new Padding(
padding: EdgeInsets.symmetric(horizontal: 4.0f),
child: new CupertinoButton(
color: CupertinoColors.activeGreen,
minSize: 0.0f,
child: new Icon(
CupertinoIcons.up_arrow,
size: 21.0f,
color: CupertinoColors.white
),
padding: EdgeInsets.all(2.0f),
borderRadius:
BorderRadius.circular(15.0f),
onPressed: () => setState(() => _chatTextController.clear())
)
),
autofocus: true,
suffixMode: OverlayVisibilityMode.editing,
onSubmitted: (string text) => setState(() => _chatTextController.clear())
);
}
Widget _buildChatTextField() {
return new CupertinoTextField(
controller: _chatTextController,
textCapitalization: TextCapitalization.sentences,
placeholder: "Text Message",
decoration: new BoxDecoration(
border: Border.all(
width: 0.0f,
color: CupertinoColors.inactiveGray
),
borderRadius: BorderRadius.circular(15.0f)
),
maxLines: null,
keyboardType: TextInputType.multiline,
prefix: new Padding(padding: EdgeInsets.symmetric(horizontal: 4.0f)),
suffix: new Padding(
padding: EdgeInsets.symmetric(horizontal: 4.0f),
child: new CupertinoButton(
color: CupertinoColors.activeGreen,
minSize: 0.0f,
child: new Icon(
CupertinoIcons.up_arrow,
size: 21.0f,
color: CupertinoColors.white
),
padding: EdgeInsets.all(2.0f),
borderRadius: BorderRadius.circular(15.0f),
onPressed: ()=> setState(()=> _chatTextController.clear())
)
),
autofocus: true,
suffixMode: OverlayVisibilityMode.editing,
onSubmitted: (string text)=> setState(()=> _chatTextController.clear())
);
}
Widget _buildNameField() {
return new CupertinoTextField(
prefix: new Icon(
CupertinoIcons.person_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
clearButtonMode: OverlayVisibilityMode.editing,
textCapitalization: TextCapitalization.words,
autocorrect: false,
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
),
placeholder: "Name"
);
}
Widget _buildNameField() {
return new CupertinoTextField(
prefix: new Icon(
CupertinoIcons.person_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
clearButtonMode: OverlayVisibilityMode.editing,
textCapitalization: TextCapitalization.words,
autocorrect: false,
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
),
placeholder: "Name"
);
}
Widget _buildEmailField() {
return new CupertinoTextField(
prefix: new Icon(
CupertinoIcons.mail_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
clearButtonMode: OverlayVisibilityMode.editing,
keyboardType: TextInputType.emailAddress,
autocorrect: false,
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
),
placeholder: "Email"
);
}
Widget _buildEmailField() {
return new CupertinoTextField(
prefix: new Icon(
CupertinoIcons.mail_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
clearButtonMode: OverlayVisibilityMode.editing,
keyboardType: TextInputType.emailAddress,
autocorrect: false,
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
),
placeholder: "Email"
);
}
Widget _buildLocationField() {
return new CupertinoTextField(
controller: _locationTextController,
prefix: new Icon(
CupertinoIcons.location_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
clearButtonMode: OverlayVisibilityMode.editing,
textCapitalization: TextCapitalization.words,
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
),
placeholder: "Location"
);
}
Widget _buildLocationField() {
return new CupertinoTextField(
controller: _locationTextController,
prefix: new Icon(
CupertinoIcons.location_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
clearButtonMode: OverlayVisibilityMode.editing,
textCapitalization: TextCapitalization.words,
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
),
placeholder: "Location"
);
}
Widget _buildPinField() {
return new CupertinoTextField(
prefix: new Icon(
CupertinoIcons.padlock_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
clearButtonMode: OverlayVisibilityMode.editing,
keyboardType: TextInputType.number,
autocorrect: false,
obscureText: true,
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
),
placeholder: "Create a PIN"
);
}
Widget _buildPinField() {
return new CupertinoTextField(
prefix: new Icon(
CupertinoIcons.padlock_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
clearButtonMode: OverlayVisibilityMode.editing,
keyboardType: TextInputType.number,
autocorrect: false,
obscureText: true,
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
),
placeholder: "Create a PIN"
);
}
Widget _buildTagsField() {
return new CupertinoTextField(
controller: new TextEditingController(text: "colleague, reading club"),
prefix: new Icon(
CupertinoIcons.tags_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
enabled: false,
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
),
placeholder:"test"
);
}
Widget _buildTagsField() {
return new CupertinoTextField(
controller: new TextEditingController(text: "colleague, reading club"),
prefix: new Icon(
CupertinoIcons.tags_solid,
color: CupertinoColors.lightBackgroundGray,
size: 28.0f
),
enabled: false,
padding: EdgeInsets.symmetric(horizontal: 6.0f, vertical: 12.0f),
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0f, color: CupertinoColors.inactiveGray))
)
);
}
public override Widget build(BuildContext context) {
return new DefaultTextStyle(
style: new TextStyle(
fontFamily: ".SF Pro Text", // ".SF UI Text",
inherit: false,
fontSize: 17.0f,
color: CupertinoColors.black
),
child: new CupertinoPageScaffold(
/*navigationBar: new CupertinoNavigationBar(
previousPageTitle: "Cupertino",
middle: new Text("Text Fields")
),*/
child:
/*new Padding(
padding: EdgeInsets.symmetric(vertical: 32.0f, horizontal: 16.0f),
child: this._buildTagsField()//_buildChatTextField()
)*/
new SafeArea(
child:
new ListView(
children: new List<Widget> {
new Padding(
padding: EdgeInsets.symmetric(vertical: 32.0f, horizontal: 16.0f),
child: new Column(
children: new List<Widget> {
//this._buildNameField(),
//this._buildEmailField(),// !点击crash!
_buildLocationField()//, // !点击crash!
//this._buildPinField(),// !点击crash!
//this._buildTagsField()
}
)
),
new Padding(
padding: EdgeInsets.symmetric(vertical: 32.0f, horizontal: 16.0f)//,
//child: this._buildChatTextField()
)
}
)
public override Widget build(BuildContext context) {
return new DefaultTextStyle(
style: new TextStyle(
fontFamily: ".SF UI Text",
inherit: false,
fontSize: 17.0f,
color: CupertinoColors.black
),
child: new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
previousPageTitle: "Cupertino",
middle: new Text("Text Fields")
),
child: new CupertinoScrollbar(
child: new ListView(
children: new List<Widget>{
new Padding(
padding: EdgeInsets.symmetric(vertical: 32.0f, horizontal: 16.0f),
child: new Column(
children: new List<Widget>{
_buildNameField(),
_buildEmailField(),
_buildLocationField(),
_buildPinField(),
_buildTagsField()
}
)
);
}
),
new Padding(
padding: EdgeInsets.symmetric(vertical: 32.0f, horizontal: 16.0f),
child: _buildChatTextField()
)
}
)
)
)
);
}
}

41
com.unity.uiwidgets/Runtime/cupertino/route.cs


routeSettings: routeSettings
);
}
public static Future<T> showCupertinoDialog<T>(
BuildContext context = null,
WidgetBuilder builder =null,
bool useRootNavigator = true,
RouteSettings routeSettings = null
) {
D.assert(builder != null);
D.assert(useRootNavigator != null);
return DialogUtils.showGeneralDialog<T>(
context: context,
barrierDismissible: false,
barrierColor: CupertinoDynamicColor.resolve(_kModalBarrierColor, context),
// This transition duration was eyeballed comparing with iOS
transitionDuration: TimeSpan.FromMilliseconds(250),
pageBuilder: (BuildContext context1, Animation<float> animation, Animation<float> secondaryAnimation)=> {
return builder(context1);
},
transitionBuilder: _buildCupertinoDialogTransitions,
useRootNavigator: useRootNavigator,
routeSettings: routeSettings
);
}
public static Future<T> showCupertinoModalPopup<T>(
BuildContext context = null,
WidgetBuilder builder =null,
ImageFilter filter = null,
bool useRootNavigator = true,
bool? semanticsDismissible =null
) {
D.assert(useRootNavigator != null);
return Navigator.of(context, rootNavigator: useRootNavigator).push(
new _CupertinoModalPopupRoute(
barrierColor: CupertinoDynamicColor.resolve(_kModalBarrierColor, context),
barrierLabel: "Dismiss",
builder: builder,
filter: filter
)
).to<T>();
}
}
class _CupertinoEdgeShadowDecoration : Decoration, IEquatable<_CupertinoEdgeShadowDecoration> {

3
com.unity.uiwidgets/Runtime/cupertino/tab_scaffold.cs


List<FocusScopeNode> scopeNodes = new List<FocusScopeNode>();
var length = widget.tabNumber - tabFocusNodes.Count;
for (int i = 0; i < length; i++) {
tabFocusNodes.Add(new FocusScopeNode(debugLabel: $"CupertinoTabScaffold Tab {i + tabFocusNodes.Count}")
scopeNodes.Add(new FocusScopeNode(debugLabel: $"CupertinoTabScaffold Tab {i + tabFocusNodes.Count}")
tabFocusNodes.AddRange(scopeNodes);
}

8
com.unity.uiwidgets/Runtime/ui2/geometry.cs


public static Rect fromCircle(Offset center, float radius) {
return new Rect(center.dx - radius, center.dy - radius, center.dx + radius, center.dy + radius);
}
public static Rect fromCenter( Offset center, float width, float height ) {
return new Rect(
center.dx - width / 2,
center.dy - height / 2,
center.dx + width / 2,
center.dy + height / 2
);
}
public static Rect fromPoints(Offset a, Offset b) {
return new Rect(

5
com.unity.uiwidgets/Runtime/widgets/heroes.cs


}
}
foreach (object tag in toHeroes.Keys) {
if (fromHeroes[tag] == null)
_HeroState heroState = new _HeroState();
if (!fromHeroes.TryGetValue(tag, out heroState)) {
}
}
}

2
com.unity.uiwidgets/Runtime/widgets/navigator.cs


public class NavigatorState : TickerProviderStateMixin<Navigator> {
public readonly GlobalKey<OverlayState> _overlayKey = GlobalKey<OverlayState>.key();
public List<_RouteEntry> _history = new List<_RouteEntry>();
public readonly FocusScopeNode focusScopeNode = new FocusScopeNode();
public readonly FocusScopeNode focusScopeNode = new FocusScopeNode(debugLabel: "Navigator Scope");
public bool _debugLocked = false; // used to prevent re-entrant calls to push, pop, and friends
public override void initState() {

237
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_refresh_demo.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.async2;
using Unity.UIWidgets.cupertino;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
using Random = System.Random;
namespace UIWidgetsGallery.gallery {
class CupertinoRefreshControlDemo : StatefulWidget {
public static string routeName = "/cupertino/refresh";
public override State createState()
{
return new _CupertinoRefreshControlDemoState();
}
}
class _CupertinoRefreshControlDemoState : State<CupertinoRefreshControlDemo> {
List<List<string>> contacts = new List<List<string>>{
new List<string>{"George Washington", "Westmoreland County", " 4/30/1789"},
new List<string>{"John Adams", "Braintree", " 3/4/1797"},
new List<string>{"Thomas Jefferson", "Shadwell", " 3/4/1801"},
new List<string>{"James Madison", "Port Conway", " 3/4/1809"},
new List<string>{"James Monroe", "Monroe Hall", " 3/4/1817"},
new List<string>{"Andrew Jackson", "Waxhaws Region South/North", " 3/4/1829"},
new List<string>{"John Quincy Adams", "Braintree", " 3/4/1825"},
new List<string>{"William Henry Harrison", "Charles City County", " 3/4/1841"},
new List<string>{"Martin Van Buren", "Kinderhook New", " 3/4/1837"},
new List<string>{"Zachary Taylor", "Barboursville", " 3/4/1849"},
new List<string>{"John Tyler", "Charles City County", " 4/4/1841"},
new List<string>{"James Buchanan", "Cove Gap", " 3/4/1857"},
new List<string>{"James K. Polk", "Pineville North", " 3/4/1845"},
new List<string>{"Millard Fillmore", "Summerhill New", "7/9/1850"},
new List<string>{"Franklin Pierce", "Hillsborough New", " 3/4/1853"},
new List<string>{"Andrew Johnson", "Raleigh North", " 4/15/1865"},
new List<string>{"Abraham Lincoln", "Sinking Spring", " 3/4/1861"},
new List<string>{"Ulysses S. Grant", "Point Pleasant", " 3/4/1869"},
new List<string>{"Rutherford B. Hayes", "Delaware", " 3/4/1877"},
new List<string>{"Chester A. Arthur", "Fairfield", " 9/19/1881"},
new List<string>{"James A. Garfield", "Moreland Hills", " 3/4/1881"},
new List<string>{"Benjamin Harrison", "North Bend", " 3/4/1889"},
new List<string>{"Grover Cleveland", "Caldwell New", " 3/4/1885"},
new List<string>{"William McKinley", "Niles", " 3/4/1897"},
new List<string>{"Woodrow Wilson", "Staunton", " 3/4/1913"},
new List<string>{"William H. Taft", "Cincinnati", " 3/4/1909"},
new List<string>{"Theodore Roosevelt", "New York City New", " 9/14/1901"},
new List<string>{"Warren G. Harding", "Blooming Grove", " 3/4/1921"},
new List<string>{"Calvin Coolidge", "Plymouth", "8/2/1923"},
new List<string>{"Herbert Hoover", "West Branch", " 3/4/1929"},
new List<string>{"Franklin D. Roosevelt", "Hyde Park New", " 3/4/1933"},
new List<string>{"Harry S. Truman", "Lamar", " 4/12/1945"},
new List<string>{"Dwight D. Eisenhower", "Denison", " 1/20/1953"},
new List<string>{"Lyndon B. Johnson", "Stonewall", "11/22/1963"},
new List<string>{"Ronald Reagan", "Tampico", " 1/20/1981"},
new List<string>{"Richard Nixon", "Yorba Linda", " 1/20/1969"},
new List<string>{"Gerald Ford", "Omaha", "August 9/1974"},
new List<string>{"John F. Kennedy", "Brookline", " 1/20/1961"},
new List<string>{"George H. W. Bush", "Milton", " 1/20/1989"},
new List<string>{"Jimmy Carter", "Plains", " 1/20/1977"},
new List<string>{"George W. Bush", "New Haven", " 1/20, 2001"},
new List<string>{"Bill Clinton", "Hope", " 1/20/1993"},
new List<string>{"Barack Obama", "Honolulu", " 1/20/2009"},
new List<string>{"Donald J. Trump", "New York City", " 1/20/2017"}
};
List<List<string>> randomizedContacts;
public override void initState() {
base.initState();
repopulateList();
}
void repopulateList() {
Random random = new Random();
for (int index = 0; index < 100; index++ ){
contacts[random.Next()].Add(random.Next()%2 == 0 ? true.ToString() : false.ToString());
randomizedContacts.Add(contacts[random.Next()]);
}
}
public override Widget build(BuildContext context) {
return new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: new CupertinoPageScaffold(
backgroundColor: CupertinoColors.systemGroupedBackground,
child: new CustomScrollView(
physics: new BouncingScrollPhysics(parent: new AlwaysScrollableScrollPhysics()),
slivers: new List<Widget>{
new CupertinoSliverNavigationBar(
largeTitle: new Text("Refresh"),
previousPageTitle: "Cupertino"
//trailing: CupertinoDemoDocumentationButton(CupertinoRefreshControlDemo.routeName),
),
new CupertinoSliverRefreshControl(
onRefresh: () =>{
return Future.delayed(new TimeSpan(0,0,0,2)).then((_)=> {
if (mounted) {
setState(() => repopulateList());
}
});
}
),
new SliverSafeArea(
top: false, // Top safe area is consumed by the navigation bar.
sliver: new SliverList(
del: new SliverChildBuilderDelegate(
(BuildContext context1, int index)=> {
return new _ListItem(
name: randomizedContacts[index][0],
place: randomizedContacts[index][1],
date: randomizedContacts[index][2],
called: randomizedContacts[index][3] == "true"
);
},
childCount: 20
)
)
),
}
)
)
);
}
}
class _ListItem : StatelessWidget {
public _ListItem(
string name = null,
string place = null,
string date = null,
bool? called = null
)
{
this.name = name;
this.place = place;
this.date = date;
this.called = called;
}
public readonly string name;
public readonly string place;
public readonly string date;
public readonly bool? called;
public override Widget build(BuildContext context) {
return new Container(
color: CupertinoDynamicColor.resolve(CupertinoColors.systemBackground, context),
height: 60.0f,
padding: EdgeInsets.only(top: 9.0f),
child: new Row(
children: new List<Widget>{
new Container(
width: 38.0f,
child: (bool)called
? new Align(
alignment: Alignment.topCenter,
child: new Icon(
CupertinoIcons.phone_solid,
color: CupertinoColors.inactiveGray.resolveFrom(context),
size: 18.0f
)
)
: null
),
new Expanded(
child: new Container(
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(color: new Color(0xFFBCBBC1), width: 0.0f)
)
),
padding: EdgeInsets.only(left: 1.0f, bottom: 9.0f, right: 10.0f),
child: new Row(
children: new List<Widget>{
new Expanded(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: new List<Widget>{
new Text(
name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: new TextStyle(
fontWeight: FontWeight.w600,
letterSpacing: -0.18f
)
),
new Text(
place,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: new TextStyle(
fontSize: 15.0f,
letterSpacing: -0.24f,
color: CupertinoColors.inactiveGray.resolveFrom(context)
)
),
}
)
),
new Text(
date,
style: new TextStyle(
color: CupertinoColors.inactiveGray.resolveFrom(context),
fontSize: 15.0f,
letterSpacing: -0.41f
)
),
new Padding(
padding: EdgeInsets.only(left: 9.0f),
child: new Icon(
CupertinoIcons.info,
color: CupertinoTheme.of(context).primaryColor
)
)
}
)
)
)
}
)
);
}
}
}

151
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/cupertino/cupertino_segmented_control_demo.cs


using System;
using System.Collections.Generic;
using uiwidgets;
using Unity.UIWidgets.async2;
using Unity.UIWidgets.cupertino;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
using Random = System.Random;
using Unity.UIWidgets.material;
namespace UIWidgetsGallery.gallery
{
public class CupertinoSegmentedControlDemo : StatefulWidget {
public static string routeName = "cupertino/segmented_control";
public override State createState()
{
return new _CupertinoSegmentedControlDemoState();
}
}
public class _CupertinoSegmentedControlDemoState : State<CupertinoSegmentedControlDemo> {
Color _kKeyUmbraOpacity = new Color(0x33000000); // alpha = 0.2
Color _kKeyPenumbraOpacity = new Color(0x24000000); // alpha = 0.14
Color _kAmbientShadowOpacity = new Color(0x1F000000); // alpha = 0.12
public readonly Dictionary<int, Widget> children = new Dictionary<int, Widget>{
{0, new Text("Midnight")},
{1, new Text("Viridian")},
{2, new Text("Cerulean")},
};
public readonly Dictionary<int, Widget> icons = new Dictionary<int, Widget>{
{0, new Center(
child: new Icon(
CupertinoIcons.home,
color: Colors.indigo,
size: 200.0f
)
)},
{1, new Center(
child: new Icon(
CupertinoIcons.bell,
color: Colors.teal,
size: 200.0f
)
)},
{2, new Center(
child: new Icon(
CupertinoIcons.back,
color: Colors.cyan,
size: 200.0f
)
)},
};
int currentSegment = 0;
void onValueChanged(int newValue) {
setState(()=> {
currentSegment = newValue;
});
}
public override Widget build(BuildContext context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text("Segmented Control"),
previousPageTitle: "Cupertino"
),
child: new DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(fontSize: 13),
child: new SafeArea(
child: new Column(
children: new List<Widget>{
new Padding(padding: EdgeInsets.all(16.0f)),
new SizedBox(
width: 500.0f,
child: new CupertinoSegmentedControl<int>(
children: children,
onValueChanged: onValueChanged,
groupValue: currentSegment
)
),
new SizedBox(
width: 500,
child: new Padding(
padding: EdgeInsets.all(16.0f),
child: new CupertinoSlidingSegmentedControl<int>(
children: children,
onValueChanged: onValueChanged,
groupValue: currentSegment
)
)
),
new Expanded(
child: new Padding(
padding: EdgeInsets.symmetric(
vertical: 32.0f,
horizontal: 16.0f
),
child: new CupertinoUserInterfaceLevel(
data: CupertinoUserInterfaceLevelData.elevatedlayer,
child: new Builder(
builder: (BuildContext context1) =>{
return new Container(
padding: EdgeInsets.symmetric(
vertical: 64.0f,
horizontal: 16.0f
),
decoration: new BoxDecoration(
color: CupertinoTheme.of(context1).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(3.0f),
boxShadow: new List<BoxShadow>{
new BoxShadow(
offset: new Offset(0.0f, 3.0f),
blurRadius: 5.0f,
spreadRadius: -1.0f,
color: _kKeyUmbraOpacity
),
new BoxShadow(
offset: new Offset(0.0f, 6.0f),
blurRadius: 10.0f,
spreadRadius: 0.0f,
color: _kKeyPenumbraOpacity
),
new BoxShadow(
offset: new Offset(0.0f, 1.0f),
blurRadius: 18.0f,
spreadRadius: 0.0f,
color: _kAmbientShadowOpacity
)
}
),
child: icons[currentSegment]
);
}
)
)
)
)
}
)
)
)
);
}
}
}

343
com.unity.uiwidgets/Runtime/cupertino/refresh.cs


using System.Collections.Generic;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.async2;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler2;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
namespace Unity.UIWidgets.cupertino {
class _CupertinoSliverRefresh : SingleChildRenderObjectWidget {
public _CupertinoSliverRefresh(
Key key = null,
float refreshIndicatorLayoutExtent = 0.0f,
bool hasLayoutExtent = false,
Widget child = null
) : base(key: key, child: child) {
D.assert(refreshIndicatorLayoutExtent != null);
D.assert(refreshIndicatorLayoutExtent >= 0.0);
D.assert(hasLayoutExtent != null);
this.refreshIndicatorLayoutExtent = refreshIndicatorLayoutExtent;
this.hasLayoutExtent = hasLayoutExtent;
}
public readonly float refreshIndicatorLayoutExtent;
public readonly bool hasLayoutExtent;
public override RenderObject createRenderObject(BuildContext context) {
return new _RenderCupertinoSliverRefresh(
refreshIndicatorExtent: refreshIndicatorLayoutExtent,
hasLayoutExtent: hasLayoutExtent
);
}
public override void updateRenderObject(BuildContext context, RenderObject renderObject) {
renderObject = (_RenderCupertinoSliverRefresh)renderObject;
((_RenderCupertinoSliverRefresh) renderObject).refreshIndicatorLayoutExtent = refreshIndicatorLayoutExtent;
((_RenderCupertinoSliverRefresh) renderObject).hasLayoutExtent = hasLayoutExtent;
}
}
class _RenderCupertinoSliverRefresh : RenderObjectWithChildMixinRenderSliver<RenderBox> {
public _RenderCupertinoSliverRefresh(
float refreshIndicatorExtent,
bool hasLayoutExtent = false,
RenderBox child = null) {
D.assert(refreshIndicatorExtent >= 0.0f);
_refreshIndicatorExtent = refreshIndicatorExtent;
_hasLayoutExtent = hasLayoutExtent;
this.child = child;
}
public float refreshIndicatorLayoutExtent {
get { return _refreshIndicatorExtent; }
set {
D.assert(value != null);
D.assert(value >= 0.0);
if (value == _refreshIndicatorExtent)
return;
_refreshIndicatorExtent = value;
markNeedsLayout();
}
}
float _refreshIndicatorExtent;
public bool hasLayoutExtent {
get { return _hasLayoutExtent; }
set {
D.assert(value != null);
if (value == _hasLayoutExtent)
return;
_hasLayoutExtent = value;
markNeedsLayout();
}
}
bool _hasLayoutExtent;
float layoutExtentOffsetCompensation = 0.0f;
protected override void performLayout() {
SliverConstraints constraints = this.constraints;
D.assert(constraints.axisDirection == AxisDirection.down);
D.assert(constraints.growthDirection == GrowthDirection.forward);
float layoutExtent =
(_hasLayoutExtent ? 1.0f : 0.0f) * _refreshIndicatorExtent;
if (layoutExtent != layoutExtentOffsetCompensation) {
geometry = new SliverGeometry(
scrollOffsetCorrection: layoutExtent - layoutExtentOffsetCompensation
);
layoutExtentOffsetCompensation = layoutExtent;
}
bool active = constraints.overlap < 0.0 || layoutExtent > 0.0;
float overscrolledExtent =
constraints.overlap < 0.0f ? constraints.overlap.abs() : 0.0f;
child.layout(
constraints.asBoxConstraints(
maxExtent: layoutExtent + overscrolledExtent
),
parentUsesSize: true
);
if (active) {
geometry = new SliverGeometry(
scrollExtent: layoutExtent,
paintOrigin: -overscrolledExtent - constraints.scrollOffset,
paintExtent: Mathf.Max(
Mathf.Max(child.size.height, layoutExtent) - constraints.scrollOffset, 0.0f),
maxPaintExtent: Mathf.Max(
Mathf.Max(child.size.height, layoutExtent) - constraints.scrollOffset, 0.0f),
layoutExtent: Mathf.Max(layoutExtent - constraints.scrollOffset, 0.0f));
} else {
geometry = SliverGeometry.zero;
}
}
public override void paint(PaintingContext paintContext, Offset offset) {
if (constraints.overlap < 0.0 || constraints.scrollOffset + child.size.height > 0) {
paintContext.paintChild(child, offset);
}
}
public override void applyPaintTransform(RenderObject child, Matrix4 transform) { }
}
public enum RefreshIndicatorMode {
/// Initial state, when not being overscrolled into, or after the overscroll
/// is canceled or after done and the sliver retracted away.
inactive,
/// While being overscrolled but not far enough yet to trigger the refresh.
drag,
/// Dragged far enough that the onRefresh callback will run and the dragged
/// displacement is not yet at the final refresh resting state.
armed,
/// While the onRefresh task is running.
refresh,
/// While the indicator is animating away after refreshing.
done,
}
public delegate Widget RefreshControlIndicatorBuilder(
BuildContext context,
RefreshIndicatorMode refreshState,
float pulledExtent,
float refreshTriggerPullDistance,
float refreshIndicatorExtent
);
public delegate Future RefreshCallback();
public class CupertinoSliverRefreshControl : StatefulWidget {
public CupertinoSliverRefreshControl(
Key key = null,
float refreshTriggerPullDistance = _defaultRefreshTriggerPullDistance,
float refreshIndicatorExtent = _defaultRefreshIndicatorExtent,
RefreshControlIndicatorBuilder builder = null,
RefreshCallback onRefresh = null
) : base(key: key) {
D.assert(refreshTriggerPullDistance != null);
D.assert(refreshTriggerPullDistance > 0.0);
D.assert(refreshIndicatorExtent != null);
D.assert(refreshIndicatorExtent >= 0.0);
D.assert(
refreshTriggerPullDistance >= refreshIndicatorExtent, () =>
"The refresh indicator cannot take more space in its final state " +
"than the amount initially created by overscrolling."
);
this.refreshIndicatorExtent = refreshIndicatorExtent;
this.refreshTriggerPullDistance = refreshTriggerPullDistance;
this.builder = builder ?? buildSimpleRefreshIndicator;
this.onRefresh = onRefresh;
}
public readonly float refreshTriggerPullDistance;
public readonly float refreshIndicatorExtent;
public readonly RefreshControlIndicatorBuilder builder;
public readonly RefreshCallback onRefresh;
const float _defaultRefreshTriggerPullDistance = 100.0f;
const float _defaultRefreshIndicatorExtent = 60.0f;
static RefreshIndicatorMode state(BuildContext context) {
_CupertinoSliverRefreshControlState state = context.findAncestorStateOfType<_CupertinoSliverRefreshControlState>();
return state.refreshState;
}
public static Widget buildSimpleRefreshIndicator(
BuildContext context,
RefreshIndicatorMode refreshState,
float pulledExtent,
float refreshTriggerPullDistance,
float refreshIndicatorExtent
) {
Curve opacityCurve = new Interval(0.4f, 0.8f, curve: Curves.easeInOut);
return new Align(
alignment: Alignment.bottomCenter,
child: new Padding(
padding: EdgeInsets.only(bottom: 16.0f),
child: refreshState == RefreshIndicatorMode.drag
? new Opacity(
opacity: opacityCurve.transform(Mathf.Min(pulledExtent / refreshTriggerPullDistance, 1.0f)
),
child: new Icon(
CupertinoIcons.down_arrow,
color: CupertinoDynamicColor.resolve(CupertinoColors.inactiveGray, context),
size: 36.0f
)
)
: new Opacity(
opacity: opacityCurve.transform(
Mathf.Min(pulledExtent / refreshIndicatorExtent, 1.0f)
),
child: new CupertinoActivityIndicator(radius: 14.0f)
)
)
);
}
public override State createState() {
return new _CupertinoSliverRefreshControlState();
}
}
public class _CupertinoSliverRefreshControlState : State<CupertinoSliverRefreshControl> {
public const float _inactiveResetOverscrollFraction = 0.1f;
public RefreshIndicatorMode refreshState;
Future refreshTask;
float latestIndicatorBoxExtent = 0.0f;
bool hasSliverLayoutExtent = false;
public override void initState() {
base.initState();
refreshState = RefreshIndicatorMode.inactive;
}
RefreshIndicatorMode transitionNextState() {
RefreshIndicatorMode nextState = RefreshIndicatorMode.refresh;
void goToDone() {
nextState = RefreshIndicatorMode.done;
if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.idle) {
setState(() => hasSliverLayoutExtent = false);
} else {
SchedulerBinding.instance.addPostFrameCallback((timestamp)=> {
setState(() => hasSliverLayoutExtent = false);
});
}
}
switch (refreshState) {
case RefreshIndicatorMode.inactive:
if (latestIndicatorBoxExtent <= 0) {
return RefreshIndicatorMode.inactive;
} else {
nextState = RefreshIndicatorMode.drag;
}
goto case RefreshIndicatorMode.drag;
case RefreshIndicatorMode.drag:
if (latestIndicatorBoxExtent == 0) {
return RefreshIndicatorMode.inactive;
} else if (latestIndicatorBoxExtent < widget.refreshTriggerPullDistance) {
return RefreshIndicatorMode.drag;
} else {
if (widget.onRefresh != null) { //HapticFeedback.mediumImpact();
SchedulerBinding.instance.addPostFrameCallback((timestamp)=> {
refreshTask = widget.onRefresh().whenComplete(() =>{
if (mounted) {
setState(() => refreshTask = null);
refreshState = transitionNextState();
}
});
setState(() => hasSliverLayoutExtent = true);
});
}
return RefreshIndicatorMode.armed;
}
break;
case RefreshIndicatorMode.armed:
if (refreshState == RefreshIndicatorMode.armed && refreshTask == null) {
goToDone();
goto case RefreshIndicatorMode.done;
}
if (latestIndicatorBoxExtent > widget.refreshIndicatorExtent) {
return RefreshIndicatorMode.armed;
} else {
nextState = RefreshIndicatorMode.refresh;
}
goto case RefreshIndicatorMode.refresh;
case RefreshIndicatorMode.refresh:
if (refreshTask != null) {
return RefreshIndicatorMode.refresh;
} else {
goToDone();
}
goto case RefreshIndicatorMode.done;
case RefreshIndicatorMode.done:
if (latestIndicatorBoxExtent >
widget.refreshTriggerPullDistance * _inactiveResetOverscrollFraction) {
return RefreshIndicatorMode.done;
} else {
nextState = RefreshIndicatorMode.inactive;
}
break;
}
return nextState;
}
public override Widget build(BuildContext context) {
return new _CupertinoSliverRefresh(
refreshIndicatorLayoutExtent: widget.refreshIndicatorExtent,
hasLayoutExtent: hasSliverLayoutExtent,
child: new LayoutBuilder(
builder: (BuildContext context1, BoxConstraints constraints) =>{
latestIndicatorBoxExtent = constraints.maxHeight;
refreshState = transitionNextState();
if (widget.builder != null && latestIndicatorBoxExtent > 0) {
return widget.builder(
context1,
refreshState,
latestIndicatorBoxExtent,
widget.refreshTriggerPullDistance,
widget.refreshIndicatorExtent
);
}
return new Container();
}
)
);
}
}
}

616
com.unity.uiwidgets/Runtime/cupertino/segmented_control.cs


using System;
using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.widgets;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
using Rect = Unity.UIWidgets.ui.Rect;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
namespace Unity.UIWidgets.cupertino {
class CupertinoSegmentedControlsUtils {
public static readonly EdgeInsetsGeometry _kHorizontalItemPadding = EdgeInsets.symmetric(horizontal: 16.0f);
public const float _kMinSegmentedControlHeight = 28.0f;
public static readonly TimeSpan _kFadeDuration = TimeSpan.FromMilliseconds(165);
}
public class CupertinoSegmentedControl<T> : StatefulWidget {
public CupertinoSegmentedControl(
Key key = null,
Dictionary<T, Widget> children = null,
ValueChanged<T> onValueChanged = null,
T groupValue = default,
Color unselectedColor = null,
Color selectedColor = null,
Color borderColor = null,
Color pressedColor = null,
EdgeInsetsGeometry Padding = null
) :base(key: key)
{
D.assert(children != null);
D.assert(children.Count >= 2);
D.assert(onValueChanged != null);
D.assert(
groupValue == null || children.Keys.Any((T child) => child.Equals(groupValue)), () =>
"The groupValue must be either null or one of the keys in the children map."
);
}
public readonly Dictionary<T, Widget> children;
public readonly T groupValue;
public readonly ValueChanged<T> onValueChanged;
public readonly Color unselectedColor;
public readonly Color selectedColor;
public readonly Color borderColor;
public readonly Color pressedColor;
public readonly EdgeInsetsGeometry padding;
public override State createState() {
return new _SegmentedControlState<T>();
}
}
class _SegmentedControlState<T> : TickerProviderStateMixin<CupertinoSegmentedControl<T>> {
T _pressedKey;
public readonly List<AnimationController> _selectionControllers = new List<AnimationController>();
public readonly List<ColorTween> _childTweens = new List<ColorTween>();
ColorTween _forwardBackgroundColorTween;
ColorTween _reverseBackgroundColorTween;
ColorTween _textColorTween;
Color _selectedColor;
Color _unselectedColor;
Color _borderColor;
Color _pressedColor;
AnimationController createAnimationController() {
var controller = new AnimationController(
duration: CupertinoSegmentedControlsUtils._kFadeDuration,
vsync: this
);
controller.addListener(()=> {
setState(() =>{
// State of background/text colors has changed
});
});
return controller;
}
bool _updateColors() {
D.assert(mounted, ()=>"This should only be called after didUpdateDependencies");
bool changed = false;
Color selectedColor = widget.selectedColor ?? CupertinoTheme.of(context).primaryColor;
if (_selectedColor != selectedColor) {
changed = true;
_selectedColor = selectedColor;
}
Color unselectedColor = widget.unselectedColor ?? CupertinoTheme.of(context).primaryContrastingColor;
if (_unselectedColor != unselectedColor) {
changed = true;
_unselectedColor = unselectedColor;
}
Color borderColor = widget.borderColor ?? CupertinoTheme.of(context).primaryColor;
if (_borderColor != borderColor) {
changed = true;
_borderColor = borderColor;
}
Color pressedColor = widget.pressedColor ?? CupertinoTheme.of(context).primaryColor.withOpacity(0.2f);
if (_pressedColor != pressedColor) {
changed = true;
_pressedColor = pressedColor;
}
_forwardBackgroundColorTween = new ColorTween(
begin: _pressedColor,
end: _selectedColor
);
_reverseBackgroundColorTween = new ColorTween(
begin: _unselectedColor,
end: _selectedColor
);
_textColorTween = new ColorTween(
begin: _selectedColor,
end: _unselectedColor
);
return changed;
}
void _updateAnimationControllers() {
D.assert(mounted, ()=>"This should only be called after didUpdateDependencies");
foreach ( AnimationController controller in _selectionControllers) {
controller.dispose();
}
_selectionControllers.Clear();
_childTweens.Clear();
foreach ( T key in widget.children.Keys) {
AnimationController animationController = createAnimationController();
if (widget.groupValue.Equals(key)) {
_childTweens.Add(_reverseBackgroundColorTween);
animationController.setValue(1.0f);
} else {
_childTweens.Add(_forwardBackgroundColorTween);
}
_selectionControllers.Add(animationController);
}
}
public override void didChangeDependencies() {
base.didChangeDependencies();
if (_updateColors()) {
_updateAnimationControllers();
}
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
oldWidget = (CupertinoSegmentedControl<T>) oldWidget;
base.didUpdateWidget(oldWidget);
if (_updateColors() || ((CupertinoSegmentedControl<T>) oldWidget).children.Count != widget.children.Count) {
_updateAnimationControllers();
}
if (!((CupertinoSegmentedControl<T>)oldWidget).groupValue.Equals(widget.groupValue)) {
int index = 0;
foreach ( T key in widget.children.Keys) {
if (widget.groupValue.Equals(key)) {
_childTweens[index] = _forwardBackgroundColorTween;
_selectionControllers[index].forward();
} else {
_childTweens[index] = _reverseBackgroundColorTween;
_selectionControllers[index].reverse();
}
index += 1;
}
}
}
public override void dispose() {
foreach( AnimationController animationController in _selectionControllers) {
animationController.dispose();
}
base.dispose();
}
void _onTapDown(T currentKey) {
if (_pressedKey == null && !currentKey.Equals(widget.groupValue)) {
setState(()=> {
_pressedKey = currentKey;
});
}
}
void _onTapCancel() {
setState(()=> {
_pressedKey = default(T);
});
}
void _onTap(T currentKey) {
if (!currentKey.Equals( _pressedKey))
return;
if (!currentKey.Equals(widget.groupValue)) {
widget.onValueChanged(currentKey);
}
_pressedKey = default;
}
Color getTextColor(int index, T currentKey) {
if (_selectionControllers[index].isAnimating)
return _textColorTween.evaluate(_selectionControllers[index]);
if (widget.groupValue.Equals(currentKey))
return _unselectedColor;
return _selectedColor;
}
Color getBackgroundColor(int index, T currentKey) {
if (_selectionControllers[index].isAnimating)
return _childTweens[index].evaluate(_selectionControllers[index]);
if (widget.groupValue.Equals(currentKey))
return _selectedColor;
if (_pressedKey.Equals(currentKey))
return _pressedColor;
return _unselectedColor;
}
public override Widget build(BuildContext context) {
List<Widget> _gestureChildren = new List<Widget>();
List<Color> _backgroundColors = new List<Color>();
int index = 0;
int selectedIndex = 0;
int pressedIndex = 0;
foreach ( T currentKey in widget.children.Keys) {
selectedIndex = (widget.groupValue.Equals(currentKey)) ? index : selectedIndex;
pressedIndex = (_pressedKey.Equals(currentKey)) ? index : pressedIndex;
TextStyle textStyle = DefaultTextStyle.of(context).style.copyWith(
color: getTextColor(index, currentKey)
);
IconThemeData iconTheme = new IconThemeData(
color: getTextColor(index, currentKey)
);
Widget child = new Center(
child: widget.children[currentKey]
);
child = new GestureDetector(
onTapDown: (TapDownDetails _event)=> {
_onTapDown(currentKey);
},
onTapCancel: _onTapCancel,
onTap: ()=> {
_onTap(currentKey);
},
child: new IconTheme(
data: iconTheme,
child: new DefaultTextStyle(
style: textStyle,
child: child /*Semantics(
button: true,
inMutuallyExclusiveGroup: true,
selected: widget.groupValue.Equals(currentKey),
child: child
)*/
)
)
);
_backgroundColors.Add(getBackgroundColor(index, currentKey));
_gestureChildren.Add(child);
index += 1;
}
Widget box = new _SegmentedControlRenderWidget<T>(
children: _gestureChildren,
selectedIndex: selectedIndex,
pressedIndex: pressedIndex,
backgroundColors: _backgroundColors,
borderColor: _borderColor
);
return new Padding(
padding: widget.padding ?? CupertinoSegmentedControlsUtils._kHorizontalItemPadding,
child: new UnconstrainedBox(
constrainedAxis: Axis.horizontal,
child: box
)
);
}
}
public class _SegmentedControlRenderWidget<T> : MultiChildRenderObjectWidget {
public _SegmentedControlRenderWidget(
Key key = null,
List<Widget> children = null,
int? selectedIndex = null,
int? pressedIndex = null,
List<Color> backgroundColors = null,
Color borderColor = null
) : base(
key: key,
children: children ?? new List<Widget>()
) {
this.selectedIndex = selectedIndex;
this.pressedIndex = pressedIndex;
this.backgroundColors = backgroundColors;
this.borderColor = borderColor;
}
public readonly int? selectedIndex;
public readonly int? pressedIndex;
public readonly List<Color> backgroundColors;
public readonly Color borderColor;
public override RenderObject createRenderObject(BuildContext context) {
return new _RenderSegmentedControl<T>(
textDirection: Directionality.of(context),
selectedIndex: selectedIndex,
pressedIndex: pressedIndex,
backgroundColors: backgroundColors,
borderColor: borderColor
);
}
public override void updateRenderObject(BuildContext context,RenderObject renderObject) {
renderObject = (_RenderSegmentedControl<T>) renderObject;
((_RenderSegmentedControl<T>) renderObject).textDirection = Directionality.of(context);
((_RenderSegmentedControl<T>) renderObject).selectedIndex = selectedIndex;
((_RenderSegmentedControl<T>) renderObject).pressedIndex = pressedIndex;
((_RenderSegmentedControl<T>) renderObject).backgroundColors = backgroundColors;
((_RenderSegmentedControl<T>) renderObject).borderColor = borderColor;
}
}
class _SegmentedControlContainerBoxParentData : ContainerBoxParentData<RenderBox> {
public RRect surroundingRect;
}
public delegate RenderBox _NextChild(RenderBox child);
class _RenderSegmentedControl<T> : RenderBoxContainerDefaultsMixinContainerRenderObjectMixinRenderBox<RenderBox,
ContainerBoxParentData<RenderBox>> {
public _RenderSegmentedControl(
int? selectedIndex = null,
int? pressedIndex = null,
TextDirection? textDirection = null,
List<Color> backgroundColors = null,
Color borderColor = null
) {
D.assert(textDirection != null);
_textDirection = textDirection;
_selectedIndex = selectedIndex;
_pressedIndex = pressedIndex;
_backgroundColors = backgroundColors;
_borderColor = borderColor;
}
public int? selectedIndex {
get {return _selectedIndex; }
set {
if (_selectedIndex == value) {
return;
}
_selectedIndex = value;
markNeedsPaint();
}
}
int? _selectedIndex;
public int? pressedIndex {
get {
return _pressedIndex;
}
set {
if (_pressedIndex == value) {
return;
}
_pressedIndex = value;
markNeedsPaint();
}
}
int? _pressedIndex;
public TextDirection? textDirection {
get {
return _textDirection;
}
set {
if (_textDirection == value) {
return;
}
_textDirection = value;
markNeedsLayout();
}
}
TextDirection? _textDirection;
public List<Color> backgroundColors {
get {
return _backgroundColors;
}
set {
if (_backgroundColors == value) {
return;
}
_backgroundColors = value;
markNeedsPaint();
}
}
List<Color> _backgroundColors;
public Color borderColor {
get {
return _borderColor;
}
set {
if (_borderColor == value) {
return;
}
_borderColor = value;
markNeedsPaint();
}
}
Color _borderColor;
protected internal override float computeMinIntrinsicWidth(float height) {
RenderBox child = firstChild;
float minWidth = 0.0f;
while (child != null) {
_SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
float childWidth = child.getMinIntrinsicWidth(height);
minWidth = Mathf.Max(minWidth, childWidth);
child = childParentData.nextSibling;
}
return minWidth * childCount;
}
protected internal override float computeMaxIntrinsicWidth(float height) {
RenderBox child = firstChild;
float maxWidth = 0.0f;
while (child != null) {
_SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
float childWidth = child.getMaxIntrinsicWidth(height);
maxWidth = Mathf.Max(maxWidth, childWidth);
child = childParentData.nextSibling;
}
return maxWidth * childCount;
}
protected internal override float computeMinIntrinsicHeight(float width) {
RenderBox child = firstChild;
float minHeight = 0.0f;
while (child != null) {
_SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
float childHeight = child.getMinIntrinsicHeight(width);
minHeight = Mathf.Max(minHeight, childHeight);
child = childParentData.nextSibling;
}
return minHeight;
}
protected internal override float computeMaxIntrinsicHeight(float width) {
RenderBox child = firstChild;
float maxHeight = 0.0f;
while (child != null) {
_SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
float childHeight = child.getMaxIntrinsicHeight(width);
maxHeight = Mathf.Max(maxHeight, childHeight);
child = childParentData.nextSibling;
}
return maxHeight;
}
public override float? computeDistanceToActualBaseline(TextBaseline baseline) {
return defaultComputeDistanceToHighestActualBaseline(baseline);
}
public override void setupParentData(RenderObject child) {
child = (RenderBox) child;
if (!(child.parentData is _SegmentedControlContainerBoxParentData)) {
child.parentData = new _SegmentedControlContainerBoxParentData();
}
}
void _layoutRects(_NextChild nextChild, RenderBox leftChild, RenderBox rightChild) {
RenderBox child = leftChild;
float start = 0.0f;
while (child != null) {
_SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
Offset childOffset = new Offset(start, 0.0f);
childParentData.offset = childOffset;
Rect childRect = Rect.fromLTWH(start, 0.0f, child.size.width, child.size.height);
RRect rChildRect = null;
if (child == leftChild) {
rChildRect = RRect.fromRectAndCorners(childRect, topLeft: Radius.circular(3.0f),
bottomLeft: Radius.circular(3.0f));
} else if (child == rightChild) {
rChildRect = RRect.fromRectAndCorners(childRect, topRight: Radius.circular(3.0f),
bottomRight: Radius.circular(3.0f));
} else {
rChildRect = RRect.fromRectAndCorners(childRect,topRight:Radius.zero);
}
childParentData.surroundingRect = rChildRect;
start += child.size.width;
child = nextChild(child);
}
}
protected override void performLayout() {
BoxConstraints constraints = this.constraints;
float maxHeight = CupertinoSegmentedControlsUtils._kMinSegmentedControlHeight;
float childWidth = constraints.minWidth / childCount;
foreach ( RenderBox child in getChildrenAsList()) {
childWidth = Mathf.Max(childWidth, child.getMaxIntrinsicWidth(float.PositiveInfinity));
}
childWidth = Mathf.Min(childWidth, constraints.maxWidth / childCount);
RenderBox child1 = firstChild;
while (child1 != null) {
float boxHeight = child1.getMaxIntrinsicHeight(childWidth);
maxHeight = Mathf.Max(maxHeight, boxHeight);
child1 = childAfter(child1);
}
constraints.constrainHeight(maxHeight);
BoxConstraints childConstraints = BoxConstraints.tightFor(
width: childWidth,
height: maxHeight
);
child1 = firstChild;
while (child1 != null) {
child1.layout(childConstraints, parentUsesSize: true);
child1 = childAfter(child1);
}
switch (textDirection) {
case TextDirection.rtl:
_layoutRects(
childBefore,
lastChild,
firstChild
);
break;
case TextDirection.ltr:
_layoutRects(
childAfter,
firstChild,
lastChild
);
break;
}
size = constraints.constrain(new Size(childWidth * childCount, maxHeight));
}
public override void paint(PaintingContext context, Offset offset) {
RenderBox child = firstChild;
int index = 0;
while (child != null) {
_paintChild(context, offset, child, index);
child = childAfter(child);
index += 1;
}
}
void _paintChild(PaintingContext context, Offset offset, RenderBox child, int childIndex) {
D.assert(child != null);
_SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
context.canvas.drawRRect(
childParentData.surroundingRect.shift(offset),
new Paint(){
color = backgroundColors[childIndex],
style = PaintingStyle.fill}
);
context.canvas.drawRRect(
childParentData.surroundingRect.shift(offset),
new Paint(){
color = borderColor,
strokeWidth = 1.0f,
style = PaintingStyle.stroke}
);
context.paintChild(child, childParentData.offset + offset);
}
protected override bool hitTestChildren(BoxHitTestResult result, Offset position = null ) {
D.assert(position != null);
RenderBox child = lastChild;
while (child != null) {
_SegmentedControlContainerBoxParentData childParentData = child.parentData as _SegmentedControlContainerBoxParentData;
if (childParentData.surroundingRect.contains(position)) {
Offset center = (Offset.zero & child.size).center;
return result.addWithRawTransform(
transform: MatrixUtils.forceToPoint(center),
position: center,
hitTest: (BoxHitTestResult result1, Offset position1) =>{
D.assert(position1 == center);
return child.hitTest(result1, position: center);
}
);
}
child = childParentData.previousSibling;
}
return false;
}
}
}

867
com.unity.uiwidgets/Runtime/cupertino/sliding_segmented_control.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.cupertino;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.widgets;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.physics;
using Unity.UIWidgets.rendering;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
using Rect = Unity.UIWidgets.ui.Rect;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
namespace Unity.UIWidgets.cupertino {
public class CupertinoSlidingSegmentedControlsUtils {
public static readonly EdgeInsetsGeometry _kHorizontalItemPadding = EdgeInsets.symmetric(vertical: 2, horizontal: 3);
public static readonly Radius _kThumbRadius = Radius.circular(6.93f);
public static readonly EdgeInsets _kThumbInsets = EdgeInsets.symmetric(horizontal: 1);
public const float _kMinSegmentedControlHeight = 28.0f;
public static readonly Color _kSeparatorColor = new Color(0x4D8E8E93);
public static readonly CupertinoDynamicColor _kThumbColor = CupertinoDynamicColor.withBrightness(
color: new Color(0xFFFFFFFF),
darkColor: new Color(0xFF636366)
);
public static readonly EdgeInsets _kSeparatorInset = EdgeInsets.symmetric(vertical: 6);
public const float _kSeparatorWidth = 1;
public static readonly Radius _kSeparatorRadius = Radius.circular(_kSeparatorWidth/2);
public const float _kMinThumbScale = 0.95f;
public const float _kSegmentMinPadding = 9.25f;
public const float _kTouchYDistanceThreshold = 50.0f * 50.0f;
public const float _kCornerRadius = 8;
public static readonly SpringSimulation _kThumbSpringAnimationSimulation = new SpringSimulation(
new SpringDescription(mass: 1, stiffness: 503.551f, damping: 44.8799f),
0,
1,
0 // Everytime a new spring animation starts the previous animation stops.
);
public static readonly TimeSpan _kSpringAnimationDuration= TimeSpan.FromMilliseconds(412);
public static readonly TimeSpan _kOpacityAnimationDuration = TimeSpan.FromMilliseconds(470);
public static readonly TimeSpan _kHighlightAnimationDuration = TimeSpan.FromMilliseconds(200);
}
class _FontWeightTween : Tween<FontWeight> {
public _FontWeightTween(FontWeight begin = null, FontWeight end = null) : base(begin: begin, end: end) {
}
public override FontWeight lerp(float t) => FontWeight.lerp(begin, end, t);
}
public class CupertinoSlidingSegmentedControl<T> : StatefulWidget {
public CupertinoSlidingSegmentedControl(
Key key = null,
Dictionary<T, Widget> children = null,
ValueChanged<T> onValueChanged = null,
T groupValue = default,
Color thumbColor = null,
EdgeInsetsGeometry padding = null,
Color backgroundColor = null
) :base(key: key)
{
D.assert(children != null);
D.assert(children.Count >= 2);
D.assert(padding != null);
D.assert(onValueChanged != null);
D.assert(
groupValue == null || children.Keys.Contains(groupValue),()=>
"The groupValue must be either null or one of the keys in the children map."
);
this.children = children;
this.onValueChanged = onValueChanged;
this.groupValue = groupValue;
this.thumbColor = thumbColor ?? CupertinoSlidingSegmentedControlsUtils._kThumbColor;
this.padding = padding ??CupertinoSlidingSegmentedControlsUtils._kHorizontalItemPadding;
this.backgroundColor = backgroundColor ?? CupertinoColors.tertiarySystemFill;
}
public readonly Dictionary<T, Widget> children;
public readonly T groupValue;
public readonly ValueChanged<T> onValueChanged;
public readonly Color backgroundColor;
public readonly Color thumbColor;
public readonly EdgeInsetsGeometry padding;
public override State createState() {
return new _SlidingSegmentedControlState<T>();
}
}
public class _SlidingSegmentedControlState<T> : TickerProviderStateMixin<CupertinoSlidingSegmentedControl<T>> {
public readonly Dictionary<T, AnimationController> _highlightControllers = new Dictionary<T, AnimationController>();
public readonly Tween<FontWeight> _highlightTween = new _FontWeightTween(begin: FontWeight.normal, end: FontWeight.w500);
public readonly Dictionary<T, AnimationController> _pressControllers = new Dictionary<T, AnimationController>();
public readonly Tween<float> _pressTween = new Tween<float>(begin: 1, end: 0.2f);
List<T> keys;
public AnimationController thumbController;
public AnimationController separatorOpacityController;
public AnimationController thumbScaleController;
public readonly TapGestureRecognizer tap = new TapGestureRecognizer();
public readonly HorizontalDragGestureRecognizer drag = new HorizontalDragGestureRecognizer();
public readonly LongPressGestureRecognizer longPress = new LongPressGestureRecognizer();
AnimationController _createHighlightAnimationController( bool isCompleted = false ) {
return new AnimationController(
duration: CupertinoSlidingSegmentedControlsUtils._kHighlightAnimationDuration,
value: isCompleted ? 1 : 0,
vsync: this
);
}
AnimationController _createFadeoutAnimationController() {
return new AnimationController(
duration:CupertinoSlidingSegmentedControlsUtils._kOpacityAnimationDuration,
vsync: this
);
}
public override void initState() {
base.initState();
GestureArenaTeam team = new GestureArenaTeam();
longPress.team = team;
drag.team = team;
team.captain = drag;
_highlighted = widget.groupValue;
thumbController = new AnimationController(
duration: CupertinoSlidingSegmentedControlsUtils._kSpringAnimationDuration,
value: 0,
vsync: this
);
thumbScaleController = new AnimationController(
duration: CupertinoSlidingSegmentedControlsUtils._kSpringAnimationDuration,
value: 1,
vsync: this
);
separatorOpacityController = new AnimationController(
duration: CupertinoSlidingSegmentedControlsUtils._kSpringAnimationDuration,
value: 0,
vsync: this
);
foreach (T currentKey in widget.children.Keys) {
_highlightControllers[currentKey] = _createHighlightAnimationController(
isCompleted: currentKey.Equals(widget.groupValue) // Highlight the current selection.
);
_pressControllers[currentKey] = _createFadeoutAnimationController();
}
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
oldWidget = (CupertinoSlidingSegmentedControl<T>)oldWidget;
base.didUpdateWidget(oldWidget);
// Update animation controllers.
foreach( T oldKey in ((CupertinoSlidingSegmentedControl<T>)oldWidget).children.Keys) {
if (!widget.children.ContainsKey(oldKey)) {
_highlightControllers[oldKey].dispose();
_pressControllers[oldKey].dispose();
_highlightControllers.Remove(oldKey);
_pressControllers.Remove(oldKey);
}
}
foreach( T newKey in widget.children.Keys) {
if (!_highlightControllers.Keys.Contains(newKey)) {
_highlightControllers[newKey] = _createHighlightAnimationController();
_pressControllers[newKey] = _createFadeoutAnimationController();
}
}
highlighted = widget.groupValue;
}
public override void dispose() {
foreach( AnimationController animationController in _highlightControllers.Values) {
animationController.dispose();
}
foreach( AnimationController animationController in _pressControllers.Values) {
animationController.dispose();
}
thumbScaleController.dispose();
thumbController.dispose();
separatorOpacityController.dispose();
drag.dispose();
tap.dispose();
longPress.dispose();
base.dispose();
}
void _animateHighlightController( T at = default, bool forward = false) {
if (at == null)
return;
AnimationController controller = _highlightControllers[at];
D.assert(!forward || controller != null);
controller?.animateTo(forward ? 1 : 0, duration: CupertinoSlidingSegmentedControlsUtils._kHighlightAnimationDuration, curve: Curves.ease);
}
T _highlighted;
public T highlighted{
set {
if (_highlighted.Equals(value))
return;
_animateHighlightController(at: value, forward: true);
_animateHighlightController(at: _highlighted, forward: false);
_highlighted = value;
}
}
T _pressed;
public T pressed{
set {
if (_pressed.Equals(value))
return;
if (_pressed != null) {
_pressControllers[_pressed]?.animateTo(0, duration: CupertinoSlidingSegmentedControlsUtils._kOpacityAnimationDuration, curve: Curves.ease);
}
if (!value.Equals(_highlighted)&& value != null) {
_pressControllers[value].animateTo(1, duration: CupertinoSlidingSegmentedControlsUtils._kOpacityAnimationDuration, curve: Curves.ease);
}
_pressed = value;
}
}
public void didChangeSelectedViaGesture() {
widget.onValueChanged(_highlighted);
}
public T indexToKey(int index) {
return index == null ? default : keys[index];
}
public override Widget build(BuildContext context) {
WidgetsD.debugCheckHasDirectionality(context);
switch (Directionality.of(context)) {
case TextDirection.ltr:
keys = widget.children.Keys.ToList();
break;
case TextDirection.rtl:
widget.children.Keys.ToList().Reverse();
keys = widget.children.Keys.ToList();
break;
}
List<Listenable> results = new List<Listenable>();
results.AddRange(_highlightControllers.Values);
results.AddRange(_pressControllers.Values);
return new AnimatedBuilder(
animation: ListenableUtils.merge(results),
builder: (BuildContext context1, Widget child1) =>{
List<Widget> children = new List<Widget>();
foreach( T currentKey in keys){
TextStyle textStyle = DefaultTextStyle.of(context1).style.copyWith(
fontWeight: _highlightTween.evaluate(_highlightControllers[currentKey])
);
Widget child = new DefaultTextStyle(
style: textStyle,
child:
new Opacity(
opacity: _pressTween.evaluate(_pressControllers[currentKey]),
child: new MetaData(
behavior: HitTestBehavior.opaque,
child: new Center(child: widget.children[currentKey])
)
)
);
children.Add(child);
}
int selectedIndex = widget.groupValue.Equals(default) ? 0 : keys.IndexOf(widget.groupValue);
Widget box = new _SlidingSegmentedControlRenderWidget<T>(
children: children,
selectedIndex: selectedIndex,
thumbColor: CupertinoDynamicColor.resolve(widget.thumbColor, context),
state: this
);
return new UnconstrainedBox(
constrainedAxis: Axis.horizontal,
child: new Container(
padding: widget.padding.resolve(Directionality.of(context)),
decoration: new BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(CupertinoSlidingSegmentedControlsUtils._kCornerRadius)),
color: CupertinoDynamicColor.resolve(widget.backgroundColor, context)
),
child: box
)
);
}
);
}
}
public class _SlidingSegmentedControlRenderWidget<T> : MultiChildRenderObjectWidget {
public _SlidingSegmentedControlRenderWidget(
Key key = null,
List<Widget> children = null,
int? selectedIndex = null,
Color thumbColor = null,
_SlidingSegmentedControlState<T> state = null
) : base(key: key, children: children ?? new List<Widget>()) {
this.selectedIndex = selectedIndex;
this.thumbColor = thumbColor;
this.state = state;
}
public readonly int? selectedIndex;
public readonly Color thumbColor;
public readonly _SlidingSegmentedControlState<T> state;
public override RenderObject createRenderObject(BuildContext context) {
return new _RenderSlidingSegmentedControl<T>(
selectedIndex: selectedIndex,
thumbColor: CupertinoDynamicColor.resolve(thumbColor, context),
state: state
);
}
public override void updateRenderObject(BuildContext context,RenderObject renderObject) {
renderObject = (_RenderSlidingSegmentedControl<T>) renderObject;
((_RenderSlidingSegmentedControl<T>)renderObject).thumbColor = CupertinoDynamicColor.resolve(thumbColor, context);
((_RenderSlidingSegmentedControl<T>)renderObject).guardedSetHighlightedIndex(selectedIndex ?? 0);
}
}
public class _ChildAnimationManifest {
public _ChildAnimationManifest(
float opacity = 1f,
float separatorOpacity = 0f) {
D.assert(separatorOpacity != null);
D.assert(opacity != null);
separatorTween = new Tween<float>(begin: separatorOpacity, end: separatorOpacity);
opacityTween = new Tween<float>(begin: opacity, end: opacity);
}
float opacity;
Tween<float> opacityTween;
public float separatorOpacity;
public Tween<float> separatorTween;
}
class _SlidingSegmentedControlContainerBoxParentData : ContainerBoxParentData<RenderBox> { }
public class _RenderSlidingSegmentedControl<T> : RenderBoxContainerDefaultsMixinContainerRenderObjectMixinRenderBox<RenderBox, ContainerBoxParentData<RenderBox>> {
public _RenderSlidingSegmentedControl(
int? selectedIndex = null,
Color thumbColor = null,
_SlidingSegmentedControlState<T> state = null
) {
highlightedIndex = selectedIndex;
_thumbColor = thumbColor;
D.assert(state != null);
state.drag.onDown = _onDown;
state.drag.onUpdate = _onUpdate;
state.drag.onEnd = _onEnd;
state.drag.onCancel = _onCancel;
state.tap.onTapUp = _onTapUp;
state.longPress.onLongPress = ()=> { };
}
public readonly _SlidingSegmentedControlState<T> state;
Dictionary<RenderBox, _ChildAnimationManifest> _childAnimations = new Dictionary<RenderBox, _ChildAnimationManifest>{};
Rect currentThumbRect;
Tween<Rect> _currentThumbTween;
Tween<float> _thumbScaleTween = new Tween<float>(begin: CupertinoSlidingSegmentedControlsUtils._kMinThumbScale, end: 1);
float currentThumbScale = 1;
Offset _localDragOffset;
bool _startedOnSelectedSegment;
public override void insert(RenderBox child, RenderBox after = null) {
base.insert(child, after: after);
if (_childAnimations == null)
return;
D.assert(_childAnimations[child] == null);
_childAnimations[child] = new _ChildAnimationManifest(separatorOpacity: 1);
}
public override void remove(RenderBox child) {
base.remove(child);
_childAnimations?.Remove(child);
}
public override void attach(object owner) {
owner = (PipelineOwner) owner;
base.attach(owner);
state.thumbController.addListener(markNeedsPaint);
state.thumbScaleController.addListener(markNeedsPaint);
state.separatorOpacityController.addListener(markNeedsPaint);
}
public override void detach() {
state.thumbController.removeListener(markNeedsPaint);
state.thumbScaleController.removeListener(markNeedsPaint);
state.separatorOpacityController.removeListener(markNeedsPaint);
base.detach();
}
bool _needsThumbAnimationUpdate = false;
int? highlightedIndex {
get {
return _highlightedIndex;
}
set {
if (_highlightedIndex == value) {
return;
}
_needsThumbAnimationUpdate = true;
_highlightedIndex = value;
state.thumbController.animateWith(CupertinoSlidingSegmentedControlsUtils._kThumbSpringAnimationSimulation);
state.separatorOpacityController.reset();
state.separatorOpacityController.animateTo(
1,
duration: CupertinoSlidingSegmentedControlsUtils._kSpringAnimationDuration,
curve: Curves.ease
);
state.highlighted = state.indexToKey(value??0);
markNeedsPaint();
//markNeedsSemanticsUpdate();
}
}
int? _highlightedIndex;
public void guardedSetHighlightedIndex(int value) {
// Ignore set highlightedIndex when the user is dragging the thumb around.
if (_startedOnSelectedSegment == true)
return;
highlightedIndex = value;
}
int? pressedIndex {
get {
return _pressedIndex;
}
set {
if (_pressedIndex == value) {
return;
}
D.assert(value == null || (value >= 0 && value < childCount));
_pressedIndex = value;
state.pressed = state.indexToKey(value ?? 0);
}
}
int? _pressedIndex;
public Color thumbColor {
get {
return _thumbColor;
}
set {
if (_thumbColor == value) {
return;
}
_thumbColor = value;
markNeedsPaint();
}
}
Color _thumbColor;
float totalSeparatorWidth {
get {
return (CupertinoSlidingSegmentedControlsUtils._kSeparatorInset.horizontal + CupertinoSlidingSegmentedControlsUtils._kSeparatorWidth) * (childCount - 1);
}
}
public override void handleEvent(PointerEvent _event, HitTestEntry entry) {
entry = (BoxHitTestEntry) entry;
D.assert(debugHandleEvent(_event, entry));
if (_event is PointerDownEvent) {
state.tap.addPointer((PointerDownEvent)_event);
state.longPress.addPointer((PointerDownEvent)_event);
state.drag.addPointer((PointerDownEvent)_event);
}
}
int? indexFromLocation(Offset location) {
return childCount == 0
? (int?) null
// This assumes all children have the same width.
: (int)((location.dx / (size.width / childCount))
.floor()
.clamp(0, childCount - 1) );
}
void _onTapUp(TapUpDetails details) {
highlightedIndex = indexFromLocation(details.localPosition);
state.didChangeSelectedViaGesture();
}
void _onDown(DragDownDetails details) {
D.assert(size.contains(details.localPosition));
_localDragOffset = details.localPosition;
int? index = indexFromLocation(_localDragOffset);
_startedOnSelectedSegment = index == highlightedIndex;
pressedIndex = index;
if (_startedOnSelectedSegment) {
_playThumbScaleAnimation(isExpanding: false);
}
}
void _onUpdate(DragUpdateDetails details) {
_localDragOffset = details.localPosition;
int? newIndex = indexFromLocation(_localDragOffset);
if (_startedOnSelectedSegment) {
highlightedIndex = newIndex;
pressedIndex = newIndex;
} else {
pressedIndex = _hasDraggedTooFar(details) ? 0 : newIndex;
}
}
void _onEnd(DragEndDetails details) {
if (_startedOnSelectedSegment) {
_playThumbScaleAnimation(isExpanding: true);
state.didChangeSelectedViaGesture();
}
if (pressedIndex != null) {
highlightedIndex = pressedIndex;
state.didChangeSelectedViaGesture();
}
pressedIndex = null;
_localDragOffset = null;
_startedOnSelectedSegment = false;
}
void _onCancel() {
if (_startedOnSelectedSegment) {
_playThumbScaleAnimation(isExpanding: true);
}
_localDragOffset = null;
pressedIndex = null;
_startedOnSelectedSegment = false;
}
void _playThumbScaleAnimation(bool isExpanding = false) {
D.assert(isExpanding != null);
_thumbScaleTween = new Tween<float>(begin: currentThumbScale, end: isExpanding ? 1 : CupertinoSlidingSegmentedControlsUtils._kMinThumbScale);
state.thumbScaleController.animateWith(CupertinoSlidingSegmentedControlsUtils._kThumbSpringAnimationSimulation);
}
bool _hasDraggedTooFar(DragUpdateDetails details) {
Offset offCenter = details.localPosition - new Offset(size.width/2, size.height/2);
return Mathf.Pow(Mathf.Max(0, offCenter.dx.abs() - size.width/2), 2) + Mathf.Pow(Mathf.Max(0, offCenter.dy.abs() - size.height/2), 2) > CupertinoSlidingSegmentedControlsUtils._kTouchYDistanceThreshold;
}
protected internal override float computeMinIntrinsicWidth(float height) {
RenderBox child = firstChild;
float maxMinChildWidth = 0;
while (child != null) {
_SlidingSegmentedControlContainerBoxParentData childParentData =
child.parentData as _SlidingSegmentedControlContainerBoxParentData;
float childWidth = child.getMinIntrinsicWidth(height);
maxMinChildWidth = Math.Max(maxMinChildWidth, childWidth);
child = childParentData.nextSibling;
}
return (maxMinChildWidth + 2 * CupertinoSlidingSegmentedControlsUtils._kSegmentMinPadding) * childCount + totalSeparatorWidth;
}
protected internal override float computeMaxIntrinsicWidth(float height) {
RenderBox child = firstChild;
float maxMaxChildWidth = 0;
while (child != null) {
_SlidingSegmentedControlContainerBoxParentData childParentData =
child.parentData as _SlidingSegmentedControlContainerBoxParentData;
float childWidth = child.getMaxIntrinsicWidth(height);
maxMaxChildWidth = Mathf.Max(maxMaxChildWidth, childWidth);
child = childParentData.nextSibling;
}
return (maxMaxChildWidth + 2 * CupertinoSlidingSegmentedControlsUtils._kSegmentMinPadding) * childCount + totalSeparatorWidth;
}
protected internal override float computeMinIntrinsicHeight(float width) {
RenderBox child = firstChild;
float maxMinChildHeight = 0;
while (child != null) {
_SlidingSegmentedControlContainerBoxParentData childParentData =
child.parentData as _SlidingSegmentedControlContainerBoxParentData;
float childHeight = child.getMinIntrinsicHeight(width);
maxMinChildHeight = Mathf.Max(maxMinChildHeight, childHeight);
child = childParentData.nextSibling;
}
return maxMinChildHeight;
}
protected internal override float computeMaxIntrinsicHeight(float width) {
RenderBox child = firstChild;
float maxMaxChildHeight = 0;
while (child != null) {
_SlidingSegmentedControlContainerBoxParentData childParentData =
child.parentData as _SlidingSegmentedControlContainerBoxParentData;
float childHeight = child.getMaxIntrinsicHeight(width);
maxMaxChildHeight = Mathf.Max(maxMaxChildHeight, childHeight);
child = childParentData.nextSibling;
}
return maxMaxChildHeight;
}
public override float? computeDistanceToActualBaseline(TextBaseline baseline) {
return defaultComputeDistanceToHighestActualBaseline(baseline);
}
public override void setupParentData(RenderObject child) {
child = (RenderBox) child;
if (!(child.parentData is _SlidingSegmentedControlContainerBoxParentData)) {
child.parentData = new _SlidingSegmentedControlContainerBoxParentData();
}
}
protected override void performLayout() {
BoxConstraints constraints = this.constraints;
float childWidth = (constraints.minWidth - totalSeparatorWidth) / childCount;
float maxHeight = CupertinoSlidingSegmentedControlsUtils._kMinSegmentedControlHeight;
foreach( RenderBox child1 in getChildrenAsList()) {
childWidth = Mathf.Max(childWidth, child1.getMaxIntrinsicWidth(float.PositiveInfinity) + 2 * CupertinoSlidingSegmentedControlsUtils._kSegmentMinPadding);
}
childWidth = Mathf.Min(
childWidth,
(constraints.maxWidth - totalSeparatorWidth) / childCount
);
RenderBox child = firstChild;
while (child != null) {
float boxHeight = child.getMaxIntrinsicHeight(childWidth);
maxHeight = Mathf.Max(maxHeight, boxHeight);
child = childAfter(child);
}
constraints.constrainHeight(maxHeight);
BoxConstraints childConstraints = BoxConstraints.tightFor(
width: childWidth,
height: maxHeight
);
// Layout children.
child = firstChild;
while (child != null) {
child.layout(childConstraints, parentUsesSize: true);
child = childAfter(child);
}
float start = 0;
child = firstChild;
while (child != null) {
_SlidingSegmentedControlContainerBoxParentData childParentData =
child.parentData as _SlidingSegmentedControlContainerBoxParentData;
Offset childOffset = new Offset(start, 0);
childParentData.offset = childOffset;
start += child.size.width + CupertinoSlidingSegmentedControlsUtils._kSeparatorWidth + CupertinoSlidingSegmentedControlsUtils._kSeparatorInset.horizontal;
child = childAfter(child);
}
size = constraints.constrain(new Size(childWidth * childCount + totalSeparatorWidth, maxHeight));
}
public override void paint(PaintingContext context, Offset offset) {
List<RenderBox> children = getChildrenAsList();
// Paint thumb if highlightedIndex is not null.
if (highlightedIndex != null) {
if (_childAnimations == null) {
_childAnimations = new Dictionary<RenderBox, _ChildAnimationManifest>();//<RenderBox, _ChildAnimationManifest> { };
for (int i = 0; i < childCount - 1; i += 1) {
bool shouldFadeOut = i == highlightedIndex || i == highlightedIndex - 1;
RenderBox child = children[i];
_childAnimations[child] = new _ChildAnimationManifest(separatorOpacity: shouldFadeOut ? 0 : 1);
}
}
RenderBox selectedChild = children[highlightedIndex ?? 0];
_SlidingSegmentedControlContainerBoxParentData childParentData =
selectedChild.parentData as _SlidingSegmentedControlContainerBoxParentData;
Rect unscaledThumbTargetRect = CupertinoSlidingSegmentedControlsUtils._kThumbInsets.inflateRect(childParentData.offset & selectedChild.size);
// Update related Tweens before animation update phase.
if (_needsThumbAnimationUpdate) {
// Needs to ensure _currentThumbRect is valid.
_currentThumbTween = new RectTween(begin: currentThumbRect ?? unscaledThumbTargetRect, end: unscaledThumbTargetRect);
for (int i = 0; i < childCount - 1; i += 1) {
bool shouldFadeOut = i == highlightedIndex || i == highlightedIndex - 1;
RenderBox child = children[i];
_ChildAnimationManifest manifest = _childAnimations[child];
D.assert(manifest != null);
manifest.separatorTween = new Tween<float>(
begin: manifest.separatorOpacity,
end: shouldFadeOut ? 0 : 1
);
}
_needsThumbAnimationUpdate = false;
} else if (_currentThumbTween != null && unscaledThumbTargetRect != _currentThumbTween.begin) {
_currentThumbTween = new RectTween(begin: _currentThumbTween.begin, end: unscaledThumbTargetRect);
}
for (int index = 0; index < childCount - 1; index += 1) {
_paintSeparator(context, offset, children[index]);
}
currentThumbRect = _currentThumbTween?.evaluate(state.thumbController)
?? unscaledThumbTargetRect;
currentThumbScale = _thumbScaleTween.evaluate(state.thumbScaleController);
Rect thumbRect = Rect.fromCenter(
center: currentThumbRect.center,
width: currentThumbRect.width * currentThumbScale,
height: currentThumbRect.height * currentThumbScale
);
_paintThumb(context, offset, thumbRect);
} else {
// Reset all animations when there"s no thumb.
currentThumbRect = null;
_childAnimations = null;
for (int index = 0; index < childCount - 1; index += 1) {
_paintSeparator(context, offset, children[index]);
}
}
for (int index = 0; index < children.Count; index++) {
_paintChild(context, offset, children[index], index);
}
}
// Paint the separator to the right of the given child.
void _paintSeparator(PaintingContext context, Offset offset, RenderBox child) {
D.assert(child != null);
_SlidingSegmentedControlContainerBoxParentData childParentData =
child.parentData as _SlidingSegmentedControlContainerBoxParentData;
Paint paint = new Paint();
_ChildAnimationManifest manifest = _childAnimations == null ? null : _childAnimations[child];
float opacity = manifest?.separatorTween?.evaluate(state.separatorOpacityController) ?? 1;
if(manifest != null)
manifest.separatorOpacity = opacity;
paint.color = CupertinoSlidingSegmentedControlsUtils._kSeparatorColor.withOpacity(CupertinoSlidingSegmentedControlsUtils._kSeparatorColor.opacity * opacity);
Rect childRect = (childParentData.offset + offset) & child.size;
Rect separatorRect = CupertinoSlidingSegmentedControlsUtils._kSeparatorInset.deflateRect(
childRect.topRight & new Size(CupertinoSlidingSegmentedControlsUtils._kSeparatorInset.horizontal + CupertinoSlidingSegmentedControlsUtils._kSeparatorWidth,
child.size.height)
);
context.canvas.drawRRect(
RRect.fromRectAndRadius(separatorRect, CupertinoSlidingSegmentedControlsUtils._kSeparatorRadius),
paint
);
}
void _paintChild(PaintingContext context, Offset offset, RenderBox child, int childIndex) {
D.assert(child != null);
_SlidingSegmentedControlContainerBoxParentData childParentData =
child.parentData as _SlidingSegmentedControlContainerBoxParentData;
context.paintChild(child, childParentData.offset + offset);
}
void _paintThumb(PaintingContext context, Offset offset, Rect thumbRect) {
List<BoxShadow> thumbShadow = new List<BoxShadow> {
new BoxShadow(
color: new Color(0x1F000000),
offset: new Offset(0, 3),
blurRadius: 8
),
new BoxShadow(
color: new Color(0x0A000000),
offset: new Offset(0, 3),
blurRadius: 1
)
};
RRect thumbRRect = RRect.fromRectAndRadius(thumbRect.shift(offset), CupertinoSlidingSegmentedControlsUtils._kThumbRadius);
foreach( BoxShadow shadow in thumbShadow) {
context.canvas.drawRRect(thumbRRect.shift(shadow.offset), shadow.toPaint());
}
context.canvas.drawRRect(
thumbRRect.inflate(0.5f),
new Paint(){color = new Color(0x0A000000)}
);
context.canvas.drawRRect(
thumbRRect,
new Paint(){color = thumbColor}
);
}
protected override bool hitTestChildren(BoxHitTestResult result, Offset position ) {
D.assert(position != null);
RenderBox child = lastChild;
while (child != null) {
_SlidingSegmentedControlContainerBoxParentData childParentData =
child.parentData as _SlidingSegmentedControlContainerBoxParentData;
if ((childParentData.offset & child.size).contains(position)) {
Offset center = (Offset.zero & child.size).center;
return result.addWithRawTransform(
transform: MatrixUtils.forceToPoint(center),
position: center,
hitTest: (BoxHitTestResult result1, Offset position1)=> {
D.assert(position == center);
return child.hitTest(result1, position: center);
}
);
}
child = childParentData.previousSibling;
}
return false;
}
}
}
正在加载...
取消
保存