You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PatientApp-KKUMC/lib/pages/conference/draggable_publisher.dart

174 lines
5.8 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:diplomaticquarterapp/pages/conference/clipped_video.dart';
import 'package:flutter/material.dart';
class DraggablePublisher extends StatefulWidget {
final Size availableScreenSize;
final Widget child;
final double scaleFactor;
final Stream<bool> onButtonBarVisible;
final Stream<double> onButtonBarHeight;
const DraggablePublisher({
Key key,
@required this.availableScreenSize,
this.child,
@required this.onButtonBarVisible,
@required this.onButtonBarHeight,
/// The portion of the screen the DraggableWidget should use.
this.scaleFactor = .25,
}) : assert(scaleFactor != null && scaleFactor > 0 && scaleFactor <= .4),
assert(availableScreenSize != null),
assert(onButtonBarVisible != null),
assert(onButtonBarHeight != null),
super(key: key);
@override
_DraggablePublisherState createState() => _DraggablePublisherState();
}
class _DraggablePublisherState extends State<DraggablePublisher> {
bool _isButtonBarVisible = true;
double _buttonBarHeight = 0;
double _width;
double _height;
double _top;
double _left;
double _viewPaddingTop;
double _viewPaddingBottom;
final double _padding = 8.0;
final Duration _duration300ms = const Duration(milliseconds: 300);
final Duration _duration0ms = const Duration(milliseconds: 0);
Duration _duration;
StreamSubscription _streamSubscription;
StreamSubscription _streamHeightSubscription;
@override
void initState() {
super.initState();
_duration = _duration300ms;
_width = widget.availableScreenSize.width * widget.scaleFactor;
_height = _width * (widget.availableScreenSize.height / widget.availableScreenSize.width);
_top = widget.availableScreenSize.height - (_buttonBarHeight + _padding) - _height;
_left = widget.availableScreenSize.width - _padding - _width;
_streamSubscription = widget.onButtonBarVisible.listen(_buttonBarVisible);
_streamHeightSubscription = widget.onButtonBarHeight.listen(_getButtonBarHeight);
}
@override
void didChangeDependencies() {
final mediaQuery = MediaQuery.of(context);
_viewPaddingTop = mediaQuery.viewPadding.top;
_viewPaddingBottom = mediaQuery.viewPadding.bottom;
super.didChangeDependencies();
}
@override
void dispose() {
_streamSubscription.cancel();
_streamHeightSubscription.cancel();
super.dispose();
}
void _getButtonBarHeight(double height) {
setState(() {
_buttonBarHeight = height;
_positionWidget();
});
}
void _buttonBarVisible(bool visible) {
if (!mounted) {
return;
}
setState(() {
_isButtonBarVisible = visible;
if (_duration == _duration300ms) {
// only position the widget when we are not currently dragging it around
_positionWidget();
}
});
}
@override
Widget build(BuildContext context) {
return AnimatedPositioned(
top: _top,
left: _left,
width: _width,
height: _height,
duration: _duration,
child: Listener(
onPointerDown: (_) => _duration = _duration0ms,
onPointerMove: (PointerMoveEvent event) {
setState(() {
_left = (_left + event.delta.dx).roundToDouble();
_top = (_top + event.delta.dy).roundToDouble();
});
},
onPointerUp: (_) => _positionWidget(),
onPointerCancel: (_) => _positionWidget(),
child: ClippedVideo(
height: _height,
width: _width,
child: widget.child,
),
),
);
}
double _getCurrentStatusBarHeight() {
if (_isButtonBarVisible) {
return _viewPaddingTop;
}
final _defaultViewPaddingTop = Platform.isIOS ? 20.0 : Platform.isAndroid ? 24.0 : 0.0;
if (_viewPaddingTop > _defaultViewPaddingTop) {
// There must be a hardware notch in the display.
return _viewPaddingTop;
}
return 0.0;
}
double _getCurrentButtonBarHeight() {
if (_isButtonBarVisible) {
return _buttonBarHeight + _viewPaddingBottom;
}
return _viewPaddingBottom;
}
void _positionWidget() {
// Determine the center of the object being dragged so we can decide
// in which corner the object should be placed.
var dx = (_width / 2) + _left;
dx = dx < 0 ? 0 : dx >= widget.availableScreenSize.width ? widget.availableScreenSize.width - 1 : dx;
var dy = (_height / 2) + _top;
dy = dy < 0 ? 0 : dy >= widget.availableScreenSize.height ? widget.availableScreenSize.height - 1 : dy;
final draggableCenter = Offset(dx, dy);
setState(() {
_duration = _duration300ms;
if (Rect.fromLTRB(0, 0, widget.availableScreenSize.width / 2, widget.availableScreenSize.height / 2).contains(draggableCenter)) {
// Top-left
_top = _getCurrentStatusBarHeight() + _padding;
_left = _padding;
} else if (Rect.fromLTRB(widget.availableScreenSize.width / 2, 0, widget.availableScreenSize.width, widget.availableScreenSize.height / 2).contains(draggableCenter)) {
// Top-right
_top = _getCurrentStatusBarHeight() + _padding;
_left = widget.availableScreenSize.width - _padding - _width;
} else if (Rect.fromLTRB(0, widget.availableScreenSize.height / 2, widget.availableScreenSize.width / 2, widget.availableScreenSize.height).contains(draggableCenter)) {
// Bottom-left
_top = widget.availableScreenSize.height - (_getCurrentButtonBarHeight() + _padding) - _height;
_left = _padding;
} else if (Rect.fromLTRB(widget.availableScreenSize.width / 2, widget.availableScreenSize.height / 2, widget.availableScreenSize.width, widget.availableScreenSize.height).contains(draggableCenter)) {
// Bottom-right
_top = widget.availableScreenSize.height - (_getCurrentButtonBarHeight() + _padding) - _height;
_left = widget.availableScreenSize.width - _padding - _width;
}
});
}
}