[infra_ui][overlar] Implement corner aligned anchor mode and update example project

This commit is contained in:
Jaylen Bian 2021-08-01 19:17:24 +08:00
parent ada5ab737e
commit dffb56d1a9
2 changed files with 115 additions and 79 deletions

View File

@ -1,5 +1,6 @@
import 'package:flowy_infra_ui/flowy_infra_ui_web.dart'; import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../home/demo_item.dart'; import '../home/demo_item.dart';
@ -19,6 +20,19 @@ class OverlayItem extends DemoItem {
} }
} }
class OverlayDemoAnchorDirection extends ChangeNotifier {
OverlayDemoAnchorDirection(this._anchorDirection);
AnchorDirection _anchorDirection;
AnchorDirection get anchorDirection => _anchorDirection;
set anchorDirection(AnchorDirection value) {
_anchorDirection = value;
notifyListeners();
}
}
class OverlayScreen extends StatelessWidget { class OverlayScreen extends StatelessWidget {
const OverlayScreen({Key? key}) : super(key: key); const OverlayScreen({Key? key}) : super(key: key);
@ -28,83 +42,99 @@ class OverlayScreen extends StatelessWidget {
appBar: AppBar( appBar: AppBar(
title: const Text('Overlay Demo'), title: const Text('Overlay Demo'),
), ),
body: Column( body: ChangeNotifierProvider(
children: [ create: (context) => OverlayDemoAnchorDirection(AnchorDirection.topLeft),
Flexible( child: Builder(builder: (context) {
child: Padding( return Column(
padding: const EdgeInsets.all(16.0), children: [
child: Container( DropdownButton<AnchorDirection>(
height: 300.0, value: context.watch<OverlayDemoAnchorDirection>().anchorDirection,
decoration: BoxDecoration( onChanged: (AnchorDirection? newValue) {
borderRadius: BorderRadius.circular(15.0), if (newValue != null) {
color: Colors.grey[200], context.read<OverlayDemoAnchorDirection>().anchorDirection = newValue;
}
},
items: AnchorDirection.values.map((AnchorDirection classType) {
return DropdownMenuItem<AnchorDirection>(value: classType, child: Text(classType.toString()));
}).toList(),
),
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: () {
ElevatedButton( FlowyOverlay.of(context).insertCustom(
onPressed: () { widget: const FlutterLogo(
FlowyOverlay.of(context).insertCustom( size: 200,
widget: const FlutterLogo( ),
size: 200, identifier: 'overlay_flutter_logo',
), delegate: null,
identifier: 'overlay_flutter_logo', );
delegate: null, },
); child: const Text('Show Overlay'),
}, ),
child: const Text('Show Overlay'), const SizedBox(height: 12.0),
), Builder(builder: (buttonContext) {
const SizedBox(height: 12.0), return ElevatedButton(
Builder(builder: (buttonContext) { onPressed: () {
return ElevatedButton( FlowyOverlay.of(context).insertWithAnchor(
onPressed: () { widget: SizedBox(
FlowyOverlay.of(context).insertWithAnchor( width: 200,
widget: SizedBox( height: 100,
width: 200, child: Card(
height: 100, color: Colors.grey[200],
child: Card( child: GestureDetector(
color: Colors.grey[200], onTapDown: (_) => print('Hello Flutter'),
child: GestureDetector( child: const Center(child: FlutterLogo(size: 100)),
onTapDown: (_) => print('Hello Flutter'), ),
child: const Center(child: FlutterLogo(size: 100)), ),
),
identifier: 'overlay_card',
delegate: null,
anchorContext: buttonContext,
anchorDirection: context.read<OverlayDemoAnchorDirection>().anchorDirection,
);
},
child: const Text('Show Anchored Overlay'),
);
}),
const SizedBox(height: 12.0),
ElevatedButton(
onPressed: () {
final windowSize = MediaQuery.of(context).size;
FlowyOverlay.of(context).insertWithRect(
widget: SizedBox(
width: 200,
height: 100,
child: Card(
color: Colors.orange[200],
child: GestureDetector(
onTapDown: (_) => print('Hello Flutter'),
child: const Center(child: FlutterLogo(size: 100)),
),
), ),
), ),
), identifier: 'overlay_card',
identifier: 'overlay_card', delegate: null,
delegate: null, anchorPosition: Offset(0, windowSize.height - 200),
anchorContext: buttonContext, anchorSize: Size.zero,
anchorDirection: AnchorDirection.topLeft, anchorDirection: context.read<OverlayDemoAnchorDirection>().anchorDirection,
); );
}, },
child: const Text('Show Anchored Overlay'), child: const Text('Show Positioned Overlay'),
); ),
}), ],
const SizedBox(height: 12.0), );
ElevatedButton( }),
onPressed: () {
final windowSize = MediaQuery.of(context).size;
FlowyOverlay.of(context).insertWithRect(
widget: SizedBox(
width: 200,
height: 100,
child: Card(
color: Colors.orange[200],
child: GestureDetector(
onTapDown: (_) => print('Hello Flutter'),
child: const Center(child: FlutterLogo(size: 100)),
),
),
),
identifier: 'overlay_card',
delegate: null,
anchorPosition: Offset(0, windowSize.height - 200),
anchorSize: Size.zero,
anchorDirection: AnchorDirection.topLeft,
);
},
child: const Text('Show Positioned Overlay'),
),
],
)); ));
} }
} }

View File

@ -39,17 +39,23 @@ class OverlayLayoutDelegate extends SingleChildLayoutDelegate {
Offset position; Offset position;
switch (anchorDirection) { switch (anchorDirection) {
case AnchorDirection.topLeft: case AnchorDirection.topLeft:
position = Offset( position = Offset(anchorRect.left - childSize.width, anchorRect.top - childSize.height);
anchorRect.left - childSize.width, break;
anchorRect.top - childSize.height, case AnchorDirection.topRight:
); position = Offset(anchorRect.right, anchorRect.top - childSize.height);
break;
case AnchorDirection.bottomLeft:
position = Offset(anchorRect.left - childSize.width, anchorRect.bottom);
break;
case AnchorDirection.bottomRight:
position = Offset(anchorRect.right, anchorRect.bottom);
break; break;
default: default:
throw UnimplementedError(); throw UnimplementedError();
} }
return Offset( return Offset(
math.max(0.0, math.min(size.width, position.dx)), math.max(0.0, math.min(size.width - childSize.width, position.dx)),
math.max(0.0, math.min(size.height, position.dy)), math.max(0.0, math.min(size.height - childSize.height, position.dy)),
); );
} }
} }