mirror of
https://github.com/wgh136/pixes.git
synced 2025-09-27 04:57:23 +00:00
improve mobile ui
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:pixes/components/md.dart';
|
||||
|
||||
void showToast(BuildContext context, {required String message, IconData? icon}) {
|
||||
var newEntry = OverlayEntry(
|
||||
@@ -27,7 +28,7 @@ class ToastOverlay extends StatelessWidget {
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: PhysicalModel(
|
||||
color: Colors.white,
|
||||
color: ColorScheme.of(context).surface,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
elevation: 1,
|
||||
child: Container(
|
||||
@@ -42,8 +43,11 @@ class ToastOverlay extends StatelessWidget {
|
||||
),
|
||||
Text(
|
||||
message,
|
||||
style: const TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.w500),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: ColorScheme.of(context).onSurface
|
||||
),
|
||||
maxLines: 3,
|
||||
),
|
||||
],
|
||||
|
@@ -307,7 +307,7 @@ class SideBarRoute<T> extends PopupRoute<T> {
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Color? get barrierColor => const Color.fromARGB(64, 205, 205, 205);
|
||||
Color? get barrierColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
bool get barrierDismissible => true;
|
||||
@@ -331,7 +331,8 @@ class SideBarRoute<T> extends PopupRoute<T> {
|
||||
color: FluentTheme.of(context).micaBackgroundColor.withOpacity(0.98),
|
||||
borderRadius: const BorderRadius.only(topLeft: Radius.circular(4), bottomLeft: Radius.circular(4))
|
||||
),
|
||||
constraints: const BoxConstraints(maxWidth: _kSideBarWidth),
|
||||
constraints: BoxConstraints(maxWidth: min(_kSideBarWidth,
|
||||
MediaQuery.of(context).size.width)),
|
||||
width: double.infinity,
|
||||
child: child,
|
||||
),
|
||||
|
@@ -31,20 +31,26 @@ class _BookMarkedArtworkPageState extends State<BookMarkedArtworkPage>{
|
||||
}
|
||||
|
||||
Widget buildTab() {
|
||||
return SegmentedButton(
|
||||
options: [
|
||||
SegmentedButtonOption("public", "Public".tl),
|
||||
SegmentedButtonOption("private", "Private".tl),
|
||||
return Row(
|
||||
children: [
|
||||
Text("Following".tl, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 20)),
|
||||
const Spacer(),
|
||||
SegmentedButton(
|
||||
options: [
|
||||
SegmentedButtonOption("public", "Public".tl),
|
||||
SegmentedButtonOption("private", "Private".tl),
|
||||
],
|
||||
onPressed: (key) {
|
||||
if(key != restrict) {
|
||||
setState(() {
|
||||
restrict = key;
|
||||
});
|
||||
}
|
||||
},
|
||||
value: restrict,
|
||||
)
|
||||
],
|
||||
onPressed: (key) {
|
||||
if(key != restrict) {
|
||||
setState(() {
|
||||
restrict = key;
|
||||
});
|
||||
}
|
||||
},
|
||||
value: restrict,
|
||||
).padding(const EdgeInsets.symmetric(vertical: 8, horizontal: 8));
|
||||
).paddingHorizontal(16).paddingVertical(4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +68,7 @@ class _OneBookmarkedPageState extends MultiPageLoadingState<_OneBookmarkedPage,
|
||||
Widget buildContent(BuildContext context, final List<Illust> data) {
|
||||
return LayoutBuilder(builder: (context, constrains){
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
|
@@ -31,21 +31,28 @@ class _FollowingArtworksPageState extends State<FollowingArtworksPage> {
|
||||
}
|
||||
|
||||
Widget buildTab() {
|
||||
return SegmentedButton(
|
||||
options: [
|
||||
SegmentedButtonOption("all", "All".tl),
|
||||
SegmentedButtonOption("public", "Public".tl),
|
||||
SegmentedButtonOption("private", "Private".tl),
|
||||
return Row(
|
||||
children: [
|
||||
Text("Following".tl,
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
|
||||
const Spacer(),
|
||||
SegmentedButton(
|
||||
options: [
|
||||
SegmentedButtonOption("all", "All".tl),
|
||||
SegmentedButtonOption("public", "Public".tl),
|
||||
SegmentedButtonOption("private", "Private".tl),
|
||||
],
|
||||
onPressed: (key) {
|
||||
if(key != restrict) {
|
||||
setState(() {
|
||||
restrict = key;
|
||||
});
|
||||
}
|
||||
},
|
||||
value: restrict,
|
||||
)
|
||||
],
|
||||
onPressed: (key) {
|
||||
if(key != restrict) {
|
||||
setState(() {
|
||||
restrict = key;
|
||||
});
|
||||
}
|
||||
},
|
||||
value: restrict,
|
||||
).padding(const EdgeInsets.symmetric(vertical: 8, horizontal: 8));
|
||||
).paddingHorizontal(16).paddingBottom(4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +70,7 @@ class _OneFollowingPageState extends MultiPageLoadingState<_OneFollowingPage, Il
|
||||
Widget buildContent(BuildContext context, final List<Illust> data) {
|
||||
return LayoutBuilder(builder: (context, constrains){
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart' show Icons;
|
||||
import 'package:pixes/components/animated_image.dart';
|
||||
import 'package:pixes/components/loading.dart';
|
||||
@@ -11,6 +12,7 @@ import 'package:pixes/foundation/image_provider.dart';
|
||||
import 'package:pixes/network/download.dart';
|
||||
import 'package:pixes/network/network.dart';
|
||||
import 'package:pixes/pages/image_page.dart';
|
||||
import 'package:pixes/pages/search_page.dart';
|
||||
import 'package:pixes/pages/user_info_page.dart';
|
||||
import 'package:pixes/utils/translation.dart';
|
||||
|
||||
@@ -65,6 +67,7 @@ class _IllustPageState extends State<IllustPage> {
|
||||
Widget buildBody(double width, double height) {
|
||||
return ListView.builder(
|
||||
itemCount: widget.illust.images.length + 2,
|
||||
padding: EdgeInsets.zero,
|
||||
itemBuilder: (context, index) {
|
||||
return buildImage(width, height, index);
|
||||
});
|
||||
@@ -155,9 +158,7 @@ class _BottomBar extends StatefulWidget {
|
||||
State<_BottomBar> createState() => _BottomBarState();
|
||||
}
|
||||
|
||||
class _BottomBarState extends State<_BottomBar> {
|
||||
double? top;
|
||||
|
||||
class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin{
|
||||
double pageHeight = 0;
|
||||
|
||||
double widgetHeight = 48;
|
||||
@@ -166,36 +167,77 @@ class _BottomBarState extends State<_BottomBar> {
|
||||
|
||||
double _width = 0;
|
||||
|
||||
late VerticalDragGestureRecognizer _recognizer;
|
||||
|
||||
late final AnimationController animationController;
|
||||
|
||||
double get minValue => pageHeight - widgetHeight;
|
||||
double get maxValue => pageHeight - _kBottomBarHeight;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_width = widget.width;
|
||||
pageHeight = widget.height;
|
||||
top = pageHeight - _kBottomBarHeight;
|
||||
Future.delayed(const Duration(milliseconds: 200), () {
|
||||
final box = key.currentContext?.findRenderObject() as RenderBox?;
|
||||
widgetHeight = (box?.size.height) ?? 0;
|
||||
});
|
||||
_recognizer = VerticalDragGestureRecognizer()
|
||||
..onStart = _handlePointerDown
|
||||
..onUpdate = _handlePointerMove
|
||||
..onEnd = _handlePointerUp
|
||||
..onCancel = _handlePointerCancel;
|
||||
animationController = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 180),
|
||||
value: 1
|
||||
);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _handlePointerDown(DragStartDetails details) {}
|
||||
void _handlePointerMove(DragUpdateDetails details) {
|
||||
var offset = details.primaryDelta ?? 0;
|
||||
final minValue = pageHeight - widgetHeight;
|
||||
final maxValue = pageHeight - _kBottomBarHeight;
|
||||
var top = animationController.value * (maxValue - minValue) + minValue;
|
||||
top = (top + offset).clamp(minValue, maxValue);
|
||||
animationController.value = (top - minValue) / (maxValue - minValue);
|
||||
}
|
||||
void _handlePointerUp(DragEndDetails details) {
|
||||
var speed = details.primaryVelocity ?? 0;
|
||||
const minShouldTransitionSpeed = 1000;
|
||||
if(speed > minShouldTransitionSpeed) {
|
||||
animationController.forward();
|
||||
} else if(speed < minShouldTransitionSpeed) {
|
||||
animationController.reverse();
|
||||
} else {
|
||||
_handlePointerCancel();
|
||||
}
|
||||
}
|
||||
void _handlePointerCancel() {
|
||||
if(animationController.value >= 0.5 ) {
|
||||
animationController.forward();
|
||||
} else {
|
||||
animationController.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant _BottomBar oldWidget) {
|
||||
if (widget.height != pageHeight) {
|
||||
setState(() {
|
||||
pageHeight = widget.height;
|
||||
top = pageHeight - _kBottomBarHeight;
|
||||
});
|
||||
}
|
||||
_recognizer.dispose();
|
||||
if(_width != widget.width) {
|
||||
_width = widget.width;
|
||||
Future.microtask(() {
|
||||
final box = key.currentContext?.findRenderObject() as RenderBox?;
|
||||
var oldHeight = widgetHeight;
|
||||
widgetHeight = (box?.size.height) ?? 0;
|
||||
if(oldHeight != widgetHeight && top != pageHeight - _kBottomBarHeight) {
|
||||
setState(() {
|
||||
top = pageHeight - widgetHeight;
|
||||
});
|
||||
if(oldHeight != widgetHeight) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -204,32 +246,44 @@ class _BottomBarState extends State<_BottomBar> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedPositioned(
|
||||
top: top,
|
||||
left: 0,
|
||||
right: 0,
|
||||
duration: const Duration(milliseconds: 180),
|
||||
curve: Curves.ease,
|
||||
child: Card(
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(8)),
|
||||
backgroundColor:
|
||||
FluentTheme.of(context).micaBackgroundColor.withOpacity(0.96),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
key: key,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildTop(),
|
||||
buildStats(),
|
||||
buildTags(),
|
||||
SelectableText("${"Artwork ID".tl}: ${widget.illust.id}\n${"Artist ID".tl}: ${widget.illust.author.id}", style: TextStyle(color: ColorScheme.of(context).outline),).paddingLeft(4),
|
||||
const SizedBox(height: 8,)
|
||||
],
|
||||
),
|
||||
),
|
||||
return AnimatedBuilder(
|
||||
animation: CurvedAnimation(
|
||||
parent: animationController,
|
||||
curve: Curves.ease,
|
||||
reverseCurve: Curves.ease,
|
||||
),
|
||||
builder: (context, child) {
|
||||
return Positioned(
|
||||
top: minValue + (maxValue - minValue) * animationController.value,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Listener(
|
||||
onPointerDown: (event) {
|
||||
_recognizer.addPointer(event);
|
||||
},
|
||||
child: Card(
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(8)),
|
||||
backgroundColor:
|
||||
FluentTheme.of(context).micaBackgroundColor.withOpacity(0.96),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
key: key,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildTop(),
|
||||
buildStats(),
|
||||
buildTags(),
|
||||
SelectableText("${"Artwork ID".tl}: ${widget.illust.id}\n${"Artist ID".tl}: ${widget.illust.author.id}", style: TextStyle(color: ColorScheme.of(context).outline),).paddingLeft(4),
|
||||
const SizedBox(height: 8,)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -243,21 +297,17 @@ class _BottomBarState extends State<_BottomBar> {
|
||||
buildAuthor(),
|
||||
...buildActions(constrains.maxWidth),
|
||||
const Spacer(),
|
||||
if (top == pageHeight - _kBottomBarHeight)
|
||||
if (animationController.value == 1)
|
||||
IconButton(
|
||||
icon: const Icon(FluentIcons.up),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
top = pageHeight - widgetHeight;
|
||||
});
|
||||
animationController.reverse();
|
||||
})
|
||||
else
|
||||
IconButton(
|
||||
icon: const Icon(FluentIcons.down),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
top = pageHeight - _kBottomBarHeight;
|
||||
});
|
||||
animationController.forward();
|
||||
})
|
||||
],
|
||||
);
|
||||
@@ -287,14 +337,15 @@ class _BottomBarState extends State<_BottomBar> {
|
||||
});
|
||||
}
|
||||
|
||||
final bool showUserName = MediaQuery.of(context).size.width > 640;
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
backgroundColor: FluentTheme.of(context).cardColor.withOpacity(0.72),
|
||||
child: SizedBox(
|
||||
height: double.infinity,
|
||||
width: 246,
|
||||
width: showUserName ? 246 : 128,
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
@@ -325,12 +376,13 @@ class _BottomBarState extends State<_BottomBar> {
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
widget.illust.author.name,
|
||||
maxLines: 2,
|
||||
if(showUserName)
|
||||
Expanded(
|
||||
child: Text(
|
||||
widget.illust.author.name,
|
||||
maxLines: 2,
|
||||
),
|
||||
),
|
||||
),
|
||||
if(isFollowing)
|
||||
Button(onPressed: follow, child: const SizedBox(
|
||||
width: 42,
|
||||
@@ -343,11 +395,14 @@ class _BottomBarState extends State<_BottomBar> {
|
||||
),
|
||||
))
|
||||
else if (!widget.illust.author.isFollowed)
|
||||
Button(onPressed: follow, child: Text("Follow".tl))
|
||||
Button(onPressed: follow, child: Text("Follow".tl).fixWidth(56))
|
||||
else
|
||||
Button(
|
||||
onPressed: follow,
|
||||
child: Text("Unfollow".tl, style: TextStyle(color: ColorScheme.of(context).error),),
|
||||
child: Text(
|
||||
"Unfollow".tl,
|
||||
style: TextStyle(color: ColorScheme.of(context).error),
|
||||
).fixWidth(56),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -558,9 +613,17 @@ class _BottomBarState extends State<_BottomBar> {
|
||||
if(e.translatedName != null && e.name != e.translatedName) {
|
||||
text += "/${e.translatedName}";
|
||||
}
|
||||
return Card(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
|
||||
child: Text(text, style: const TextStyle(fontSize: 13),),
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.to(() => SearchResultPage(e.name));
|
||||
},
|
||||
child: Card(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
|
||||
child: Text(text, style: const TextStyle(fontSize: 13),),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
@@ -601,10 +664,11 @@ class _CommentsPageState extends MultiPageLoadingState<_CommentsPage, Comment> {
|
||||
|
||||
Widget buildBody(BuildContext context, List<Comment> data) {
|
||||
return ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: data.length + 2,
|
||||
itemBuilder: (context, index) {
|
||||
if(index == 0) {
|
||||
return Text("Comments".tl, style: const TextStyle(fontSize: 20)).paddingVertical(8).paddingHorizontal(12);
|
||||
return Text("Comments".tl, style: const TextStyle(fontSize: 20)).paddingVertical(16).paddingHorizontal(12);
|
||||
} else if(index == data.length + 1) {
|
||||
return const SizedBox(height: 64,);
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ import "package:window_manager/window_manager.dart";
|
||||
import "../components/page_route.dart";
|
||||
import "downloading_page.dart";
|
||||
|
||||
const _kAppBarHeight = 36.0;
|
||||
double get _appBarHeight => App.isDesktop ? 36.0 : 48.0;
|
||||
|
||||
class MainPage extends StatefulWidget {
|
||||
const MainPage({super.key});
|
||||
@@ -143,11 +143,14 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
||||
),
|
||||
],
|
||||
),
|
||||
paneBodyBuilder: (pane, child) => Navigator(
|
||||
key: navigatorKey,
|
||||
onGenerateRoute: (settings) => AppPageRoute(
|
||||
builder: (context) => const RecommendationPage()),
|
||||
)),
|
||||
paneBodyBuilder: (pane, child) => NavigatorPopHandler(
|
||||
key: const Key("navigator"),
|
||||
onPop: () => navigatorKey.currentState?.pop(),
|
||||
child: Navigator(
|
||||
key: navigatorKey,
|
||||
onGenerateRoute: (settings) => AppPageRoute(
|
||||
builder: (context) => const RecommendationPage()),
|
||||
))),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -176,7 +179,7 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
||||
BuildContext context, GlobalKey<NavigatorState> navigatorKey) {
|
||||
return NavigationAppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
height: _kAppBarHeight,
|
||||
height: _appBarHeight,
|
||||
title: () {
|
||||
if (!App.isDesktop) {
|
||||
return const Align(
|
||||
@@ -198,9 +201,9 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
||||
);
|
||||
}(),
|
||||
leading: _BackButton(navigatorKey),
|
||||
actions: WindowButtons(
|
||||
actions: App.isDesktop ? WindowButtons(
|
||||
key: ValueKey(windowButtonKey),
|
||||
),
|
||||
) : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -298,7 +301,7 @@ class WindowButtons extends StatelessWidget {
|
||||
|
||||
return SizedBox(
|
||||
width: 138,
|
||||
height: _kAppBarHeight,
|
||||
height: _appBarHeight,
|
||||
child: Row(
|
||||
children: [
|
||||
WindowButton(
|
||||
|
@@ -67,7 +67,7 @@ class _RankingPageState extends State<RankingPage> {
|
||||
)
|
||||
],
|
||||
)
|
||||
).padding(const EdgeInsets.symmetric(vertical: 8, horizontal: 12));
|
||||
).padding(const EdgeInsets.symmetric(vertical: 8, horizontal: 16));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ class _OneRankingPageState extends MultiPageLoadingState<_OneRankingPage, Illust
|
||||
Widget buildContent(BuildContext context, final List<Illust> data) {
|
||||
return LayoutBuilder(builder: (context, constrains){
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
|
@@ -35,20 +35,29 @@ class _RecommendationPageState extends State<RecommendationPage> {
|
||||
}
|
||||
|
||||
Widget buildTab() {
|
||||
return SegmentedButton<int>(
|
||||
options: [
|
||||
SegmentedButtonOption(0, "Artworks".tl),
|
||||
SegmentedButtonOption(1, "Users".tl),
|
||||
],
|
||||
onPressed: (key) {
|
||||
if(key != type) {
|
||||
setState(() {
|
||||
type = key;
|
||||
});
|
||||
}
|
||||
},
|
||||
value: type,
|
||||
).padding(const EdgeInsets.symmetric(vertical: 8, horizontal: 8));
|
||||
return SizedBox(
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Explore".tl,
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
|
||||
const Spacer(),
|
||||
SegmentedButton<int>(
|
||||
options: [
|
||||
SegmentedButtonOption(0, "Artworks".tl),
|
||||
SegmentedButtonOption(1, "Users".tl),
|
||||
],
|
||||
onPressed: (key) {
|
||||
if(key != type) {
|
||||
setState(() {
|
||||
type = key;
|
||||
});
|
||||
}
|
||||
},
|
||||
value: type,
|
||||
)
|
||||
],
|
||||
).paddingHorizontal(16).paddingBottom(4),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +74,7 @@ class _RecommendationArtworksPageState extends MultiPageLoadingState<_Recommenda
|
||||
Widget buildContent(BuildContext context, final List<Illust> data) {
|
||||
return LayoutBuilder(builder: (context, constrains){
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
|
@@ -58,6 +58,7 @@ class _SearchPageState extends State<SearchPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ScaffoldPage(
|
||||
padding: EdgeInsets.zero,
|
||||
content: Column(
|
||||
children: [
|
||||
buildSearchBar(),
|
||||
@@ -171,6 +172,7 @@ class _TrendingTagsViewState extends LoadingState<_TrendingTagsView, List<Trendi
|
||||
@override
|
||||
Widget buildContent(BuildContext context, List<TrendingTag> data) {
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
|
@@ -77,6 +77,7 @@ class _UserInfoPageState extends LoadingState<UserInfoPage, UserDetails> {
|
||||
image: CachedImageProvider(data!.avatar),
|
||||
width: 64,
|
||||
height: 64,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),),
|
||||
const SizedBox(height: 8),
|
||||
|
Reference in New Issue
Block a user