xingwei.zhu
4 年前
当前提交
757fc7f2
共有 6 个文件被更改,包括 1247 次插入 和 345 次删除
-
732Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/material/slider_demo.cs
-
36Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/gallery/demos.cs
-
111Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/material/snack_bar_demo.cs
-
240Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/material/tabs_demo.cs
-
387Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/material/text_form_field_demo.cs
-
86Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/material/tooltip_demo.cs
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UIWidgetsGallery.gallery; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.widgets; |
|||
using UnityEngine; |
|||
|
|||
namespace UIWidgetsGallery.demo.material |
|||
{ |
|||
internal static class SnackBarDemoUtils |
|||
{ |
|||
public static readonly string _text1 = |
|||
"Snackbars provide lightweight feedback about an operation by " + |
|||
"showing a brief message at the bottom of the screen. Snackbars " + |
|||
"can contain an action."; |
|||
|
|||
public static readonly string _text2 = |
|||
"Snackbars should contain a single line of text directly related " + |
|||
"to the operation performed. They cannot contain icons."; |
|||
|
|||
public static readonly string _text3 = |
|||
"By default snackbars automatically disappear after a few seconds "; |
|||
} |
|||
|
|||
internal class SnackBarDemo : StatefulWidget |
|||
{ |
|||
public SnackBarDemo(Key key = null) : base(key: key) |
|||
{ |
|||
} |
|||
|
|||
public static readonly string routeName = "/material/snack-bar"; |
|||
|
|||
|
|||
public override State createState() |
|||
{ |
|||
return new _SnackBarDemoState(); |
|||
} |
|||
} |
|||
|
|||
internal class _SnackBarDemoState : State<SnackBarDemo> |
|||
{ |
|||
private int _snackBarIndex = 1; |
|||
|
|||
private Widget buildBody(BuildContext context) |
|||
{ |
|||
return new SafeArea( |
|||
top: false, |
|||
bottom: false, |
|||
child: new ListView( |
|||
padding: EdgeInsets.all(24.0f), |
|||
children: new List<Widget> |
|||
{ |
|||
new Text(SnackBarDemoUtils._text1), |
|||
new Text(SnackBarDemoUtils._text2), |
|||
new Center( |
|||
child: new RaisedButton( |
|||
child: new Text("SHOW A SNACKBAR"), |
|||
onPressed: () => |
|||
{ |
|||
int thisSnackBarIndex = _snackBarIndex++; |
|||
Scaffold.of(context).showSnackBar(new SnackBar( |
|||
content: new Text($"This is snackbar #{thisSnackBarIndex}."), |
|||
action: new SnackBarAction( |
|||
label: "ACTION", |
|||
onPressed: () => |
|||
{ |
|||
Scaffold.of(context).showSnackBar(new SnackBar( |
|||
content: new Text( |
|||
$"You pressed snackbar {thisSnackBarIndex}'s action.") |
|||
)); |
|||
} |
|||
) |
|||
)); |
|||
} |
|||
) |
|||
), |
|||
new Text(SnackBarDemoUtils._text3) |
|||
} |
|||
.Select<Widget, Widget>((Widget child) => |
|||
{ |
|||
return new Container( |
|||
margin: EdgeInsets.symmetric(vertical: 12.0f), |
|||
child: child |
|||
); |
|||
}) |
|||
.ToList() |
|||
) |
|||
); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
return new Scaffold( |
|||
appBar: new AppBar( |
|||
title: new Text("Snackbar"), |
|||
actions: new List<Widget> {new MaterialDemoDocumentationButton(SnackBarDemo.routeName)} |
|||
), |
|||
body: new Builder( |
|||
builder: buildBody |
|||
), |
|||
floatingActionButton: new FloatingActionButton( |
|||
child: new Icon(Icons.add), |
|||
tooltip: "Create", |
|||
onPressed: () => { Debug.Log("Floating Action Button was pressed"); } |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UIWidgetsGallery.gallery; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace UIWidgetsGallery.demo.material |
|||
{ |
|||
static class TabsDemoUtils |
|||
{ |
|||
public static readonly string _kGalleryAssetsPackage = "flutter_gallery_assets"; |
|||
|
|||
public static readonly Dictionary<_TabPage, List<_CardData>> _allPages = |
|||
new Dictionary<_TabPage, List<_CardData>> |
|||
{ |
|||
{ |
|||
new _TabPage(label: "HOME"), new List<_CardData> |
|||
{ |
|||
new _CardData( |
|||
title: "Flatwear", |
|||
imageAsset: "products/flatwear.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Pine Table", |
|||
imageAsset: "products/table.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Blue Cup", |
|||
imageAsset: "products/cup.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Tea Set", |
|||
imageAsset: "products/teaset.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Desk Set", |
|||
imageAsset: "products/deskset.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Blue Linen Napkins", |
|||
imageAsset: "products/napkins.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Planters", |
|||
imageAsset: "products/planters.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Kitchen Quattro", |
|||
imageAsset: "products/kitchen_quattro.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Platter", |
|||
imageAsset: "products/platter.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
} |
|||
}, |
|||
{ |
|||
new _TabPage(label: "APPAREL"), new List<_CardData> |
|||
{ |
|||
new _CardData( |
|||
title: "Cloud-White Dress", |
|||
imageAsset: "products/dress.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Ginger Scarf", |
|||
imageAsset: "products/scarf.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
new _CardData( |
|||
title: "Blush Sweats", |
|||
imageAsset: "products/sweats.png", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
), |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
|
|||
internal class _TabPage { |
|||
public _TabPage(string label) |
|||
{ |
|||
this.label = label; |
|||
} |
|||
|
|||
public readonly string label; |
|||
public string id => label.Substring(0, 1); |
|||
|
|||
public override string ToString() => $"{GetType()}(\"{label}\")"; |
|||
} |
|||
|
|||
internal class _CardData { |
|||
public _CardData(string title, string imageAsset, string imageAssetPackage) |
|||
{ |
|||
this.title = title; |
|||
this.imageAsset = imageAsset; |
|||
this.imageAssetPackage = imageAssetPackage; |
|||
} |
|||
|
|||
public readonly string title; |
|||
public readonly string imageAsset; |
|||
public readonly string imageAssetPackage; |
|||
|
|||
|
|||
} |
|||
|
|||
class _CardDataItem : StatelessWidget { |
|||
public _CardDataItem(_TabPage page, _CardData data) |
|||
{ |
|||
this.page = page; |
|||
this.data = data; |
|||
} |
|||
|
|||
internal const float height = 272.0f; |
|||
public readonly _TabPage page; |
|||
public readonly _CardData data; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Card( |
|||
child: new Padding( |
|||
padding: EdgeInsets.all(16.0f), |
|||
child: new Column( |
|||
crossAxisAlignment: CrossAxisAlignment.stretch, |
|||
mainAxisAlignment: MainAxisAlignment.start, |
|||
children: new List<Widget>{ |
|||
new Align( |
|||
alignment: page.id == "H" |
|||
? Alignment.centerLeft |
|||
: Alignment.centerRight, |
|||
child: new CircleAvatar(child: new Text(page.id)) |
|||
), |
|||
new SizedBox( |
|||
width: 144.0f, |
|||
height: 144.0f, |
|||
child: Image.file( |
|||
data.imageAssetPackage + data.imageAsset, |
|||
fit: BoxFit.contain |
|||
) |
|||
), |
|||
new Center( |
|||
child: new Text( |
|||
data.title, |
|||
style: Theme.of(context).textTheme.headline6 |
|||
) |
|||
) |
|||
} |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
class TabsDemo : StatelessWidget { |
|||
public static readonly string routeName = "/material/tabs"; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new DefaultTabController( |
|||
length: TabsDemoUtils._allPages.Count, |
|||
child: new Scaffold( |
|||
body: new NestedScrollView( |
|||
headerSliverBuilder: (BuildContext subContext, bool innerBoxIsScrolled) => { |
|||
return new List<Widget>{ |
|||
new SliverOverlapAbsorber( |
|||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(subContext), |
|||
sliver: new SliverAppBar( |
|||
title: new Text("Tabs and scrolling"), |
|||
actions: new List<Widget>{new MaterialDemoDocumentationButton(routeName)}, |
|||
pinned: true, |
|||
expandedHeight: 150.0f, |
|||
forceElevated: innerBoxIsScrolled, |
|||
bottom: new TabBar( |
|||
tabs: TabsDemoUtils._allPages.Keys.Select<_TabPage, Widget>( |
|||
(_TabPage page) => new Tab(text: page.label) |
|||
).ToList() |
|||
) |
|||
) |
|||
) |
|||
}; |
|||
}, |
|||
body: new TabBarView( |
|||
children: TabsDemoUtils._allPages.Keys.Select<_TabPage, Widget>((_TabPage page) => { |
|||
return new SafeArea( |
|||
top: false, |
|||
bottom: false, |
|||
child: new Builder( |
|||
builder: (BuildContext subContext) => { |
|||
return new CustomScrollView( |
|||
key: new PageStorageKey<_TabPage>(page), |
|||
slivers: new List<Widget>{ |
|||
new SliverOverlapInjector( |
|||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(subContext) |
|||
), |
|||
new SliverPadding( |
|||
padding: EdgeInsets.symmetric( |
|||
vertical: 8.0f, |
|||
horizontal: 16.0f |
|||
), |
|||
sliver: new SliverFixedExtentList( |
|||
itemExtent: _CardDataItem.height, |
|||
del: new SliverChildBuilderDelegate( |
|||
(BuildContext subsubContext, int index) => { |
|||
_CardData data = TabsDemoUtils._allPages[page][index]; |
|||
return new Padding( |
|||
padding: EdgeInsets.symmetric( |
|||
vertical: 8.0f |
|||
), |
|||
child: new _CardDataItem( |
|||
page: page, |
|||
data: data |
|||
) |
|||
); |
|||
}, |
|||
childCount: TabsDemoUtils._allPages[page].Count |
|||
) |
|||
) |
|||
) |
|||
} |
|||
); |
|||
} |
|||
) |
|||
); |
|||
}).ToList() |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using System.Text.RegularExpressions; |
|||
using uiwidgets; |
|||
using UIWidgets.Runtime.material; |
|||
using UIWidgetsGallery.gallery; |
|||
using Unity.UIWidgets.async2; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.gestures; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.service; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace UIWidgetsGallery.demo.material |
|||
{ |
|||
internal class TextFormFieldDemo : StatefulWidget |
|||
{ |
|||
public TextFormFieldDemo(Key key = null) : base(key: key) |
|||
{ |
|||
} |
|||
|
|||
public static readonly string routeName = "/material/text-form-field"; |
|||
|
|||
public override State createState() |
|||
{ |
|||
return new TextFormFieldDemoState(); |
|||
} |
|||
} |
|||
|
|||
internal class PersonData |
|||
{ |
|||
public string name = ""; |
|||
public string phoneNumber = ""; |
|||
public string email = ""; |
|||
public string password = ""; |
|||
} |
|||
|
|||
internal class PasswordField : StatefulWidget |
|||
{ |
|||
public PasswordField( |
|||
Key fieldKey = null, |
|||
string hintText = null, |
|||
string labelText = null, |
|||
string helperText = null, |
|||
FormFieldSetter<string> onSaved = null, |
|||
FormFieldValidator<string> validator = null, |
|||
ValueChanged<string> onFieldSubmitted = null |
|||
) |
|||
{ |
|||
this.fieldKey = fieldKey; |
|||
this.hintText = hintText; |
|||
this.labelText = labelText; |
|||
this.helperText = helperText; |
|||
this.onSaved = onSaved; |
|||
this.validator = validator; |
|||
this.onFieldSubmitted = onFieldSubmitted; |
|||
} |
|||
|
|||
public readonly Key fieldKey; |
|||
public readonly string hintText; |
|||
public readonly string labelText; |
|||
public readonly string helperText; |
|||
public readonly FormFieldSetter<string> onSaved; |
|||
public readonly FormFieldValidator<string> validator; |
|||
public readonly ValueChanged<string> onFieldSubmitted; |
|||
|
|||
|
|||
public override State createState() |
|||
{ |
|||
return new _PasswordFieldState(); |
|||
} |
|||
} |
|||
|
|||
internal class _PasswordFieldState : State<PasswordField> |
|||
{ |
|||
private bool _obscureText = true; |
|||
|
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
return new TextFormField( |
|||
key: widget.fieldKey, |
|||
obscureText: _obscureText, |
|||
maxLength: 8, |
|||
onSaved: widget.onSaved, |
|||
validator: widget.validator, |
|||
onFieldSubmitted: widget.onFieldSubmitted, |
|||
decoration: new InputDecoration( |
|||
border: new UnderlineInputBorder(), |
|||
filled: true, |
|||
hintText: widget.hintText, |
|||
labelText: widget.labelText, |
|||
helperText: widget.helperText, |
|||
suffixIcon: new GestureDetector( |
|||
dragStartBehavior: DragStartBehavior.down, |
|||
onTap: () => { setState(() => { _obscureText = !_obscureText; }); }, |
|||
child: new Icon( |
|||
_obscureText ? Icons.visibility : Icons.visibility_off |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
internal class TextFormFieldDemoState : State<TextFormFieldDemo> |
|||
{ |
|||
private readonly GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>.key(); |
|||
|
|||
private PersonData person = new PersonData(); |
|||
|
|||
private void showInSnackBar(string value) |
|||
{ |
|||
_scaffoldKey.currentState.showSnackBar(new SnackBar( |
|||
content: new Text(value) |
|||
)); |
|||
} |
|||
|
|||
private bool _autovalidate = false; |
|||
private bool _formWasEdited = false; |
|||
|
|||
private readonly GlobalKey<FormState> _formKey = GlobalKey<FormState>.key(); |
|||
private readonly GlobalKey<FormFieldState<string>> _passwordFieldKey = GlobalKey<FormFieldState<string>>.key(); |
|||
private readonly _UsNumberTextInputFormatter _phoneNumberFormatter = new _UsNumberTextInputFormatter(); |
|||
|
|||
private void _handleSubmitted() |
|||
{ |
|||
FormState form = _formKey.currentState; |
|||
if (!form.validate()) |
|||
{ |
|||
_autovalidate = true; // Start validating on every change"
|
|||
showInSnackBar("Please fix the errors in red before submitting."); |
|||
} |
|||
else |
|||
{ |
|||
form.save(); |
|||
showInSnackBar($"{person.name}'s phone number is ${person.phoneNumber}"); |
|||
} |
|||
} |
|||
|
|||
private string _validateName(string value) |
|||
{ |
|||
_formWasEdited = true; |
|||
if (value.isEmpty()) |
|||
return "Name is required."; |
|||
if (!Regex.IsMatch(value, @"^[a-zA-Z]+$")) |
|||
return "Please enter only alphabetical characters."; |
|||
return null; |
|||
} |
|||
|
|||
private string _validatePhoneNumber(string value) |
|||
{ |
|||
_formWasEdited = true; |
|||
if (!Regex.IsMatch(value, @"^\(\d\d\d\) \d\d\d\-\d\d\d\d$")) |
|||
return "(###) ###-#### - Enter a US phone number."; |
|||
return null; |
|||
} |
|||
|
|||
private string _validatePassword(string value) |
|||
{ |
|||
_formWasEdited = true; |
|||
FormFieldState<string> passwordField = _passwordFieldKey.currentState; |
|||
if (passwordField.value == null || passwordField.value.isEmpty()) |
|||
return "Please enter a password."; |
|||
if (passwordField.value != value) |
|||
return "The passwords don't match"; |
|||
return null; |
|||
} |
|||
|
|||
private Future<bool> _warnUserAboutInvalidData() |
|||
{ |
|||
FormState form = _formKey.currentState; |
|||
if (form == null || !_formWasEdited || form.validate()) |
|||
return Future.value(true).to<bool>(); |
|||
|
|||
return material_.showDialog<bool>( |
|||
context: context, |
|||
builder: (BuildContext context) => |
|||
{ |
|||
return new AlertDialog( |
|||
title: new Text("This form has errors"), |
|||
content: new Text("Really leave this form?"), |
|||
actions: new List<Widget> |
|||
{ |
|||
new FlatButton( |
|||
child: new Text("YES"), |
|||
onPressed: () => { Navigator.of(context).pop(true); } |
|||
), |
|||
new FlatButton( |
|||
child: new Text("NO"), |
|||
onPressed: () => { Navigator.of(context).pop(false); } |
|||
) |
|||
} |
|||
); |
|||
} |
|||
); |
|||
} |
|||
|
|||
|
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
return new Scaffold( |
|||
drawerDragStartBehavior: DragStartBehavior.down, |
|||
key: _scaffoldKey, |
|||
appBar: new AppBar( |
|||
title: new Text("Text fields"), |
|||
actions: new List<Widget> {new MaterialDemoDocumentationButton(TextFormFieldDemo.routeName)} |
|||
), |
|||
body: new SafeArea( |
|||
top: false, |
|||
bottom: false, |
|||
child: new Form( |
|||
key: _formKey, |
|||
autovalidate: _autovalidate, |
|||
onWillPop: _warnUserAboutInvalidData, |
|||
child: new Scrollbar( |
|||
child: new SingleChildScrollView( |
|||
dragStartBehavior: DragStartBehavior.down, |
|||
padding: EdgeInsets.symmetric(horizontal: 16.0f), |
|||
child: new Column( |
|||
crossAxisAlignment: CrossAxisAlignment.stretch, |
|||
children: new List<Widget> |
|||
{ |
|||
new SizedBox(height: 24.0f), |
|||
new TextFormField( |
|||
textCapitalization: TextCapitalization.words, |
|||
decoration: new InputDecoration( |
|||
border: new UnderlineInputBorder(), |
|||
filled: true, |
|||
icon: new Icon(Icons.person), |
|||
hintText: "What do people call you?", |
|||
labelText: "Name *" |
|||
), |
|||
onSaved: (string value) => { person.name = value; }, |
|||
validator: _validateName |
|||
), |
|||
new SizedBox(height: 24.0f), |
|||
new TextFormField( |
|||
decoration: new InputDecoration( |
|||
border: new UnderlineInputBorder(), |
|||
filled: true, |
|||
icon: new Icon(Icons.phone), |
|||
hintText: "Where can we reach you?", |
|||
labelText: "Phone Number *", |
|||
prefixText: "+1" |
|||
), |
|||
keyboardType: TextInputType.phone, |
|||
onSaved: (string value) => { person.phoneNumber = value; }, |
|||
validator: _validatePhoneNumber, |
|||
// TextInputFormatters are applied in sequence.
|
|||
inputFormatters: new List<TextInputFormatter> |
|||
{ |
|||
WhitelistingTextInputFormatter.digitsOnly, |
|||
// Fit the validating format.
|
|||
_phoneNumberFormatter |
|||
} |
|||
), |
|||
new SizedBox(height: 24.0f), |
|||
new TextFormField( |
|||
decoration: new InputDecoration( |
|||
border: new UnderlineInputBorder(), |
|||
filled: true, |
|||
icon: new Icon(Icons.email), |
|||
hintText: "Your email address", |
|||
labelText: "E-mail" |
|||
), |
|||
keyboardType: TextInputType.emailAddress, |
|||
onSaved: (string value) => { person.email = value; } |
|||
), |
|||
new SizedBox(height: 24.0f), |
|||
new TextFormField( |
|||
decoration: new InputDecoration( |
|||
border: new OutlineInputBorder(), |
|||
hintText: |
|||
"Tell us about yourself (e.g., write down what you do or what hobbies you have)", |
|||
helperText: "Keep it short, this is just a demo.", |
|||
labelText: "Life story" |
|||
), |
|||
maxLines: 3 |
|||
), |
|||
new SizedBox(height: 24.0f), |
|||
new TextFormField( |
|||
keyboardType: TextInputType.number, |
|||
decoration: new InputDecoration( |
|||
border: new OutlineInputBorder(), |
|||
labelText: "Salary", |
|||
prefixText: "$", |
|||
suffixText: "USD", |
|||
suffixStyle: new TextStyle(color: Colors.green) |
|||
), |
|||
maxLines: 1 |
|||
), |
|||
new SizedBox(height: 24.0f), |
|||
new PasswordField( |
|||
fieldKey: _passwordFieldKey, |
|||
helperText: "No more than 8 characters.", |
|||
labelText: "Password *", |
|||
onFieldSubmitted: (string value) => |
|||
{ |
|||
setState(() => { person.password = value; }); |
|||
} |
|||
), |
|||
new SizedBox(height: 24.0f), |
|||
new TextFormField( |
|||
enabled: person.password != null && person.password.isNotEmpty(), |
|||
decoration: new InputDecoration( |
|||
border: new UnderlineInputBorder(), |
|||
filled: true, |
|||
labelText: "Re-type password" |
|||
), |
|||
maxLength: 8, |
|||
obscureText: true, |
|||
validator: _validatePassword |
|||
), |
|||
new SizedBox(height: 24.0f), |
|||
new Center( |
|||
child: new RaisedButton( |
|||
child: new Text("SUBMIT"), |
|||
onPressed: _handleSubmitted |
|||
) |
|||
), |
|||
new SizedBox(height: 24.0f), |
|||
new Text( |
|||
"* indicates required field", |
|||
style: Theme.of(context).textTheme.caption |
|||
), |
|||
new SizedBox(height: 24.0f) |
|||
} |
|||
) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
internal class _UsNumberTextInputFormatter : TextInputFormatter |
|||
{ |
|||
public override TextEditingValue formatEditUpdate( |
|||
TextEditingValue oldValue, |
|||
TextEditingValue newValue |
|||
) |
|||
{ |
|||
int newTextLength = newValue.text.Length; |
|||
int selectionIndex = newValue.selection.end; |
|||
int usedSubstringIndex = 0; |
|||
StringBuilder newText = new StringBuilder(); |
|||
if (newTextLength >= 1) |
|||
{ |
|||
newText.Append("("); |
|||
if (newValue.selection.end >= 1) |
|||
selectionIndex++; |
|||
} |
|||
|
|||
if (newTextLength >= 4) |
|||
{ |
|||
newText.Append(newValue.text.Substring(0, usedSubstringIndex = 3) + ") "); |
|||
if (newValue.selection.end >= 3) |
|||
selectionIndex += 2; |
|||
} |
|||
|
|||
if (newTextLength >= 7) |
|||
{ |
|||
newText.Append(newValue.text.Substring(3, usedSubstringIndex = 6) + "-"); |
|||
if (newValue.selection.end >= 6) |
|||
selectionIndex++; |
|||
} |
|||
|
|||
if (newTextLength >= 11) |
|||
{ |
|||
newText.Append(newValue.text.Substring(6, usedSubstringIndex = 10) + " "); |
|||
if (newValue.selection.end >= 10) |
|||
selectionIndex++; |
|||
} |
|||
|
|||
// Dump the rest.
|
|||
if (newTextLength >= usedSubstringIndex) |
|||
newText.Append(newValue.text.Substring(usedSubstringIndex)); |
|||
return new TextEditingValue( |
|||
text: newText.ToString(), |
|||
selection: TextSelection.collapsed(offset: selectionIndex) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UIWidgetsGallery.gallery; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace UIWidgetsGallery.demo.material |
|||
{ |
|||
internal static class TooltipsDemoUtils |
|||
{ |
|||
public static readonly string _introText = |
|||
"Tooltips are short identifying messages that briefly appear in response to " + |
|||
"a long press. Tooltip messages are also used by services that make Flutter " + |
|||
"apps accessible, like screen readers."; |
|||
} |
|||
|
|||
internal class TooltipDemo : StatelessWidget |
|||
{ |
|||
public static readonly string routeName = |
|||
"/material/tooltips"; |
|||
|
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
ThemeData theme = Theme.of(context); |
|||
return new Scaffold( |
|||
appBar: new AppBar( |
|||
title: new Text("Tooltips"), |
|||
actions: new List<Widget> {new MaterialDemoDocumentationButton(routeName)} |
|||
), |
|||
body: new Builder( |
|||
builder: (BuildContext subContext) => |
|||
{ |
|||
return new SafeArea( |
|||
top: false, |
|||
bottom: false, |
|||
child: new ListView( |
|||
children: new List<Widget> |
|||
{ |
|||
new Text(TooltipsDemoUtils._introText, style: theme.textTheme.subtitle1), |
|||
new Row( |
|||
children: new List<Widget> |
|||
{ |
|||
new Text("Long press the ", style: theme.textTheme.subtitle1), |
|||
new Tooltip( |
|||
message: "call icon", |
|||
child: new Icon( |
|||
Icons.call, |
|||
size: 18.0f, |
|||
color: theme.iconTheme.color |
|||
) |
|||
), |
|||
new Text(" icon.", style: theme.textTheme.subtitle1) |
|||
} |
|||
), |
|||
new Center( |
|||
child: new IconButton( |
|||
iconSize: 48.0f, |
|||
icon: new Icon(Icons.call), |
|||
color: theme.iconTheme.color, |
|||
tooltip: "Place a phone call", |
|||
onPressed: () => |
|||
{ |
|||
Scaffold.of(context).showSnackBar(new SnackBar( |
|||
content: new Text("That was an ordinary tap.") |
|||
)); |
|||
} |
|||
) |
|||
) |
|||
} |
|||
.Select<Widget, Widget>((Widget widget) => |
|||
{ |
|||
return new Padding( |
|||
padding: EdgeInsets.only(top: 16.0f, left: 16.0f, right: 16.0f), |
|||
child: widget |
|||
); |
|||
}) |
|||
.ToList() |
|||
) |
|||
); |
|||
} |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue