switch scale mode if 3 fingers tap
This commit is contained in:
parent
8090726649
commit
d73d3166d3
104
flutter_hbb/lib/drag.dart
Normal file
104
flutter_hbb/lib/drag.dart
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import 'package:flutter/gestures.dart';
|
||||||
|
|
||||||
|
class MultiTouchGestureRecognizer extends MultiTapGestureRecognizer {
|
||||||
|
MultiTouchGestureRecognizerCallback onMultiTap;
|
||||||
|
var numberOfTouches = 0;
|
||||||
|
|
||||||
|
MultiTouchGestureRecognizer() {
|
||||||
|
this
|
||||||
|
..onTapDown = addTouch
|
||||||
|
..onTapUp = removeTouch
|
||||||
|
..onTapCancel = cancelTouch
|
||||||
|
..onTap = captureDefaultTap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addTouch(int pointer, TapDownDetails details) {
|
||||||
|
numberOfTouches++;
|
||||||
|
onMultiTap(numberOfTouches, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeTouch(int pointer, TapUpDetails details) {
|
||||||
|
numberOfTouches--;
|
||||||
|
onMultiTap(numberOfTouches, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancelTouch(int pointer) {
|
||||||
|
numberOfTouches = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void captureDefaultTap(int pointer) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef MultiTouchGestureRecognizerCallback = void Function(
|
||||||
|
int touchCount, bool addOrRemove);
|
||||||
|
|
||||||
|
typedef OnUpdate(DragUpdateDetails details);
|
||||||
|
|
||||||
|
class CustomMultiDrag extends Drag {
|
||||||
|
CustomMultiDrag({this.events, this.offset});
|
||||||
|
|
||||||
|
List<PointerDownEvent> events;
|
||||||
|
Offset offset;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(DragUpdateDetails details) {
|
||||||
|
var n = events.length;
|
||||||
|
print('$n $details');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void end(DragEndDetails details) {
|
||||||
|
super.end(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef OnDisposeState();
|
||||||
|
|
||||||
|
// clone _ImmediatePointerState
|
||||||
|
class CustomPointerState extends MultiDragPointerState {
|
||||||
|
final OnDisposeState onDisposeState;
|
||||||
|
CustomPointerState(Offset initialPosition, PointerDeviceKind kind,
|
||||||
|
{this.onDisposeState})
|
||||||
|
: super(initialPosition, kind);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void checkForResolutionAfterMove() {
|
||||||
|
assert(pendingDelta != null);
|
||||||
|
if (pendingDelta.distance > computeHitSlop(kind))
|
||||||
|
resolve(GestureDisposition.accepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void accepted(GestureMultiDragStartCallback starter) {
|
||||||
|
starter(initialPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
onDisposeState.call();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clone ImmediateMultiDragGestureRecognizer
|
||||||
|
class CustomMultiDragGestureRecognizer
|
||||||
|
extends MultiDragGestureRecognizer<CustomPointerState> {
|
||||||
|
var events = List<PointerDownEvent>();
|
||||||
|
|
||||||
|
/// Create a gesture recognizer for tracking multiple pointers at once.
|
||||||
|
CustomMultiDragGestureRecognizer({
|
||||||
|
Object debugOwner,
|
||||||
|
PointerDeviceKind kind,
|
||||||
|
}) : super(debugOwner: debugOwner, kind: kind);
|
||||||
|
|
||||||
|
@override
|
||||||
|
CustomPointerState createNewPointerState(PointerDownEvent event) {
|
||||||
|
events.add(event);
|
||||||
|
return CustomPointerState(event.position, event.kind, onDisposeState: () {
|
||||||
|
events.remove(event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get debugDescription => 'custom_multidrag';
|
||||||
|
}
|
@ -7,9 +7,10 @@ import 'package:flutter_easyloading/flutter_easyloading.dart';
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
import 'common.dart';
|
|
||||||
import 'model.dart';
|
|
||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
|
import 'common.dart';
|
||||||
|
import 'drag.dart';
|
||||||
|
import 'model.dart';
|
||||||
|
|
||||||
class RemotePage extends StatefulWidget {
|
class RemotePage extends StatefulWidget {
|
||||||
RemotePage({Key key, this.id}) : super(key: key);
|
RemotePage({Key key, this.id}) : super(key: key);
|
||||||
@ -26,6 +27,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
bool _showBar = true;
|
bool _showBar = true;
|
||||||
double _bottom = 0;
|
double _bottom = 0;
|
||||||
bool _pan = false;
|
bool _pan = false;
|
||||||
|
var _scaleMode = false;
|
||||||
final FocusNode _focusNode = FocusNode();
|
final FocusNode _focusNode = FocusNode();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -162,19 +164,35 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
body: RawGestureDetector(
|
body: RawGestureDetector(
|
||||||
gestures: {
|
gestures: buildGuestures(),
|
||||||
MultiTouchGestureRecognizer:
|
child: FlutterEasyLoading(
|
||||||
GestureRecognizerFactoryWithHandlers<
|
child: Container(
|
||||||
MultiTouchGestureRecognizer>(
|
color: MyTheme.canvasColor,
|
||||||
() => MultiTouchGestureRecognizer(),
|
child: Stack(children: [
|
||||||
(MultiTouchGestureRecognizer instance) {
|
ImagePaint(),
|
||||||
instance.onMultiTap = (
|
CursorPaint(),
|
||||||
touchCount,
|
SizedBox(
|
||||||
addOrRemove,
|
width: 0,
|
||||||
) =>
|
height: 0,
|
||||||
print('$touchCount, $addOrRemove');
|
child: _bottom < 100
|
||||||
},
|
? Container()
|
||||||
|
: TextField(
|
||||||
|
textInputAction: TextInputAction.newline,
|
||||||
|
autocorrect: false,
|
||||||
|
enableSuggestions: false,
|
||||||
|
focusNode: _focusNode,
|
||||||
|
maxLines: null,
|
||||||
|
keyboardType: TextInputType.multiline,
|
||||||
|
onChanged: (x) => print('$x'),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
])),
|
||||||
|
)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Type, GestureRecognizerFactory> buildGuestures() {
|
||||||
|
var m = {
|
||||||
TapGestureRecognizer:
|
TapGestureRecognizer:
|
||||||
GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
|
GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
|
||||||
() => TapGestureRecognizer(),
|
() => TapGestureRecognizer(),
|
||||||
@ -184,20 +202,32 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ImmediateMultiDragGestureRecognizer:
|
MultiTouchGestureRecognizer:
|
||||||
GestureRecognizerFactoryWithHandlers<
|
GestureRecognizerFactoryWithHandlers<MultiTouchGestureRecognizer>(
|
||||||
ImmediateMultiDragGestureRecognizer>(
|
() => MultiTouchGestureRecognizer(),
|
||||||
() => ImmediateMultiDragGestureRecognizer(),
|
(MultiTouchGestureRecognizer instance) {
|
||||||
(ImmediateMultiDragGestureRecognizer instance) {
|
instance.onMultiTap = (
|
||||||
|
touchCount,
|
||||||
|
addOrRemove,
|
||||||
|
) {
|
||||||
|
if (touchCount == 3 && addOrRemove) {
|
||||||
|
setState(() => _scaleMode = !_scaleMode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
),
|
||||||
|
CustomMultiDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<
|
||||||
|
CustomMultiDragGestureRecognizer>(
|
||||||
|
() => CustomMultiDragGestureRecognizer(),
|
||||||
|
(CustomMultiDragGestureRecognizer instance) {
|
||||||
instance
|
instance
|
||||||
..onStart = (x) {
|
..onStart = (offset) {
|
||||||
return CustomDrag();
|
return CustomMultiDrag(events: instance.events, offset: offset);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
LongPressGestureRecognizer:
|
LongPressGestureRecognizer:
|
||||||
GestureRecognizerFactoryWithHandlers<
|
GestureRecognizerFactoryWithHandlers<LongPressGestureRecognizer>(
|
||||||
LongPressGestureRecognizer>(
|
|
||||||
() => LongPressGestureRecognizer(),
|
() => LongPressGestureRecognizer(),
|
||||||
(LongPressGestureRecognizer instance) {
|
(LongPressGestureRecognizer instance) {
|
||||||
var x = 0.0;
|
var x = 0.0;
|
||||||
@ -225,21 +255,8 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
PanGestureRecognizer:
|
ScaleGestureRecognizer:
|
||||||
GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
|
GestureRecognizerFactoryWithHandlers<ScaleGestureRecognizer>(
|
||||||
() => PanGestureRecognizer(),
|
|
||||||
(PanGestureRecognizer instance) {
|
|
||||||
instance
|
|
||||||
..onStart = (detail) {
|
|
||||||
print('pan start');
|
|
||||||
}
|
|
||||||
..onUpdate = (detail) {
|
|
||||||
print('$detail');
|
|
||||||
};
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ScaleGestureRecognizer: GestureRecognizerFactoryWithHandlers<
|
|
||||||
ScaleGestureRecognizer>(
|
|
||||||
() => ScaleGestureRecognizer(),
|
() => ScaleGestureRecognizer(),
|
||||||
(ScaleGestureRecognizer instance) {
|
(ScaleGestureRecognizer instance) {
|
||||||
instance
|
instance
|
||||||
@ -252,8 +269,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
DoubleTapGestureRecognizer:
|
DoubleTapGestureRecognizer:
|
||||||
GestureRecognizerFactoryWithHandlers<
|
GestureRecognizerFactoryWithHandlers<DoubleTapGestureRecognizer>(
|
||||||
DoubleTapGestureRecognizer>(
|
|
||||||
() => DoubleTapGestureRecognizer(),
|
() => DoubleTapGestureRecognizer(),
|
||||||
(DoubleTapGestureRecognizer instance) {
|
(DoubleTapGestureRecognizer instance) {
|
||||||
instance.onDoubleTap = () {
|
instance.onDoubleTap = () {
|
||||||
@ -261,31 +277,13 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
},
|
};
|
||||||
child: FlutterEasyLoading(
|
if (_scaleMode) {
|
||||||
child: Container(
|
m.remove(CustomMultiDragGestureRecognizer);
|
||||||
color: MyTheme.canvasColor,
|
} else {
|
||||||
child: Stack(children: [
|
m.remove(ScaleGestureRecognizer);
|
||||||
ImagePaint(),
|
}
|
||||||
CursorPaint(),
|
return m;
|
||||||
SizedBox(
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
child: _bottom < 100
|
|
||||||
? Container()
|
|
||||||
: TextField(
|
|
||||||
textInputAction: TextInputAction.newline,
|
|
||||||
autocorrect: false,
|
|
||||||
enableSuggestions: false,
|
|
||||||
focusNode: _focusNode,
|
|
||||||
maxLines: null,
|
|
||||||
keyboardType: TextInputType.multiline,
|
|
||||||
onChanged: (x) => print('$x'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
])),
|
|
||||||
)),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
@ -503,52 +501,3 @@ void showActions(BuildContext context) {
|
|||||||
true,
|
true,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiTouchGestureRecognizer extends MultiTapGestureRecognizer {
|
|
||||||
MultiTouchGestureRecognizerCallback onMultiTap;
|
|
||||||
var numberOfTouches = 0;
|
|
||||||
|
|
||||||
MultiTouchGestureRecognizer() {
|
|
||||||
this
|
|
||||||
..onTapDown = addTouch
|
|
||||||
..onTapUp = removeTouch
|
|
||||||
..onTapCancel = cancelTouch
|
|
||||||
..onTap = captureDefaultTap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addTouch(int pointer, TapDownDetails details) {
|
|
||||||
numberOfTouches++;
|
|
||||||
onMultiTap(numberOfTouches, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeTouch(int pointer, TapUpDetails details) {
|
|
||||||
numberOfTouches--;
|
|
||||||
onMultiTap(numberOfTouches, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cancelTouch(int pointer) {
|
|
||||||
numberOfTouches--;
|
|
||||||
print('$numberOfTouches x');
|
|
||||||
}
|
|
||||||
|
|
||||||
void captureDefaultTap(int pointer) {
|
|
||||||
print('$pointer');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef MultiTouchGestureRecognizerCallback = void Function(
|
|
||||||
int touchCount, bool addOrRemove);
|
|
||||||
|
|
||||||
typedef OnUpdate(DragUpdateDetails details);
|
|
||||||
|
|
||||||
class CustomDrag extends Drag {
|
|
||||||
@override
|
|
||||||
void update(DragUpdateDetails details) {
|
|
||||||
print('xx $details');
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void end(DragEndDetails details) {
|
|
||||||
super.end(details);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user