130 lines
4.2 KiB
Dart
130 lines
4.2 KiB
Dart
import 'package:aves/widgets/common/magnifier/controller/controller.dart';
|
|
import 'package:aves/widgets/common/magnifier/controller/state.dart';
|
|
import 'package:aves/widgets/common/magnifier/core/core.dart';
|
|
import 'package:aves/widgets/common/magnifier/scale/scale_boundaries.dart';
|
|
import 'package:aves/widgets/common/magnifier/scale/scale_level.dart';
|
|
import 'package:aves/widgets/common/magnifier/scale/state.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
/// `Magnifier` is derived from `photo_view` package v0.9.2:
|
|
/// - removed image related aspects to focus on a general purpose pan/scale viewer (à la `InteractiveViewer`)
|
|
/// - removed rotation and many customization parameters
|
|
/// - removed ignorable/ignoring partial notifiers
|
|
/// - formatted, renamed and reorganized
|
|
/// - fixed gesture recognizers when used inside a scrollable widget like `PageView`
|
|
/// - fixed corner hit detection when in containers scrollable in both axes
|
|
/// - fixed corner hit detection issues due to imprecise double comparisons
|
|
/// - added single & double tap position feedback
|
|
/// - fixed focus when scaling by double-tap/pinch
|
|
class Magnifier extends StatefulWidget {
|
|
const Magnifier({
|
|
Key key,
|
|
@required this.child,
|
|
this.childSize,
|
|
this.controller,
|
|
this.maxScale,
|
|
this.minScale,
|
|
this.initialScale,
|
|
this.scaleStateCycle,
|
|
this.onTap,
|
|
this.gestureDetectorBehavior,
|
|
this.applyScale,
|
|
}) : super(key: key);
|
|
|
|
final Widget child;
|
|
|
|
/// The size of the custom [child]. This value is used to compute the relation between the child and the container's size to calculate the scale value.
|
|
final Size childSize;
|
|
|
|
/// Defines the maximum size in which the image will be allowed to assume, it is proportional to the original image size.
|
|
final ScaleLevel maxScale;
|
|
|
|
/// Defines the minimum size in which the image will be allowed to assume, it is proportional to the original image size.
|
|
final ScaleLevel minScale;
|
|
|
|
/// Defines the size the image will assume when the component is initialized, it is proportional to the original image size.
|
|
final ScaleLevel initialScale;
|
|
|
|
final MagnifierController controller;
|
|
final ScaleStateCycle scaleStateCycle;
|
|
final MagnifierTapCallback onTap;
|
|
final HitTestBehavior gestureDetectorBehavior;
|
|
final bool applyScale;
|
|
|
|
@override
|
|
State<StatefulWidget> createState() {
|
|
return _MagnifierState();
|
|
}
|
|
}
|
|
|
|
class _MagnifierState extends State<Magnifier> {
|
|
bool _controlledController;
|
|
MagnifierController _controller;
|
|
|
|
Size get childSize => widget.childSize;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
if (widget.controller == null) {
|
|
_controlledController = true;
|
|
_controller = MagnifierController();
|
|
} else {
|
|
_controlledController = false;
|
|
_controller = widget.controller;
|
|
}
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(covariant Magnifier oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (widget.controller == null) {
|
|
if (!_controlledController) {
|
|
_controlledController = true;
|
|
_controller = MagnifierController();
|
|
}
|
|
} else {
|
|
_controlledController = false;
|
|
_controller = widget.controller;
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
if (_controlledController) {
|
|
_controller.dispose();
|
|
}
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return LayoutBuilder(
|
|
builder: (context, constraints) {
|
|
_controller.setScaleBoundaries(ScaleBoundaries(
|
|
widget.minScale ?? 0.0,
|
|
widget.maxScale ?? ScaleLevel(factor: double.infinity),
|
|
widget.initialScale ?? ScaleLevel(ref: ScaleReference.contained),
|
|
constraints.biggest,
|
|
widget.childSize?.isEmpty == true ? constraints.biggest : widget.childSize,
|
|
));
|
|
|
|
return MagnifierCore(
|
|
child: widget.child,
|
|
controller: _controller,
|
|
scaleStateCycle: widget.scaleStateCycle ?? defaultScaleStateCycle,
|
|
onTap: widget.onTap,
|
|
gestureDetectorBehavior: widget.gestureDetectorBehavior,
|
|
applyScale: widget.applyScale ?? true,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
typedef MagnifierTapCallback = Function(
|
|
BuildContext context,
|
|
TapUpDetails details,
|
|
MagnifierState state,
|
|
Offset childTapPosition,
|
|
);
|