浏览代码
Merge pull request #281 from UnityTech/yczhang1.5.4
Merge pull request #281 from UnityTech/yczhang1.5.4
[Cupertino] Implement nav bar (with ValueListenerBuilder and DefaultTextStyleTransition)/main
GitHub
5 年前
当前提交
5836cbf7
共有 10 个文件被更改,包括 1354 次插入 和 10 次删除
-
8Runtime/cupertino/page_scaffold.cs
-
2Runtime/cupertino/text_theme.cs
-
12Runtime/cupertino/theme.cs
-
43Runtime/widgets/transitions.cs
-
202Runtime/cupertino/bottom_app_bar.cs
-
11Runtime/cupertino/bottom_app_bar.cs.meta
-
1001Runtime/cupertino/nav_bar.cs
-
11Runtime/cupertino/nav_bar.cs.meta
-
63Runtime/widgets/value_listenable_builder.cs
-
11Runtime/widgets/value_listenable_builder.cs.meta
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.gestures; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using TextStyle = Unity.UIWidgets.painting.TextStyle; |
|||
|
|||
namespace Unity.UIWidgets.cupertino { |
|||
class BottomAppBarUtils { |
|||
public const float _kTabBarHeight = 50.0f; |
|||
public static readonly Color _kDefaultTabBarBorderColor = new Color(0x4C000000); |
|||
} |
|||
|
|||
|
|||
public class CupertinoTabBar : StatelessWidget { |
|||
public CupertinoTabBar( |
|||
Key key = null, |
|||
List<BottomNavigationBarItem> items = null, |
|||
ValueChanged<int> onTap = null, |
|||
int currentIndex = 0, |
|||
Color backgroundColor = null, |
|||
Color activeColor = null, |
|||
Color inactiveColor = null, |
|||
float iconSize = 30.0f, |
|||
Border border = null |
|||
) : base(key: key) { |
|||
D.assert(items != null); |
|||
D.assert(items.Count >= 2, |
|||
() => "Tabs need at least 2 items to conform to Apple's HIG" |
|||
); |
|||
D.assert(0 <= currentIndex && currentIndex < items.Count); |
|||
D.assert(inactiveColor != null); |
|||
this.items = items; |
|||
this.onTap = onTap; |
|||
this.currentIndex = currentIndex; |
|||
|
|||
this.backgroundColor = backgroundColor; |
|||
this.activeColor = activeColor; |
|||
this.inactiveColor = inactiveColor ?? CupertinoColors.inactiveGray; |
|||
this.iconSize = iconSize; |
|||
this.border = border ?? new Border( |
|||
top: new BorderSide( |
|||
color: BottomAppBarUtils._kDefaultTabBarBorderColor, |
|||
width: 0.0f, // One physical pixel.
|
|||
style: BorderStyle.solid |
|||
) |
|||
); |
|||
} |
|||
|
|||
public readonly List<BottomNavigationBarItem> items; |
|||
|
|||
public readonly ValueChanged<int> onTap; |
|||
|
|||
public readonly int currentIndex; |
|||
|
|||
public readonly Color backgroundColor; |
|||
|
|||
public readonly Color activeColor; |
|||
|
|||
public readonly Color inactiveColor; |
|||
|
|||
public readonly float iconSize; |
|||
|
|||
public readonly Border border; |
|||
|
|||
public Size preferredSize { |
|||
get { return Size.fromHeight(BottomAppBarUtils._kTabBarHeight); } |
|||
} |
|||
|
|||
bool opaque(BuildContext context) { |
|||
Color backgroundColor = |
|||
this.backgroundColor ?? CupertinoTheme.of(context).barBackgroundColor; |
|||
return backgroundColor.alpha == 0xFF; |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
float bottomPadding = MediaQuery.of(context).padding.bottom; |
|||
|
|||
Widget result = new DecoratedBox( |
|||
decoration: new BoxDecoration( |
|||
border: this.border, |
|||
color: this.backgroundColor ?? CupertinoTheme.of(context).barBackgroundColor |
|||
), |
|||
child: new SizedBox( |
|||
height: BottomAppBarUtils._kTabBarHeight + bottomPadding, |
|||
child: IconTheme.merge( // Default with the inactive state.
|
|||
data: new IconThemeData( |
|||
color: this.inactiveColor, |
|||
size: this.iconSize |
|||
), |
|||
child: new DefaultTextStyle( // Default with the inactive state.
|
|||
style: CupertinoTheme.of(context).textTheme.tabLabelTextStyle |
|||
.copyWith(color: this.inactiveColor), |
|||
child: new Padding( |
|||
padding: EdgeInsets.only(bottom: bottomPadding), |
|||
child: new Row( |
|||
crossAxisAlignment: CrossAxisAlignment.end, |
|||
children: this._buildTabItems(context) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
|
|||
if (!this.opaque(context)) { |
|||
result = new ClipRect( |
|||
child: new BackdropFilter( |
|||
filter: ImageFilter.blur(sigmaX: 10.0f, sigmaY: 10.0f), |
|||
child: result |
|||
) |
|||
); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
List<Widget> _buildTabItems(BuildContext context) { |
|||
List<Widget> result = new List<Widget> { }; |
|||
|
|||
for (int index = 0; index < this.items.Count; index += 1) { |
|||
bool active = index == this.currentIndex; |
|||
result.Add( |
|||
this._wrapActiveItem( |
|||
context, |
|||
new Expanded( |
|||
child: new GestureDetector( |
|||
behavior: HitTestBehavior.opaque, |
|||
onTap: this.onTap == null ? null : (GestureTapCallback) (() => { this.onTap(index); }), |
|||
child: new Padding( |
|||
padding: EdgeInsets.only(bottom: 4.0f), |
|||
child: new Column( |
|||
mainAxisAlignment: MainAxisAlignment.end, |
|||
children: this._buildSingleTabItem(this.items[index], active) |
|||
) |
|||
) |
|||
) |
|||
), |
|||
active: active |
|||
) |
|||
); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
List<Widget> _buildSingleTabItem(BottomNavigationBarItem item, bool active) { |
|||
List<Widget> components = new List<Widget> { |
|||
new Expanded( |
|||
child: new Center(child: active ? item.activeIcon : item.icon) |
|||
) |
|||
}; |
|||
|
|||
if (item.title != null) { |
|||
components.Add(item.title); |
|||
} |
|||
|
|||
return components; |
|||
} |
|||
|
|||
Widget _wrapActiveItem(BuildContext context, Widget item, bool active) { |
|||
if (!active) { |
|||
return item; |
|||
} |
|||
|
|||
Color activeColor = this.activeColor ?? CupertinoTheme.of(context).primaryColor; |
|||
return IconTheme.merge( |
|||
data: new IconThemeData(color: activeColor), |
|||
child: DefaultTextStyle.merge( |
|||
style: new TextStyle(color: activeColor), |
|||
child: item |
|||
) |
|||
); |
|||
} |
|||
|
|||
CupertinoTabBar copyWith( |
|||
Key key = null, |
|||
List<BottomNavigationBarItem> items = null, |
|||
Color backgroundColor = null, |
|||
Color activeColor = null, |
|||
Color inactiveColor = null, |
|||
float? iconSize = null, |
|||
Border border = null, |
|||
int? currentIndex = null, |
|||
ValueChanged<int> onTap = null |
|||
) { |
|||
return new CupertinoTabBar( |
|||
key: key ?? this.key, |
|||
items: items ?? this.items, |
|||
backgroundColor: backgroundColor ?? this.backgroundColor, |
|||
activeColor: activeColor ?? this.activeColor, |
|||
inactiveColor: inactiveColor ?? this.inactiveColor, |
|||
iconSize: iconSize ?? this.iconSize, |
|||
border: border ?? this.border, |
|||
currentIndex: currentIndex ?? this.currentIndex, |
|||
onTap: onTap ?? this.onTap |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a4d68e50e84368e42b995ebca3727675 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
1001
Runtime/cupertino/nav_bar.cs
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
fileFormatVersion: 2 |
|||
guid: 3b784deecd91aef4085ba0796eea3324 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
namespace Unity.UIWidgets.widgets { |
|||
public delegate Widget ValueWidgetBuilder<T>(BuildContext context, T value, Widget child); |
|||
|
|||
public class ValueListenableBuilder<T> : StatefulWidget { |
|||
public ValueListenableBuilder( |
|||
ValueListenable<T> valueListenable, |
|||
ValueWidgetBuilder<T> builder, |
|||
Widget child = null |
|||
) { |
|||
D.assert(valueListenable != null); |
|||
D.assert(builder != null); |
|||
this.valueListenable = valueListenable; |
|||
this.builder = builder; |
|||
this.child = child; |
|||
} |
|||
|
|||
public readonly ValueListenable<T> valueListenable; |
|||
|
|||
public readonly ValueWidgetBuilder<T> builder; |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public override State createState() { |
|||
return new _ValueListenableBuilderState<T>(); |
|||
} |
|||
} |
|||
|
|||
class _ValueListenableBuilderState<T> : State<ValueListenableBuilder<T>> { |
|||
T value; |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this.value = this.widget.valueListenable.value; |
|||
this.widget.valueListenable.addListener(this._valueChanged); |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget _oldWidget) { |
|||
ValueListenableBuilder<T> oldWidget = _oldWidget as ValueListenableBuilder<T>; |
|||
if (oldWidget.valueListenable != this.widget.valueListenable) { |
|||
oldWidget.valueListenable.removeListener(this._valueChanged); |
|||
this.value = this.widget.valueListenable.value; |
|||
this.widget.valueListenable.addListener(this._valueChanged); |
|||
} |
|||
|
|||
base.didUpdateWidget(oldWidget); |
|||
} |
|||
|
|||
public override void dispose() { |
|||
this.widget.valueListenable.removeListener(this._valueChanged); |
|||
base.dispose(); |
|||
} |
|||
|
|||
void _valueChanged() { |
|||
this.setState(() => { this.value = this.widget.valueListenable.value; }); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return this.widget.builder(context, this.value, this.widget.child); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c4b7ae22b588cdf4093501087a4ecadb |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue