chore: some UI/UX to bottom nav bar navigation (#2190)
This commit is contained in:
parent
185595370e
commit
bf102a33ef
5 changed files with 145 additions and 220 deletions
|
|
@ -692,11 +692,14 @@ abstract class AppRoutes {
|
|||
GoRouterState state,
|
||||
Widget child,
|
||||
) =>
|
||||
FluffyThemes.isColumnMode(context)
|
||||
? noTransitionPageBuilder(context, state, child)
|
||||
: MaterialPage(
|
||||
key: state.pageKey,
|
||||
restorationId: state.pageKey.value,
|
||||
child: child,
|
||||
);
|
||||
// #Pangea
|
||||
noTransitionPageBuilder(context, state, child);
|
||||
// FluffyThemes.isColumnMode(context)
|
||||
// ? noTransitionPageBuilder(context, state, child)
|
||||
// : MaterialPage(
|
||||
// key: state.pageKey,
|
||||
// restorationId: state.pageKey.value,
|
||||
// child: child,
|
||||
// );
|
||||
// Pangea#
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart';
|
||||
import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart';
|
||||
|
|
@ -44,37 +42,6 @@ class ActivitySuggestionsAreaState extends State<ActivitySuggestionsArea> {
|
|||
double get cardPadding => _isColumnMode ? 8.0 : 0.0;
|
||||
double get cardWidth => _isColumnMode ? 225.0 : 150.0;
|
||||
|
||||
void _scrollToItem(int index) {
|
||||
final viewportDimension = _scrollController.position.viewportDimension;
|
||||
final double scrollOffset = _isColumnMode
|
||||
? index * cardWidth - (viewportDimension / 2) + (cardWidth / 2)
|
||||
: (index + 1) * (cardHeight + 8.0);
|
||||
final maxScrollExtent = _scrollController.position.maxScrollExtent;
|
||||
final safeOffset = scrollOffset.clamp(0.0, maxScrollExtent);
|
||||
if (safeOffset == _scrollController.offset) {
|
||||
return;
|
||||
}
|
||||
_scrollController.animateTo(
|
||||
safeOffset,
|
||||
duration: FluffyThemes.animationDuration,
|
||||
curve: FluffyThemes.animationCurve,
|
||||
);
|
||||
}
|
||||
|
||||
// void _scrollToNextItem(AxisDirection direction) {
|
||||
// final currentOffset = _scrollController.offset;
|
||||
// final scrollAmount = _isColumnMode ? cardWidth : cardHeight;
|
||||
|
||||
// _scrollController.animateTo(
|
||||
// (direction == AxisDirection.left
|
||||
// ? currentOffset - scrollAmount
|
||||
// : currentOffset + scrollAmount)
|
||||
// .clamp(0.0, _scrollController.position.maxScrollExtent),
|
||||
// duration: FluffyThemes.animationDuration,
|
||||
// curve: FluffyThemes.animationCurve,
|
||||
// );
|
||||
// }
|
||||
|
||||
Future<void> _setActivityItems() async {
|
||||
final ActivityPlanRequest request = ActivityPlanRequest(
|
||||
topic: "",
|
||||
|
|
@ -91,17 +58,16 @@ class ActivitySuggestionsAreaState extends State<ActivitySuggestionsArea> {
|
|||
);
|
||||
final resp = await ActivitySearchRepo.get(request);
|
||||
_activityItems.addAll(resp.activityPlans);
|
||||
setState(() {});
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Widget> cards = _activityItems
|
||||
.mapIndexed((i, activity) {
|
||||
.map((activity) {
|
||||
return ActivitySuggestionCard(
|
||||
activity: activity,
|
||||
onPressed: () {
|
||||
_scrollToItem(i);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
|
|
@ -142,14 +108,13 @@ class ActivitySuggestionsAreaState extends State<ActivitySuggestionsArea> {
|
|||
),
|
||||
),
|
||||
)
|
||||
: SizedBox.expand(
|
||||
child: SingleChildScrollView(
|
||||
controller: _scrollController,
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceEvenly,
|
||||
runSpacing: 16.0,
|
||||
children: cards,
|
||||
),
|
||||
: SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceEvenly,
|
||||
runSpacing: 16.0,
|
||||
spacing: 4.0,
|
||||
children: cards,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,67 +15,72 @@ class SuggestionsPage extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final isColumnMode = FluffyThemes.isColumnMode(context);
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: isColumnMode ? 36.0 : 8.0,
|
||||
vertical: isColumnMode ? 24.0 : 8.0,
|
||||
),
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (!isColumnMode) const LearningProgressIndicators(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: isColumnMode ? 12.0 : 4.0,
|
||||
right: isColumnMode ? 12.0 : 4.0,
|
||||
top: 16.0,
|
||||
bottom: 16.0,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).learnByTexting,
|
||||
style: isColumnMode
|
||||
? theme.textTheme.titleLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold)
|
||||
: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
return SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: isColumnMode ? 36.0 : 4.0,
|
||||
vertical: 16.0,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (!isColumnMode)
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: isColumnMode ? 0 : 12.0),
|
||||
child: const LearningProgressIndicators(),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: isColumnMode ? 12.0 : 4.0,
|
||||
right: isColumnMode ? 12.0 : 4.0,
|
||||
top: 16.0,
|
||||
bottom: 16.0,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).learnByTexting,
|
||||
style: isColumnMode
|
||||
? theme.textTheme.titleLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold)
|
||||
: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(36.0),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 6.0,
|
||||
horizontal: 10.0,
|
||||
),
|
||||
child: Row(
|
||||
spacing: 8.0,
|
||||
children: [
|
||||
PangeaLogoSvg(
|
||||
width: 16.0,
|
||||
forceColor: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(36.0),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 6.0,
|
||||
horizontal: 10.0,
|
||||
),
|
||||
child: Row(
|
||||
spacing: 8.0,
|
||||
children: [
|
||||
PangeaLogoSvg(
|
||||
width: 16.0,
|
||||
forceColor: theme.colorScheme.primary,
|
||||
),
|
||||
Text(
|
||||
AppConfig.applicationName,
|
||||
style: theme.textTheme.titleSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
Text(
|
||||
AppConfig.applicationName,
|
||||
style: theme.textTheme.titleSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const Flexible(
|
||||
child: ActivitySuggestionsArea(),
|
||||
),
|
||||
],
|
||||
const ActivitySuggestionsArea(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -113,44 +113,51 @@ class LearningProgressIndicatorsState
|
|||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () => context.go("/rooms/settings"),
|
||||
child: Stack(
|
||||
children: [
|
||||
FutureBuilder<Profile>(
|
||||
future: client.fetchOwnProfile(),
|
||||
builder: (context, snapshot) => Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(99),
|
||||
child: Avatar(
|
||||
mxContent: snapshot.data?.avatarUrl,
|
||||
name: snapshot.data?.displayName ??
|
||||
client.userID!.localpart,
|
||||
size: 60,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 8.0,
|
||||
right: 8.0,
|
||||
),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none, // Allow overflow
|
||||
children: [
|
||||
FutureBuilder<Profile>(
|
||||
future: client.fetchOwnProfile(),
|
||||
builder: (context, snapshot) => Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(99),
|
||||
child: Avatar(
|
||||
mxContent: snapshot.data?.avatarUrl,
|
||||
name: snapshot.data?.displayName ??
|
||||
client.userID!.localpart,
|
||||
size: 60,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: -3,
|
||||
right: -3,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: Theme.of(context).colorScheme.surfaceBright,
|
||||
),
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Icon(
|
||||
size: 14,
|
||||
Icons.settings_outlined,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
weight: 1000,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: -3,
|
||||
right: -3,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: Theme.of(context).colorScheme.surfaceBright,
|
||||
),
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Icon(
|
||||
size: 14,
|
||||
Icons.settings_outlined,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
weight: 1000,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -40,12 +40,6 @@ class BottomNavBarState extends State<BottomNavBar> {
|
|||
return 1;
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant BottomNavBar oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
debugPrint("didUpdateWidget");
|
||||
}
|
||||
|
||||
void onItemTapped(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
|
|
@ -65,87 +59,38 @@ class BottomNavBarState extends State<BottomNavBar> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Theme.of(context).colorScheme.primary.withAlpha(50),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
BottomNavItem(
|
||||
controller: this,
|
||||
icon: Icons.home,
|
||||
child: BottomNavigationBar(
|
||||
iconSize: 16.0,
|
||||
onTap: onItemTapped,
|
||||
selectedItemColor: Theme.of(context).colorScheme.primary,
|
||||
selectedFontSize: 14.0,
|
||||
unselectedFontSize: 14.0,
|
||||
currentIndex: selectedIndex,
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.home_outlined),
|
||||
activeIcon: const Icon(Icons.home),
|
||||
label: L10n.of(context).home,
|
||||
index: 0,
|
||||
),
|
||||
BottomNavItem(
|
||||
controller: this,
|
||||
icon: Icons.chat_bubble_outline,
|
||||
BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.chat_bubble_outline),
|
||||
activeIcon: const Icon(Icons.chat_bubble),
|
||||
label: L10n.of(context).chats,
|
||||
index: 1,
|
||||
),
|
||||
BottomNavItem(
|
||||
controller: this,
|
||||
icon: Icons.settings,
|
||||
BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.settings_outlined),
|
||||
activeIcon: const Icon(Icons.settings),
|
||||
label: L10n.of(context).settings,
|
||||
index: 2,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BottomNavItem extends StatelessWidget {
|
||||
final BottomNavBarState controller;
|
||||
final int index;
|
||||
final IconData icon;
|
||||
final String label;
|
||||
|
||||
const BottomNavItem({
|
||||
required this.controller,
|
||||
required this.index,
|
||||
required this.icon,
|
||||
required this.label,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isSelected = controller.selectedIndex == index;
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () => controller.onItemTapped(index),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 6.0,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.secondaryContainer,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
color: isSelected
|
||||
? theme.colorScheme.onPrimary
|
||||
: theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: isSelected
|
||||
? theme.colorScheme.onPrimary
|
||||
: theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue