左右拖动布局

This commit is contained in:
wanghongen
2023-06-27 15:39:18 +08:00
parent 1ad938c533
commit a5530171b7
7 changed files with 131 additions and 18 deletions

View File

@@ -2,6 +2,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:network_proxy/network/bin/server.dart';
import 'package:network_proxy/ui/component/split_view.dart';
import 'package:network_proxy/ui/left/domain.dart';
import 'package:network_proxy/ui/panel.dart';
import 'package:network_proxy/ui/toolbar/toolbar.dart';
@@ -84,19 +85,12 @@ class _NetworkHomePagePageState extends State<NetworkHomePage> implements EventL
@override
Widget build(BuildContext context) {
final domainWidget = DomainWidget(key: domainStateKey, panel: panel);
return Scaffold(
appBar: Tab(
child: Toolbar(proxyServer, domainStateKey),
),
body: Padding(
padding: const EdgeInsets.only(top: 5),
child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
SizedBox(width: 400, child: domainWidget),
const VerticalDivider(),
Expanded(flex: 100, child: panel),
])));
body: VerticalSplitView(ratio: 0.3, minRatio: 0.15, maxRatio: 0.9, left: domainWidget, right: panel));
}
}

View File

@@ -0,0 +1,83 @@
import 'package:flutter/material.dart';
class VerticalSplitView extends StatefulWidget {
final Widget left;
final Widget right;
final double ratio;
final double minRatio;
final double maxRatio;
const VerticalSplitView(
{super.key, required this.left, required this.right, this.ratio = 0.5, this.minRatio = 0, this.maxRatio = 1})
: assert(ratio >= 0 && ratio <= 1);
@override
State<VerticalSplitView> createState() => _VerticalSplitViewState();
}
class _VerticalSplitViewState extends State<VerticalSplitView> {
final _dividerWidth = 10.0;
//from 0-1
late double _ratio;
double _maxWidth = double.infinity;
get _width1 => _ratio * _maxWidth;
get _width2 => (1 - _ratio) * _maxWidth;
@override
void initState() {
super.initState();
_ratio = widget.ratio;
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, BoxConstraints constraints) {
if (_maxWidth != constraints.maxWidth) {
_maxWidth = constraints.maxWidth - _dividerWidth;
}
return SizedBox(
width: constraints.maxWidth,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
width: _width1 - 5,
child: widget.left,
),
GestureDetector(
behavior: HitTestBehavior.translucent,
child: MouseRegion(
cursor: SystemMouseCursors.resizeColumn,
child: SizedBox(
width: _dividerWidth,
height: double.infinity,
child: (_ratio <= 0 || _ratio >= 1)
? const Icon(Icons.drag_handle, size: 16)
: const VerticalDivider(thickness: 2),
)),
onPanUpdate: (DragUpdateDetails details) {
setState(() {
_ratio += details.delta.dx / _maxWidth;
if (_ratio > widget.maxRatio) {
_ratio = widget.maxRatio;
} else if (_ratio < widget.minRatio) {
_ratio = widget.minRatio;
}
});
},
),
SizedBox(
width: _width2,
child: widget.right,
),
],
),
);
});
}
}

View File

@@ -6,8 +6,12 @@ class ColorTransition extends StatefulWidget {
final Duration duration;
final Widget child;
const ColorTransition({super.key, required this.begin, this.end = Colors.transparent,
this.duration = const Duration(milliseconds: 500), required this.child});
const ColorTransition(
{super.key,
required this.begin,
this.end = Colors.transparent,
this.duration = const Duration(milliseconds: 500),
required this.child});
@override
State<ColorTransition> createState() {
@@ -22,7 +26,6 @@ class ColorTransitionState extends State<ColorTransition> with SingleTickerProvi
@override
void initState() {
super.initState();
print("AnimationController");
//
_animationController = AnimationController(
@@ -39,7 +42,7 @@ class ColorTransitionState extends State<ColorTransition> with SingleTickerProvi
_animation = ColorTween(begin: widget.begin, end: widget.end).animate(_animationController);
//
Future.delayed(const Duration(milliseconds: 80), () {
Future.delayed(const Duration(milliseconds: 150), () {
_animationController.forward();
});
}

View File

@@ -2,7 +2,7 @@ import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:network_proxy/network/http/http.dart';
import 'package:network_proxy/ui/components.dart';
import 'package:network_proxy/ui/component/transition.dart';
import 'package:network_proxy/ui/left/path.dart';
import '../../network/channel.dart';
@@ -109,7 +109,8 @@ class _HeaderBodyState extends State<HeaderBody> {
@override
Widget build(BuildContext context) {
return Column(children: [
return Column(
children: [
_hostWidget(widget.header),
Offstage(offstage: !selected, child: Column(children: widget._body.toList()))
]);

View File

@@ -155,6 +155,7 @@ class _DomainFilterState extends State<DomainFilter> {
String? host;
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
scrollable: true,
@@ -168,7 +169,7 @@ class _DomainFilterState extends State<DomainFilter> {
onSaved: (val) => host = val)
]))),
actions: [
ElevatedButton(
FilledButton(
child: const Text("添加"),
onPressed: () {
(formKey.currentState as FormState).save();
@@ -182,6 +183,11 @@ class _DomainFilterState extends State<DomainFilter> {
}
}
Navigator.of(context).pop();
}),
ElevatedButton(
child: const Text("关闭"),
onPressed: () {
Navigator.of(context).pop();
})
]);
});
@@ -211,9 +217,9 @@ class DomainList extends StatefulWidget {
class _DomainListState extends State<DomainList> {
late Map<int, bool> selected = {};
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(top: 10),
height: 300,

View File

@@ -94,6 +94,7 @@ class _RequestRewriteState extends State<RequestRewrite> {
void add([int currentIndex = -1]) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return RuleAddDialog(
requestRewrites: widget.proxyServer.requestRewrites,
@@ -187,6 +188,11 @@ class RuleAddDialog extends StatelessWidget {
onChange.call();
Navigator.of(context).pop();
}
}),
ElevatedButton(
child: const Text("关闭"),
onPressed: () {
Navigator.of(context).pop();
})
]);
}

View File

@@ -1,9 +1,9 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:network_proxy/ui/toolbar/setting/setting.dart';
import 'package:network_proxy/ui/toolbar/ssl/ssl.dart';
import 'package:window_manager/window_manager.dart';
import '../../network/bin/server.dart';
import '../left/domain.dart';
@@ -21,7 +21,27 @@ class Toolbar extends StatefulWidget {
}
}
class _ToolbarState extends State<Toolbar> with WindowListener {
class _ToolbarState extends State<Toolbar> {
@override
void initState() {
super.initState();
RawKeyboard.instance.addListener(onKeyEvent);
}
void onKeyEvent(RawKeyEvent event) {
if (event.isKeyPressed(LogicalKeyboardKey.escape)) {
if (ModalRoute.of(context)?.isCurrent == false) {
Navigator.of(context).pop();
}
}
}
@override
void dispose() {
RawKeyboard.instance.removeListener(onKeyEvent);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Row(