mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
[infra_ui][overlay] (WIP) Temp submit before refactor
This commit is contained in:
parent
ae45e64244
commit
7efbf03030
@ -1,4 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../overlay/overlay_screen.dart';
|
||||
import '../keyboard/keyboard_screen.dart';
|
||||
import 'demo_item.dart';
|
||||
|
||||
@ -8,6 +10,7 @@ class HomeScreen extends StatelessWidget {
|
||||
static List<ListItem> items = [
|
||||
SectionHeaderItem('Widget Demos'),
|
||||
KeyboardItem(),
|
||||
OverlayItem(),
|
||||
];
|
||||
|
||||
@override
|
||||
|
@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../home/demo_item.dart';
|
||||
|
||||
class OverlayItem extends DemoItem {
|
||||
@override
|
||||
String buildTitle() => 'Overlay';
|
||||
|
||||
@override
|
||||
void handleTap(BuildContext context) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const OverlayScreen();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class OverlayScreen extends StatelessWidget {
|
||||
const OverlayScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Overlay Demo'),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Container(
|
||||
height: 300.0,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15.0),
|
||||
color: Colors.grey[200],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
child: const Text('Show Overlay'),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
5
app_flowy/packages/flowy_infra_ui/lib/basis.dart
Normal file
5
app_flowy/packages/flowy_infra_ui/lib/basis.dart
Normal file
@ -0,0 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// MARK: - Shared Builder
|
||||
|
||||
typedef WidgetBuilder = Widget Function();
|
@ -1,2 +1,5 @@
|
||||
// Basis
|
||||
export 'basis.dart';
|
||||
|
||||
// Keyboard
|
||||
export 'src/keyboard/keyboard_visibility_detector.dart';
|
||||
|
@ -1,2 +1,5 @@
|
||||
// Basis
|
||||
export 'basis.dart';
|
||||
|
||||
// Keyboard
|
||||
export 'src/keyboard/keyboard_visibility_detector.dart';
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Specifies how overlay are anchored to the SourceWidget
|
||||
enum AnchorDirection {
|
||||
// Corner aligned with a corner of the SourceWidget
|
||||
|
@ -0,0 +1,50 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'overlay_basis.dart';
|
||||
|
||||
class OverlayLayoutDelegate extends SingleChildLayoutDelegate {
|
||||
OverlayLayoutDelegate({
|
||||
required this.anchorRect,
|
||||
required this.targetRect,
|
||||
required this.anchorDirection,
|
||||
required this.safeAreaEnabled,
|
||||
required this.insets,
|
||||
});
|
||||
|
||||
final AnchorDirection anchorDirection;
|
||||
final bool safeAreaEnabled;
|
||||
final EdgeInsets insets;
|
||||
final Rect anchorRect;
|
||||
final Rect targetRect;
|
||||
|
||||
@override
|
||||
bool shouldRelayout(OverlayLayoutDelegate oldDelegate) {
|
||||
return anchorRect != oldDelegate.anchorRect ||
|
||||
insets != oldDelegate.insets ||
|
||||
safeAreaEnabled != oldDelegate.safeAreaEnabled ||
|
||||
anchorDirection != oldDelegate.anchorDirection;
|
||||
}
|
||||
|
||||
@override
|
||||
Offset getPositionForChild(Size size, Size childSize) {
|
||||
// calculate the pannel maximum available rect
|
||||
var pannelRect = Rect.fromLTWH(0, 0, size.width, size.height);
|
||||
pannelRect = insets.deflateRect(pannelRect);
|
||||
// apply safearea
|
||||
if (safeAreaEnabled) {
|
||||
final safeArea = MediaQueryData.fromWindow(window).padding;
|
||||
pannelRect = safeArea.deflateRect(pannelRect);
|
||||
}
|
||||
|
||||
// clip pannel rect
|
||||
|
||||
// TODO: junlin - calculate child position
|
||||
return Offset.zero;
|
||||
}
|
||||
|
||||
@override
|
||||
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
|
||||
return constraints.loosen();
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class OverlayManager extends StatefulWidget {
|
||||
const OverlayManager({Key? key}) : super(key: key);
|
||||
|
||||
static OverlayManagerState of(
|
||||
BuildContext context, {
|
||||
bool rootOverlay = false,
|
||||
}) {
|
||||
OverlayManagerState? overlayManager;
|
||||
if (rootOverlay) {
|
||||
overlayManager = context.findRootAncestorStateOfType<OverlayManagerState>() ?? overlayManager;
|
||||
} else {
|
||||
overlayManager = overlayManager ?? context.findAncestorStateOfType<OverlayManagerState>();
|
||||
}
|
||||
|
||||
assert(() {
|
||||
if (overlayManager == null) {
|
||||
throw FlutterError(
|
||||
'Can\'t find overlay manager in current context, please check if already wrapped by overlay manager.',
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
return overlayManager!;
|
||||
}
|
||||
|
||||
static OverlayManagerState? maybeOf(
|
||||
BuildContext context, {
|
||||
bool rootOverlay = false,
|
||||
}) {
|
||||
OverlayManagerState? overlayManager;
|
||||
if (rootOverlay) {
|
||||
overlayManager = context.findRootAncestorStateOfType<OverlayManagerState>() ?? overlayManager;
|
||||
} else {
|
||||
overlayManager = overlayManager ?? context.findAncestorStateOfType<OverlayManagerState>();
|
||||
}
|
||||
|
||||
return overlayManager;
|
||||
}
|
||||
|
||||
@override
|
||||
OverlayManagerState createState() => OverlayManagerState();
|
||||
}
|
||||
|
||||
class OverlayManagerState extends State<OverlayManager> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Navigator.of(context, rootNavigator: true);
|
||||
return Container();
|
||||
}
|
||||
}
|
@ -1,43 +1,37 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'overlay_basis.dart';
|
||||
|
||||
class OverlayPannel extends SingleChildLayoutDelegate {
|
||||
OverlayPannel({
|
||||
import 'overlay_basis.dart';
|
||||
import 'overlay_layout_delegate.dart';
|
||||
|
||||
class OverlayPannel extends StatelessWidget {
|
||||
const OverlayPannel({
|
||||
Key? key,
|
||||
required this.child,
|
||||
required this.targetRect,
|
||||
required this.anchorRect,
|
||||
this.safeAreaEnabled = true,
|
||||
this.anchorDirection = AnchorDirection.topRight,
|
||||
this.safeAreaEnabled = false,
|
||||
this.insets = EdgeInsets.zero,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
final AnchorDirection anchorDirection;
|
||||
final bool safeAreaEnabled;
|
||||
final EdgeInsets insets;
|
||||
final Rect targetRect;
|
||||
final Rect anchorRect;
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
bool shouldRelayout(OverlayPannel oldDelegate) {
|
||||
return targetRect != oldDelegate.targetRect ||
|
||||
insets != oldDelegate.insets ||
|
||||
safeAreaEnabled != oldDelegate.safeAreaEnabled ||
|
||||
anchorDirection != oldDelegate.anchorDirection;
|
||||
}
|
||||
|
||||
@override
|
||||
Offset getPositionForChild(Size size, Size childSize) {
|
||||
var pannelRect = targetRect;
|
||||
if (safeAreaEnabled) {
|
||||
final safeArea = MediaQueryData.fromWindow(window).padding;
|
||||
pannelRect = safeArea.deflateRect(pannelRect);
|
||||
}
|
||||
|
||||
// TODO: junlin - calculate child position
|
||||
return Offset.zero;
|
||||
}
|
||||
|
||||
@override
|
||||
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
|
||||
return constraints.loosen();
|
||||
Widget build(BuildContext context) {
|
||||
return CustomSingleChildLayout(
|
||||
delegate: OverlayLayoutDelegate(
|
||||
targetRect: targetRect,
|
||||
anchorRect: anchorRect,
|
||||
safeAreaEnabled: safeAreaEnabled,
|
||||
anchorDirection: anchorDirection,
|
||||
insets: insets,
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Overlay extends StatelessWidget {
|
||||
const Overlay({
|
||||
Key? key,
|
||||
this.safeAreaEnabled = true,
|
||||
}) : super(key: key);
|
||||
|
||||
final bool safeAreaEnabled;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
@ -6,9 +6,7 @@ typedef HoverBuilder = Widget Function(BuildContext context, bool isHovering);
|
||||
class MouseHoverBuilder extends StatefulWidget {
|
||||
final bool isClickable;
|
||||
|
||||
const MouseHoverBuilder(
|
||||
{Key? key, required this.builder, this.isClickable = false})
|
||||
: super(key: key);
|
||||
const MouseHoverBuilder({Key? key, required this.builder, this.isClickable = false}) : super(key: key);
|
||||
|
||||
final HoverBuilder builder;
|
||||
|
||||
@ -22,9 +20,7 @@ class _MouseHoverBuilderState extends State<MouseHoverBuilder> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MouseRegion(
|
||||
cursor: widget.isClickable
|
||||
? SystemMouseCursors.click
|
||||
: SystemMouseCursors.basic,
|
||||
cursor: widget.isClickable ? SystemMouseCursors.click : SystemMouseCursors.basic,
|
||||
onEnter: (p) => setOver(true),
|
||||
onExit: (p) => setOver(false),
|
||||
child: widget.builder(context, isOver),
|
||||
|
Loading…
Reference in New Issue
Block a user