Skip to content

Commit 77a5e25

Browse files
robelatorclaude
andcommitted
+Update and format
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8043acf commit 77a5e25

22 files changed

Lines changed: 396 additions & 222 deletions

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
[![banner](https://github.com/dev-cetera/df_screen/blob/v0.8.13/doc/assets/banner.png?raw=true)](https://github.com/dev-cetera)
1+
[![banner](https://github.com/dev-cetera/df_screen/blob/v0.8.15/doc/assets/banner.png?raw=true)](https://github.com/dev-cetera)
22

33
[![pub](https://img.shields.io/pub/v/df_screen.svg)](https://pub.dev/packages/df_screen)
4-
[![tag](https://img.shields.io/badge/Tag-v0.8.13-purple?logo=github)](https://github.com/dev-cetera/df_screen/tree/v0.8.13)
4+
[![tag](https://img.shields.io/badge/Tag-v0.8.15-purple?logo=github)](https://github.com/dev-cetera/df_screen/tree/v0.8.15)
55
[![buymeacoffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-FFDD00?logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/dev_cetera)
66
[![sponsor](https://img.shields.io/badge/Sponsor-grey?logo=github-sponsors&logoColor=pink)](https://github.com/sponsors/dev-cetera)
77
[![patreon](https://img.shields.io/badge/Patreon-grey?logo=patreon)](https://www.patreon.com/robelator)
@@ -15,7 +15,7 @@
1515

1616
## Summary
1717

18-
A package that provides a useful screen widget andcontroller for Flutter apps.
18+
A package that provides a useful screen widget and controller for Flutter apps.
1919

2020
<!-- END _README_CONTENT -->
2121

_README_CONTENT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
## Summary
22

3-
A package that provides a useful screen widget andcontroller for Flutter apps.
3+
A package that provides a useful screen widget and controller for Flutter apps.

analysis_options.yaml

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
1-
##.title
2-
## ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
3-
##
4-
## Copyright © dev-cetera.com & contributors.
5-
##
6-
## The use of this source code is governed by an MIT-style license described in
7-
## the LICENSE file located in this project's root directory.
8-
##
9-
## See: https://opensource.org/license/mit
10-
##
11-
## ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
12-
##.title~
1+
# For dev-cetera.com
2+
# Version: Flutter-1
133

144
include: package:flutter_lints/flutter.yaml
155

@@ -31,6 +21,7 @@ linter:
3121
prefer_relative_imports: true
3222
prefer_single_quotes: true
3323
require_trailing_commas: true
24+
unawaited_futures: true
3425
unnecessary_this: true
3526

3627
analyzer:
@@ -42,22 +33,27 @@ analyzer:
4233
strict-raw-types: true
4334
exclude:
4435
- build/**
36+
# - '**.g.dart'
4537

4638
errors:
47-
unused_label: ignore
4839
always_declare_return_types: error
4940
avoid_renaming_method_parameters: error
5041
avoid_type_to_string: error
42+
close_sinks: error
43+
collection_methods_unrelated_type: error
5144
depend_on_referenced_packages: error
5245
flutter_style_todos: error
5346
invalid_override_of_non_virtual_member: error
5447
invalid_use_of_protected_member: error
48+
missing_return: error
5549
no_leading_underscores_for_local_identifiers: error
5650
prefer_final_in_for_each: error
5751
prefer_relative_imports: error
52+
record_literal_one_positional_no_trailing_comma: error
5853
unnecessary_new: error
5954
unrelated_type_equality_checks: error
55+
unused_label: ignore
6056
use_key_in_widget_constructors: error
6157

6258
formatter:
63-
trailing_commas: preserve
59+
trailing_commas: preserve

example/lib/example_3.dart

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
import 'package:df_screen/df_screen.dart';
2+
import 'package:flutter/material.dart';
3+
4+
void main() {
5+
runApp(
6+
const MaterialApp(
7+
debugShowCheckedModeBanner: false,
8+
home: Material(child: OverlayExampleScreen()),
9+
),
10+
);
11+
}
12+
13+
/// 1. THE SCREEN
14+
base class OverlayExampleScreen extends Screen {
15+
const OverlayExampleScreen({super.key});
16+
17+
@override
18+
State createState() => _OverlayExampleScreenState();
19+
20+
@override
21+
ScreenController createController(Screen screen, ScreenState state) {
22+
return OverlayExampleController(screen, state);
23+
}
24+
}
25+
26+
/// 2. THE CONTROLLER (Business Logic)
27+
final class OverlayExampleController extends ScreenController {
28+
OverlayExampleController(super.screen, super.state);
29+
30+
void onActionPressed() {
31+
print("Action button tapped!");
32+
}
33+
}
34+
35+
/// 3. THE STATE (UI & Adaptive Layout)
36+
final class _OverlayExampleScreenState extends AdaptiveScreenState<
37+
OverlayExampleScreen, OverlayExampleController> {
38+
// Use OVERLAY so the body content scrolls behind the header/footer
39+
@override
40+
AdaptiveScreenSideMode get topSideMode => AdaptiveScreenSideMode.OVERLAY;
41+
42+
@override
43+
AdaptiveScreenSideMode get bottomSideMode => AdaptiveScreenSideMode.OVERLAY;
44+
45+
// By setting these, the framework avoids "layout jumps" on the first frame
46+
@override
47+
double get minTopSideSize => 80.0;
48+
@override
49+
double get minBottomSideSize => 90.0;
50+
51+
/// THE HEADER (TopSide)
52+
@override
53+
Widget topSide(BuildContext context, double topInsets) {
54+
return PreferredSize(
55+
preferredSize: Size.fromHeight(minTopSideSize + topInsets),
56+
child: Container(
57+
margin: const EdgeInsets.all(12),
58+
decoration: BoxDecoration(
59+
// Glassmorphism effect
60+
color: Colors.white.withAlpha(200),
61+
borderRadius: BorderRadius.circular(16),
62+
boxShadow: [
63+
BoxShadow(
64+
color: Colors.black.withAlpha(20),
65+
blurRadius: 10,
66+
offset: const Offset(0, 4),
67+
)
68+
],
69+
),
70+
child: SafeArea(
71+
bottom: false,
72+
child: ListTile(
73+
leading: const CircleAvatar(
74+
backgroundColor: Colors.indigo,
75+
child: Icon(Icons.person, color: Colors.white)),
76+
title: const Text('Hello, Explorer',
77+
style: TextStyle(fontWeight: FontWeight.bold)),
78+
subtitle: const Text('Welcome back!'),
79+
trailing: IconButton(
80+
icon: const Icon(Icons.notifications_none),
81+
onPressed: c.onActionPressed,
82+
),
83+
),
84+
),
85+
),
86+
);
87+
}
88+
89+
/// THE NAVIGATION BAR (BottomSide)
90+
@override
91+
Widget bottomSide(BuildContext context, double bottomInsets) {
92+
return PreferredSize(
93+
preferredSize: Size.fromHeight(minBottomSideSize + bottomInsets),
94+
child: Container(
95+
padding: EdgeInsets.only(
96+
bottom: bottomInsets + 10, left: 20, right: 20, top: 10),
97+
child: Container(
98+
height: 60,
99+
decoration: BoxDecoration(
100+
color: Colors.indigo.shade900,
101+
borderRadius: BorderRadius.circular(30),
102+
boxShadow: const [BoxShadow(color: Colors.black45, blurRadius: 20)],
103+
),
104+
child: Row(
105+
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
106+
children: [
107+
_navIcon(Icons.home, true),
108+
_navIcon(Icons.search, false),
109+
_navIcon(Icons.favorite_border, false),
110+
_navIcon(Icons.settings, false),
111+
],
112+
),
113+
),
114+
),
115+
);
116+
}
117+
118+
Widget _navIcon(IconData icon, bool active) {
119+
return Icon(icon, color: active ? Colors.white : Colors.white54, size: 28);
120+
}
121+
122+
/// THE MAIN CONTENT
123+
@override
124+
Widget body(BuildContext context) {
125+
return ListView.builder(
126+
// CRITICAL: Use the built-in controller for synchronized animations
127+
controller: bodyScrollController,
128+
// Add padding so the first/last items aren't hidden under the overlays
129+
padding: EdgeInsets.only(
130+
top: minTopSideSize + 30,
131+
bottom: minBottomSideSize + 20,
132+
left: 16,
133+
right: 16,
134+
),
135+
itemCount: 25,
136+
itemBuilder: (context, index) {
137+
return Card(
138+
margin: const EdgeInsets.only(bottom: 12),
139+
shape:
140+
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
141+
child: Container(
142+
height: 100,
143+
padding: const EdgeInsets.all(16),
144+
child: Row(
145+
children: [
146+
Container(
147+
width: 60,
148+
decoration: BoxDecoration(
149+
color: Colors.indigo.withAlpha(30),
150+
borderRadius: BorderRadius.circular(8),
151+
),
152+
child: Center(
153+
child: Text('#$index',
154+
style: const TextStyle(fontWeight: FontWeight.bold))),
155+
),
156+
const SizedBox(width: 16),
157+
const Expanded(
158+
child: Column(
159+
mainAxisAlignment: MainAxisAlignment.center,
160+
crossAxisAlignment: CrossAxisAlignment.start,
161+
children: [
162+
Text('Adaptive Overlay Card',
163+
style: TextStyle(fontWeight: FontWeight.bold)),
164+
Text('Scroll behind the floating bars...',
165+
style: TextStyle(color: Colors.grey)),
166+
],
167+
),
168+
)
169+
],
170+
),
171+
),
172+
);
173+
},
174+
);
175+
}
176+
177+
// Set the background color for the whole screen
178+
@override
179+
Widget background(BuildContext context) {
180+
return Container(color: Colors.grey.shade100);
181+
}
182+
}

example/pubspec.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ dependencies:
1818
sdk: flutter
1919
df_screen:
2020
path: ../
21-
df_widgets:
22-
path: ../../df_widgets
2321

2422
cupertino_icons: ^1.0.8
2523

lib/src/_utils/current_platform.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import 'package:device_info_plus/device_info_plus.dart' as device_info_plus;
1919

2020
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
2121

22+
const _MOBILE_MAX_WIDTH = 550.0;
23+
2224
class CurrentPlatform {
2325
//
2426
//
@@ -108,9 +110,13 @@ class CurrentPlatform {
108110
static bool get isDesktop => isOsWindows || isOsMacOs || isOsLinux;
109111

110112
static bool get isWindowSizeMobile {
111-
final firstView = WidgetsBinding.instance.platformDispatcher.views.first;
113+
final firstView =
114+
WidgetsBinding.instance.platformDispatcher.views.firstOrNull;
115+
if (firstView == null) {
116+
throw StateError('No platform views available.');
117+
}
112118
final data = MediaQueryData.fromView(firstView);
113-
return data.size.shortestSide < 550.0;
119+
return data.size.shortestSide < _MOBILE_MAX_WIDTH;
114120
}
115121

116122
static bool get isWindowSizeTabletOrDesktop => !isWindowSizeMobile;

lib/src/_utils/screen_calculator.dart

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -96,29 +96,29 @@ const MIN_MOBILE_ASPECT_RATIO = 4.0 / 3.0;
9696

9797
/// The smallest of the following common aspect ratios for mobile phones (4.0 / 3.0)
9898
double get minMobileAspectRatio => {
99-
// Samsungs
100-
16.0 / 10.0,
101-
// Pixels, Samsungs
102-
16.0 / 9.0,
103-
// Pixels, most iPhones before 2018
104-
18.0 / 9.0,
105-
// Pixels
106-
18.5 / 9.0,
107-
18.7 / 9.0,
108-
19.0 / 10.0,
109-
// Pixels
110-
19.0 / 9.0,
111-
// Pixels and most iPhones after 2018
112-
19.5 / 9.0,
113-
3.0 / 2.0,
114-
// Old iPhones, and many tablets!
115-
4.0 / 3.0,
116-
5.0 / 3.0,
117-
// Samsungs
118-
2.10 / 1,
119-
20.0 / 9.0,
120-
193 / 90,
121-
}.reduce((a, b) => a <= b ? a : b);
99+
// Samsungs
100+
16.0 / 10.0,
101+
// Pixels, Samsungs
102+
16.0 / 9.0,
103+
// Pixels, most iPhones before 2018
104+
18.0 / 9.0,
105+
// Pixels
106+
18.5 / 9.0,
107+
18.7 / 9.0,
108+
19.0 / 10.0,
109+
// Pixels
110+
19.0 / 9.0,
111+
// Pixels and most iPhones after 2018
112+
19.5 / 9.0,
113+
3.0 / 2.0,
114+
// Old iPhones, and many tablets!
115+
4.0 / 3.0,
116+
5.0 / 3.0,
117+
// Samsungs
118+
2.10 / 1,
119+
20.0 / 9.0,
120+
193 / 90,
121+
}.reduce((a, b) => a <= b ? a : b);
122122

123123
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
124124

lib/src/_utils/surface.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,19 @@ class Surface extends StatelessWidget {
5151

5252
@override
5353
Widget build(BuildContext context) {
54-
final $color =
54+
final color1 =
5555
decoration?.color ?? color ?? Theme.of(context).colorScheme.surface;
56-
final $borderRadius = decoration?.borderRadius ?? borderRadius;
57-
final $decoration =
58-
decoration?.copyWith(color: $color, borderRadius: $borderRadius) ??
59-
BoxDecoration(color: $color, borderRadius: $borderRadius);
56+
final borderRadius1 = decoration?.borderRadius ?? borderRadius;
57+
final decoration1 =
58+
decoration?.copyWith(color: color1, borderRadius: borderRadius1) ??
59+
BoxDecoration(color: color1, borderRadius: borderRadius1);
6060
return ClipRRect(
61-
borderRadius: $borderRadius,
61+
borderRadius: borderRadius1,
6262
child: Container(
6363
width: width,
6464
height: height,
6565
constraints: constraints,
66-
decoration: $decoration,
66+
decoration: decoration1,
6767
padding: padding ?? EdgeInsets.zero,
6868
child: child,
6969
),

lib/src/_utils/view_insets_builder.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,11 @@ class _State extends State<ViewInsetsBuilder> with WidgetsBindingObserver {
9898

9999
void _updateViewInsets() {
100100
final viewInsets = View.of(context).viewInsets;
101-
final reachedMax =
102-
viewInsets.top > _viewInsets.top ||
101+
final reachedMax = viewInsets.top > _viewInsets.top ||
103102
viewInsets.bottom > _viewInsets.bottom ||
104103
viewInsets.left > _viewInsets.left ||
105104
viewInsets.right > _viewInsets.right;
106-
final reachedMin =
107-
viewInsets.top == 0 &&
105+
final reachedMin = viewInsets.top == 0 &&
108106
viewInsets.bottom == 0 &&
109107
viewInsets.left == 0 &&
110108
viewInsets.right == 0;

0 commit comments

Comments
 (0)