mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
improve ui
This commit is contained in:
@@ -30,6 +30,7 @@ class NaviPane extends StatefulWidget {
|
|||||||
this.initialPage = 0,
|
this.initialPage = 0,
|
||||||
this.onPageChange,
|
this.onPageChange,
|
||||||
required this.observer,
|
required this.observer,
|
||||||
|
required this.navigatorKey,
|
||||||
super.key});
|
super.key});
|
||||||
|
|
||||||
final List<PaneItemEntry> paneItems;
|
final List<PaneItemEntry> paneItems;
|
||||||
@@ -44,6 +45,8 @@ class NaviPane extends StatefulWidget {
|
|||||||
|
|
||||||
final NaviObserver observer;
|
final NaviObserver observer;
|
||||||
|
|
||||||
|
final GlobalKey<NavigatorState> navigatorKey;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<NaviPane> createState() => _NaviPaneState();
|
State<NaviPane> createState() => _NaviPaneState();
|
||||||
}
|
}
|
||||||
@@ -60,6 +63,8 @@ class _NaviPaneState extends State<NaviPane>
|
|||||||
widget.onPageChange?.call(value);
|
widget.onPageChange?.call(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Function()? mainViewUpdateHandler;
|
||||||
|
|
||||||
late AnimationController controller;
|
late AnimationController controller;
|
||||||
|
|
||||||
static const _kBottomBarHeight = 58.0;
|
static const _kBottomBarHeight = 58.0;
|
||||||
@@ -77,6 +82,16 @@ class _NaviPaneState extends State<NaviPane>
|
|||||||
onRebuild(context);
|
onRebuild(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updatePage(int index) {
|
||||||
|
if(widget.observer.routes.length > 1) {
|
||||||
|
widget.navigatorKey.currentState!.popUntil((route) => route.isFirst);
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
currentPage = index;
|
||||||
|
});
|
||||||
|
mainViewUpdateHandler?.call();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
controller = AnimationController(
|
controller = AnimationController(
|
||||||
@@ -86,13 +101,11 @@ class _NaviPaneState extends State<NaviPane>
|
|||||||
vsync: this,
|
vsync: this,
|
||||||
);
|
);
|
||||||
widget.observer.addListener(onNavigatorStateChange);
|
widget.observer.addListener(onNavigatorStateChange);
|
||||||
StateController.put(NaviPaddingWidgetController());
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
StateController.remove<NaviPaddingWidgetController>();
|
|
||||||
controller.dispose();
|
controller.dispose();
|
||||||
widget.observer.removeListener(onNavigatorStateChange);
|
widget.observer.removeListener(onNavigatorStateChange);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
@@ -101,9 +114,6 @@ class _NaviPaneState extends State<NaviPane>
|
|||||||
double targetFormContext(BuildContext context) {
|
double targetFormContext(BuildContext context) {
|
||||||
var width = MediaQuery.of(context).size.width;
|
var width = MediaQuery.of(context).size.width;
|
||||||
double target = 0;
|
double target = 0;
|
||||||
if (widget.observer.pageCount > 1) {
|
|
||||||
target = 1;
|
|
||||||
}
|
|
||||||
if (width > changePoint) {
|
if (width > changePoint) {
|
||||||
target = 2;
|
target = 2;
|
||||||
}
|
}
|
||||||
@@ -125,19 +135,7 @@ class _NaviPaneState extends State<NaviPane>
|
|||||||
controller.stop();
|
controller.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (target == 1) {
|
|
||||||
StateController.find<NaviPaddingWidgetController>()
|
|
||||||
.setWithPadding(true, true, true);
|
|
||||||
controller.value = target;
|
|
||||||
} else if (controller.value == 1 && target == 0) {
|
|
||||||
StateController.findOrNull<NaviPaddingWidgetController>()
|
|
||||||
?.setWithPadding(false, false, false);
|
|
||||||
controller.value = target;
|
|
||||||
} else {
|
|
||||||
StateController.findOrNull<NaviPaddingWidgetController>()
|
|
||||||
?.setWithPadding(false, false, false);
|
|
||||||
controller.animateTo(target);
|
controller.animateTo(target);
|
||||||
}
|
|
||||||
animationTarget = target;
|
animationTarget = target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,40 +158,17 @@ class _NaviPaneState extends State<NaviPane>
|
|||||||
final value = controller.value;
|
final value = controller.value;
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
if (value <= 1)
|
|
||||||
Positioned(
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: bottomBarHeight * (0 - value),
|
|
||||||
child: buildBottom(),
|
|
||||||
),
|
|
||||||
if (value <= 1)
|
|
||||||
Positioned(
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
top: _kTopBarHeight * (0 - value) +
|
|
||||||
MediaQuery.of(context).padding.top * (1 - value),
|
|
||||||
child: buildTop(),
|
|
||||||
),
|
|
||||||
Positioned(
|
Positioned(
|
||||||
left: _kFoldedSideBarWidth * ((value - 2.0).clamp(-1.0, 0.0)),
|
left: _kFoldedSideBarWidth * ((value - 2.0).clamp(-1.0, 0.0)),
|
||||||
top: 0,
|
top: 0,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
child: buildLeft(),
|
child: buildLeft(),
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned.fill(
|
||||||
top: _kTopBarHeight * ((1 - value).clamp(0, 1)) +
|
|
||||||
MediaQuery.of(context).padding.top * (value == 0 ? 1 : 0),
|
|
||||||
left: _kFoldedSideBarWidth * ((value - 1).clamp(0, 1)) +
|
left: _kFoldedSideBarWidth * ((value - 1).clamp(0, 1)) +
|
||||||
(_kSideBarWidth - _kFoldedSideBarWidth) *
|
(_kSideBarWidth - _kFoldedSideBarWidth) *
|
||||||
((value - 2).clamp(0, 1)),
|
((value - 2).clamp(0, 1)),
|
||||||
right: 0,
|
child: buildMainView(),
|
||||||
bottom: bottomBarHeight * ((1 - value).clamp(0, 1)),
|
|
||||||
child: MediaQuery.removePadding(
|
|
||||||
removeTop: value == 0,
|
|
||||||
context: context,
|
|
||||||
child: Material(child: widget.pageBuilder(currentPage)),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -202,6 +177,24 @@ class _NaviPaneState extends State<NaviPane>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildMainView() {
|
||||||
|
return Navigator(
|
||||||
|
observers: [widget.observer],
|
||||||
|
key: widget.navigatorKey,
|
||||||
|
onGenerateRoute: (settings) => AppPageRoute(
|
||||||
|
preventRebuild: false,
|
||||||
|
isRootRoute: true,
|
||||||
|
builder: (context) {
|
||||||
|
return _NaviMainView(state: this);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildMainViewContent() {
|
||||||
|
return widget.pageBuilder(currentPage);
|
||||||
|
}
|
||||||
|
|
||||||
Widget buildTop() {
|
Widget buildTop() {
|
||||||
return Material(
|
return Material(
|
||||||
child: Container(
|
child: Container(
|
||||||
@@ -244,22 +237,25 @@ class _NaviPaneState extends State<NaviPane>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding: EdgeInsets.only(
|
||||||
EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
bottom: MediaQuery.of(context).padding.bottom,
|
||||||
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: List<Widget>.generate(
|
children: List<Widget>.generate(
|
||||||
widget.paneItems.length,
|
widget.paneItems.length,
|
||||||
(index) => Expanded(
|
(index) {
|
||||||
|
return Expanded(
|
||||||
child: _SingleBottomNaviWidget(
|
child: _SingleBottomNaviWidget(
|
||||||
enabled: currentPage == index,
|
enabled: currentPage == index,
|
||||||
entry: widget.paneItems[index],
|
entry: widget.paneItems[index],
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
updatePage(index);
|
||||||
currentPage = index;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
key: ValueKey(index),
|
key: ValueKey(index),
|
||||||
))),
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -300,9 +296,7 @@ class _NaviPaneState extends State<NaviPane>
|
|||||||
entry: widget.paneItems[index],
|
entry: widget.paneItems[index],
|
||||||
showTitle: value == 3,
|
showTitle: value == 3,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
updatePage(index);
|
||||||
currentPage = index;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
key: ValueKey(index),
|
key: ValueKey(index),
|
||||||
),
|
),
|
||||||
@@ -654,54 +648,44 @@ class _NaviPopScope extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NaviPaddingWidgetController extends StateController {
|
class _NaviMainView extends StatefulWidget {
|
||||||
NaviPaddingWidgetController();
|
const _NaviMainView({required this.state});
|
||||||
|
|
||||||
bool _withPadding = false;
|
final _NaviPaneState state;
|
||||||
|
|
||||||
bool _withTopBarPadding = false;
|
@override
|
||||||
|
State<_NaviMainView> createState() => _NaviMainViewState();
|
||||||
bool _withBottomBarPadding = false;
|
|
||||||
|
|
||||||
void setWithPadding(
|
|
||||||
bool withPadding, bool withAppbarPadding, bool withBottomBarPadding) {
|
|
||||||
_withPadding = withPadding;
|
|
||||||
_withTopBarPadding = withAppbarPadding;
|
|
||||||
_withBottomBarPadding = withBottomBarPadding;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class NaviPaddingWidget extends StatelessWidget {
|
class _NaviMainViewState extends State<_NaviMainView> {
|
||||||
const NaviPaddingWidget({super.key, required this.child});
|
_NaviPaneState get state => widget.state;
|
||||||
|
|
||||||
final Widget child;
|
@override
|
||||||
|
void initState() {
|
||||||
|
state.mainViewUpdateHandler = () {
|
||||||
|
setState(() {});
|
||||||
|
};
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StateBuilder<NaviPaddingWidgetController>(
|
var shouldShowAppBar = state.controller.value < 2;
|
||||||
builder: (controller) {
|
return Column(
|
||||||
return Padding(
|
children: [
|
||||||
padding: controller._withPadding
|
if (shouldShowAppBar) state.buildTop().paddingTop(context.padding.top),
|
||||||
? EdgeInsets.only(
|
Expanded(
|
||||||
top: context.padding.top +
|
|
||||||
(controller._withTopBarPadding
|
|
||||||
? _NaviPaneState._kTopBarHeight
|
|
||||||
: 0),
|
|
||||||
bottom: context.padding.bottom +
|
|
||||||
(controller._withBottomBarPadding
|
|
||||||
? _NaviPaneState._kBottomBarHeight
|
|
||||||
: 0),
|
|
||||||
)
|
|
||||||
: EdgeInsets.zero,
|
|
||||||
child: MediaQuery.removePadding(
|
child: MediaQuery.removePadding(
|
||||||
removeTop: controller._withPadding,
|
|
||||||
removeBottom: controller._withPadding,
|
|
||||||
context: context,
|
context: context,
|
||||||
child: child,
|
removeTop: shouldShowAppBar,
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: _fastAnimationDuration,
|
||||||
|
child: state.buildMainViewContent(),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
|
if (shouldShowAppBar) state.buildBottom().paddingBottom(context.padding.bottom),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ import 'dart:math';
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:venera/components/components.dart';
|
|
||||||
|
|
||||||
const double _kBackGestureWidth = 20.0;
|
const double _kBackGestureWidth = 20.0;
|
||||||
const int _kMaxDroppedSwipePageForwardAnimationTime = 800;
|
const int _kMaxDroppedSwipePageForwardAnimationTime = 800;
|
||||||
@@ -36,11 +35,7 @@ class AppPageRoute<T> extends PageRoute<T> with _AppRouteTransitionMixin{
|
|||||||
@override
|
@override
|
||||||
Widget buildContent(BuildContext context) {
|
Widget buildContent(BuildContext context) {
|
||||||
var widget = builder(context);
|
var widget = builder(context);
|
||||||
if(widget is NaviPaddingWidget) {
|
|
||||||
label = widget.child.runtimeType.toString();
|
|
||||||
} else {
|
|
||||||
label = widget.runtimeType.toString();
|
label = widget.runtimeType.toString();
|
||||||
}
|
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,7 +6,6 @@ import 'package:venera/utils/translations.dart';
|
|||||||
|
|
||||||
import '../components/components.dart';
|
import '../components/components.dart';
|
||||||
import '../foundation/app.dart';
|
import '../foundation/app.dart';
|
||||||
import '../foundation/app_page_route.dart';
|
|
||||||
import 'explore_page.dart';
|
import 'explore_page.dart';
|
||||||
import 'favorites/favorites_page.dart';
|
import 'favorites/favorites_page.dart';
|
||||||
import 'home_page.dart';
|
import 'home_page.dart';
|
||||||
@@ -56,6 +55,7 @@ class _MainPageState extends State<MainPage> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return NaviPane(
|
return NaviPane(
|
||||||
observer: _observer,
|
observer: _observer,
|
||||||
|
navigatorKey: _navigatorKey!,
|
||||||
paneItems: [
|
paneItems: [
|
||||||
PaneItemEntry(
|
PaneItemEntry(
|
||||||
label: 'Home'.tl,
|
label: 'Home'.tl,
|
||||||
@@ -96,32 +96,7 @@ class _MainPageState extends State<MainPage> {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
pageBuilder: (index) {
|
pageBuilder: (index) {
|
||||||
return Navigator(
|
return _pages[index];
|
||||||
observers: [_observer],
|
|
||||||
key: _navigatorKey,
|
|
||||||
onGenerateRoute: (settings) => AppPageRoute(
|
|
||||||
preventRebuild: false,
|
|
||||||
isRootRoute: true,
|
|
||||||
builder: (context) {
|
|
||||||
return NaviPaddingWidget(child: _pages[index]);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onPageChange: (index) {
|
|
||||||
setState(() {
|
|
||||||
this.index = index;
|
|
||||||
});
|
|
||||||
_navigatorKey!.currentState?.pushAndRemoveUntil(
|
|
||||||
AppPageRoute(
|
|
||||||
preventRebuild: false,
|
|
||||||
isRootRoute: true,
|
|
||||||
builder: (context) {
|
|
||||||
return NaviPaddingWidget(child: _pages[index]);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(route) => false,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user