mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-03-23 05:59:46 +08:00
左右拖动布局
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
83
lib/ui/component/split_view.dart
Normal file
83
lib/ui/component/split_view.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
@@ -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()))
|
||||
]);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user