mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-03-22 23:19:21 +01:00
Add fade out effect also to nav bar settings page
This commit is contained in:
parent
78c02fd280
commit
058a8d38af
5 changed files with 171 additions and 116 deletions
118
app/lib/widget/fade_out_list.dart
Normal file
118
app/lib/widget/fade_out_list.dart
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class FadeOutListContainer extends StatefulWidget {
|
||||||
|
const FadeOutListContainer({
|
||||||
|
super.key,
|
||||||
|
required this.scrollController,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _FadeOutListContainerState();
|
||||||
|
|
||||||
|
final ScrollController scrollController;
|
||||||
|
final Widget child;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FadeOutListContainerState extends State<FadeOutListContainer> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
widget.scrollController.addListener(_onScrollEvent);
|
||||||
|
_ensureUpdateButtonScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
widget.scrollController.removeListener(_onScrollEvent);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ShaderMask(
|
||||||
|
shaderCallback: (rect) {
|
||||||
|
final colors = <Color>[];
|
||||||
|
final stops = <double>[];
|
||||||
|
if (_hasLeftContent) {
|
||||||
|
colors.addAll([Colors.white, Colors.transparent]);
|
||||||
|
stops.addAll([0, .1]);
|
||||||
|
} else {
|
||||||
|
colors.add(Colors.transparent);
|
||||||
|
stops.add(0);
|
||||||
|
}
|
||||||
|
if (_hasRightContent) {
|
||||||
|
colors.addAll([Colors.transparent, Colors.white]);
|
||||||
|
stops.addAll([.9, 1]);
|
||||||
|
} else {
|
||||||
|
colors.add(Colors.transparent);
|
||||||
|
stops.add(1);
|
||||||
|
}
|
||||||
|
return LinearGradient(
|
||||||
|
begin: Alignment.centerLeft,
|
||||||
|
end: Alignment.centerRight,
|
||||||
|
colors: colors,
|
||||||
|
stops: stops,
|
||||||
|
).createShader(rect);
|
||||||
|
},
|
||||||
|
blendMode: BlendMode.dstOut,
|
||||||
|
child: widget.child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onScrollEvent() {
|
||||||
|
_updateButtonScroll(widget.scrollController.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _updateButtonScroll(ScrollPosition pos) {
|
||||||
|
if (!pos.hasContentDimensions || !pos.hasPixels) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pos.pixels <= pos.minScrollExtent) {
|
||||||
|
if (_hasLeftContent) {
|
||||||
|
setState(() {
|
||||||
|
_hasLeftContent = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!_hasLeftContent) {
|
||||||
|
setState(() {
|
||||||
|
_hasLeftContent = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pos.pixels >= pos.maxScrollExtent) {
|
||||||
|
if (_hasRightContent) {
|
||||||
|
setState(() {
|
||||||
|
_hasRightContent = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!_hasRightContent) {
|
||||||
|
setState(() {
|
||||||
|
_hasRightContent = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_hasFirstScrollUpdate = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ensureUpdateButtonScroll() {
|
||||||
|
if (_hasFirstScrollUpdate || !mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (widget.scrollController.hasClients) {
|
||||||
|
if (_updateButtonScroll(widget.scrollController.position)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Timer(const Duration(milliseconds: 100), _ensureUpdateButtonScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
var _hasFirstScrollUpdate = false;
|
||||||
|
var _hasLeftContent = false;
|
||||||
|
var _hasRightContent = false;
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ import 'package:nc_photos/widget/archive_browser.dart';
|
||||||
import 'package:nc_photos/widget/collection_browser.dart';
|
import 'package:nc_photos/widget/collection_browser.dart';
|
||||||
import 'package:nc_photos/widget/collection_grid_item.dart';
|
import 'package:nc_photos/widget/collection_grid_item.dart';
|
||||||
import 'package:nc_photos/widget/enhanced_photo_browser.dart';
|
import 'package:nc_photos/widget/enhanced_photo_browser.dart';
|
||||||
|
import 'package:nc_photos/widget/fade_out_list.dart';
|
||||||
import 'package:nc_photos/widget/handler/double_tap_exit_handler.dart';
|
import 'package:nc_photos/widget/handler/double_tap_exit_handler.dart';
|
||||||
import 'package:nc_photos/widget/home_app_bar.dart';
|
import 'package:nc_photos/widget/home_app_bar.dart';
|
||||||
import 'package:nc_photos/widget/navigation_bar_blur_filter.dart';
|
import 'package:nc_photos/widget/navigation_bar_blur_filter.dart';
|
||||||
|
|
|
@ -20,15 +20,6 @@ class _NavigationBar extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NavigationBarState extends State<_NavigationBar> {
|
class _NavigationBarState extends State<_NavigationBar> {
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_scrollController = ScrollController();
|
|
||||||
_scrollController
|
|
||||||
.addListener(() => _updateButtonScroll(_scrollController.position));
|
|
||||||
_ensureUpdateButtonScroll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_scrollController.dispose();
|
_scrollController.dispose();
|
||||||
|
@ -42,32 +33,8 @@ class _NavigationBarState extends State<_NavigationBar> {
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ShaderMask(
|
child: FadeOutListContainer(
|
||||||
shaderCallback: (rect) {
|
scrollController: _scrollController,
|
||||||
final colors = <Color>[];
|
|
||||||
final stops = <double>[];
|
|
||||||
if (_hasLeftContent) {
|
|
||||||
colors.addAll([Colors.white, Colors.transparent]);
|
|
||||||
stops.addAll([0, .1]);
|
|
||||||
} else {
|
|
||||||
colors.add(Colors.transparent);
|
|
||||||
stops.add(0);
|
|
||||||
}
|
|
||||||
if (_hasRightContent) {
|
|
||||||
colors.addAll([Colors.transparent, Colors.white]);
|
|
||||||
stops.addAll([.9, 1]);
|
|
||||||
} else {
|
|
||||||
colors.add(Colors.transparent);
|
|
||||||
stops.add(1);
|
|
||||||
}
|
|
||||||
return LinearGradient(
|
|
||||||
begin: Alignment.centerLeft,
|
|
||||||
end: Alignment.centerRight,
|
|
||||||
colors: colors,
|
|
||||||
stops: stops,
|
|
||||||
).createShader(rect);
|
|
||||||
},
|
|
||||||
blendMode: BlendMode.dstOut,
|
|
||||||
child: _BlocSelector(
|
child: _BlocSelector(
|
||||||
selector: (state) => state.navBarButtons,
|
selector: (state) => state.navBarButtons,
|
||||||
builder: (context, navBarButtons) {
|
builder: (context, navBarButtons) {
|
||||||
|
@ -112,56 +79,7 @@ class _NavigationBarState extends State<_NavigationBar> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _updateButtonScroll(ScrollPosition pos) {
|
final _scrollController = ScrollController();
|
||||||
if (!pos.hasContentDimensions || !pos.hasPixels) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (pos.pixels <= pos.minScrollExtent) {
|
|
||||||
if (_hasLeftContent) {
|
|
||||||
setState(() {
|
|
||||||
_hasLeftContent = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!_hasLeftContent) {
|
|
||||||
setState(() {
|
|
||||||
_hasLeftContent = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pos.pixels >= pos.maxScrollExtent) {
|
|
||||||
if (_hasRightContent) {
|
|
||||||
setState(() {
|
|
||||||
_hasRightContent = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!_hasRightContent) {
|
|
||||||
setState(() {
|
|
||||||
_hasRightContent = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_hasFirstScrollUpdate = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _ensureUpdateButtonScroll() {
|
|
||||||
if (_hasFirstScrollUpdate || !mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (_scrollController.hasClients) {
|
|
||||||
if (_updateButtonScroll(_scrollController.position)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Timer(const Duration(milliseconds: 100), _ensureUpdateButtonScroll);
|
|
||||||
}
|
|
||||||
|
|
||||||
late final ScrollController _scrollController;
|
|
||||||
var _hasFirstScrollUpdate = false;
|
|
||||||
var _hasLeftContent = false;
|
|
||||||
var _hasRightContent = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NavBarButtonIndicator extends StatelessWidget {
|
class _NavBarButtonIndicator extends StatelessWidget {
|
||||||
|
|
|
@ -1,8 +1,19 @@
|
||||||
part of '../collections_nav_bar_settings.dart';
|
part of '../collections_nav_bar_settings.dart';
|
||||||
|
|
||||||
class _DemoView extends StatelessWidget {
|
class _DemoView extends StatefulWidget {
|
||||||
const _DemoView();
|
const _DemoView();
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _DemoViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DemoViewState extends State<_DemoView> {
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_scrollController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return _BlocSelector(
|
return _BlocSelector(
|
||||||
|
@ -13,7 +24,10 @@ class _DemoView extends StatelessWidget {
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
child: FadeOutListContainer(
|
||||||
|
scrollController: _scrollController,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
|
controller: _scrollController,
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
padding: const EdgeInsets.only(left: 16 - 6),
|
padding: const EdgeInsets.only(left: 16 - 6),
|
||||||
itemCount: buttons.length,
|
itemCount: buttons.length,
|
||||||
|
@ -47,6 +61,7 @@ class _DemoView extends StatelessWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
const _NewButton(),
|
const _NewButton(),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
|
@ -81,6 +96,8 @@ class _DemoView extends StatelessWidget {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final _scrollController = ScrollController();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DemoButtonDelegate extends StatelessWidget {
|
class _DemoButtonDelegate extends StatelessWidget {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import 'package:nc_photos/exception_event.dart';
|
||||||
import 'package:nc_photos/k.dart' as k;
|
import 'package:nc_photos/k.dart' as k;
|
||||||
import 'package:nc_photos/snack_bar_manager.dart';
|
import 'package:nc_photos/snack_bar_manager.dart';
|
||||||
import 'package:nc_photos/widget/draggable.dart' as my;
|
import 'package:nc_photos/widget/draggable.dart' as my;
|
||||||
|
import 'package:nc_photos/widget/fade_out_list.dart';
|
||||||
import 'package:nc_photos/widget/home_collections.dart';
|
import 'package:nc_photos/widget/home_collections.dart';
|
||||||
import 'package:nc_photos/widget/page_visibility_mixin.dart';
|
import 'package:nc_photos/widget/page_visibility_mixin.dart';
|
||||||
import 'package:np_codegen/np_codegen.dart';
|
import 'package:np_codegen/np_codegen.dart';
|
||||||
|
|
Loading…
Reference in a new issue