Yuncong Zhang
5 年前
当前提交
c2a0a0dd
共有 3 个文件被更改,包括 227 次插入 和 2 次删除
-
4Runtime/cupertino/bottom_app_bar.cs
-
214Runtime/cupertino/tab_scaffold.cs
-
11Runtime/cupertino/tab_scaffold.cs.meta
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace Unity.UIWidgets.cupertino { |
|||
public class CupertinoTabScaffold : StatefulWidget { |
|||
public CupertinoTabScaffold( |
|||
Key key = null, |
|||
CupertinoTabBar tabBar = null, |
|||
IndexedWidgetBuilder tabBuilder = null, |
|||
Color backgroundColor = null, |
|||
bool resizeToAvoidBottomInset = true |
|||
) : base(key: key) { |
|||
D.assert(tabBar != null); |
|||
D.assert(tabBuilder != null); |
|||
this.tabBar = tabBar; |
|||
this.tabBuilder = tabBuilder; |
|||
this.backgroundColor = backgroundColor; |
|||
this.resizeToAvoidBottomInset = resizeToAvoidBottomInset; |
|||
} |
|||
|
|||
|
|||
public readonly CupertinoTabBar tabBar; |
|||
|
|||
public readonly IndexedWidgetBuilder tabBuilder; |
|||
|
|||
public readonly Color backgroundColor; |
|||
|
|||
public readonly bool resizeToAvoidBottomInset; |
|||
|
|||
public override State createState() { |
|||
return new _CupertinoTabScaffoldState(); |
|||
} |
|||
} |
|||
|
|||
class _CupertinoTabScaffoldState : State<CupertinoTabScaffold> { |
|||
int _currentPage; |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this._currentPage = this.widget.tabBar.currentIndex; |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget _oldWidget) { |
|||
CupertinoTabScaffold oldWidget = _oldWidget as CupertinoTabScaffold; |
|||
base.didUpdateWidget(oldWidget); |
|||
if (this._currentPage >= this.widget.tabBar.items.Count) { |
|||
this._currentPage = this.widget.tabBar.items.Count - 1; |
|||
D.assert(this._currentPage >= 0, |
|||
() => "CupertinoTabBar is expected to keep at least 2 tabs after updating" |
|||
); |
|||
} |
|||
|
|||
if (this.widget.tabBar.currentIndex != oldWidget.tabBar.currentIndex) { |
|||
this._currentPage = this.widget.tabBar.currentIndex; |
|||
} |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
List<Widget> stacked = new List<Widget> { }; |
|||
|
|||
MediaQueryData existingMediaQuery = MediaQuery.of(context); |
|||
MediaQueryData newMediaQuery = MediaQuery.of(context); |
|||
|
|||
Widget content = new _TabSwitchingView( |
|||
currentTabIndex: this._currentPage, |
|||
tabNumber: this.widget.tabBar.items.Count, |
|||
tabBuilder: this.widget.tabBuilder |
|||
); |
|||
EdgeInsets contentPadding = EdgeInsets.zero; |
|||
|
|||
if (this.widget.resizeToAvoidBottomInset) { |
|||
newMediaQuery = newMediaQuery.removeViewInsets(removeBottom: true); |
|||
contentPadding = EdgeInsets.only(bottom: existingMediaQuery.viewInsets.bottom); |
|||
} |
|||
|
|||
if (this.widget.tabBar != null && |
|||
(!this.widget.resizeToAvoidBottomInset || |
|||
this.widget.tabBar.preferredSize.height > existingMediaQuery.viewInsets.bottom)) { |
|||
float bottomPadding = this.widget.tabBar.preferredSize.height + existingMediaQuery.padding.bottom; |
|||
|
|||
if (this.widget.tabBar.opaque(context)) { |
|||
contentPadding = EdgeInsets.only(bottom: bottomPadding); |
|||
} |
|||
else { |
|||
newMediaQuery = newMediaQuery.copyWith( |
|||
padding: newMediaQuery.padding.copyWith( |
|||
bottom: bottomPadding |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
content = new MediaQuery( |
|||
data: newMediaQuery, |
|||
child: new Padding( |
|||
padding: contentPadding, |
|||
child: content |
|||
) |
|||
); |
|||
|
|||
stacked.Add(content); |
|||
|
|||
if (this.widget.tabBar != null) { |
|||
stacked.Add(new Align( |
|||
alignment: Alignment.bottomCenter, |
|||
child: this.widget.tabBar.copyWith( |
|||
currentIndex: this._currentPage, |
|||
onTap: (int newIndex) => { |
|||
this.setState(() => { this._currentPage = newIndex; }); |
|||
if (this.widget.tabBar.onTap != null) { |
|||
this.widget.tabBar.onTap(newIndex); |
|||
} |
|||
} |
|||
) |
|||
)); |
|||
} |
|||
|
|||
return new DecoratedBox( |
|||
decoration: new BoxDecoration( |
|||
color: this.widget.backgroundColor ?? CupertinoTheme.of(context).scaffoldBackgroundColor |
|||
), |
|||
child: new Stack( |
|||
children: stacked |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _TabSwitchingView : StatefulWidget { |
|||
public _TabSwitchingView( |
|||
int currentTabIndex, |
|||
int tabNumber, |
|||
IndexedWidgetBuilder tabBuilder |
|||
) { |
|||
D.assert(currentTabIndex != null); |
|||
D.assert(tabNumber != null && tabNumber > 0); |
|||
D.assert(tabBuilder != null); |
|||
} |
|||
|
|||
public readonly int currentTabIndex; |
|||
public readonly int tabNumber; |
|||
public readonly IndexedWidgetBuilder tabBuilder; |
|||
|
|||
public override State createState() { |
|||
return new _TabSwitchingViewState(); |
|||
} |
|||
} |
|||
|
|||
class _TabSwitchingViewState : State<_TabSwitchingView> { |
|||
List<Widget> tabs; |
|||
List<FocusScopeNode> tabFocusNodes; |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this.tabs = new List<Widget>(this.widget.tabNumber); |
|||
this.tabFocusNodes = Enumerable.Repeat(new FocusScopeNode(), this.widget.tabNumber).ToList(); |
|||
} |
|||
|
|||
public override void didChangeDependencies() { |
|||
base.didChangeDependencies(); |
|||
this._focusActiveTab(); |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget _oldWidget) { |
|||
_TabSwitchingView oldWidget = _oldWidget as _TabSwitchingView; |
|||
base.didUpdateWidget(oldWidget); |
|||
this._focusActiveTab(); |
|||
} |
|||
|
|||
void _focusActiveTab() { |
|||
FocusScope.of(this.context).setFirstFocus(this.tabFocusNodes[this.widget.currentTabIndex]); |
|||
} |
|||
|
|||
public override void dispose() { |
|||
foreach (FocusScopeNode focusScopeNode in this.tabFocusNodes) { |
|||
focusScopeNode.detach(); |
|||
} |
|||
|
|||
base.dispose(); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
List<Widget> children = new List<Widget>(); |
|||
for (int index = 0; index < this.widget.tabNumber; index++) { |
|||
bool active = index == this.widget.currentTabIndex; |
|||
|
|||
if (active || this.tabs[index] != null) { |
|||
this.tabs[index] = this.widget.tabBuilder(context, index); |
|||
} |
|||
|
|||
children.Add(new Offstage( |
|||
offstage: !active, |
|||
child: new TickerMode( |
|||
enabled: active, |
|||
child: new FocusScope( |
|||
node: this.tabFocusNodes[index], |
|||
child: this.tabs[index] ?? new Container() |
|||
) |
|||
) |
|||
)); |
|||
} |
|||
|
|||
return new Stack( |
|||
fit: StackFit.expand, |
|||
children: children |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: dd65a2bea05bed8409d301489cf20864 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue