mirror of
https://bitbucket.org/FransoletThomas/tablet-app.git
synced 2025-12-06 16:41:19 +00:00
Fix some html element not supported (map) + init puzzle widget
This commit is contained in:
parent
11ab21abd9
commit
09a0cd04e9
@ -8,6 +8,7 @@ import 'package:manager_api/api.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tablet_app/Models/map-marker.dart';
|
import 'package:tablet_app/Models/map-marker.dart';
|
||||||
import 'package:tablet_app/Screens/Map/map_context.dart';
|
import 'package:tablet_app/Screens/Map/map_context.dart';
|
||||||
|
import 'package:html/parser.dart' show parse;
|
||||||
|
|
||||||
class GoogleMapView extends StatefulWidget {
|
class GoogleMapView extends StatefulWidget {
|
||||||
final MapDTO? mapDTO;
|
final MapDTO? mapDTO;
|
||||||
@ -34,9 +35,10 @@ class _GoogleMapViewState extends State<GoogleMapView> {
|
|||||||
markers = {};
|
markers = {};
|
||||||
|
|
||||||
widget.mapDTO!.points!.forEach((point) {
|
widget.mapDTO!.points!.forEach((point) {
|
||||||
|
var textSansHTML = parse(point.title!.firstWhere((translation) => translation.language == language).value);
|
||||||
var mapMarker = new MapMarker(
|
var mapMarker = new MapMarker(
|
||||||
id: point.id,
|
id: point.id,
|
||||||
title: point.title!.firstWhere((translation) => translation.language == language).value,
|
title: parse(textSansHTML.body!.text).documentElement!.text,
|
||||||
description: point.description!.firstWhere((translation) => translation.language == language).value,
|
description: point.description!.firstWhere((translation) => translation.language == language).value,
|
||||||
longitude: point.longitude,
|
longitude: point.longitude,
|
||||||
latitude: point.latitude,
|
latitude: point.latitude,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:carousel_slider/carousel_slider.dart';
|
import 'package:carousel_slider/carousel_slider.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||||
import 'package:photo_view/photo_view.dart';
|
import 'package:photo_view/photo_view.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tablet_app/Models/map-marker.dart';
|
import 'package:tablet_app/Models/map-marker.dart';
|
||||||
@ -99,7 +100,13 @@ class _MarkerInfoWidget extends State<MarkerViewWidget> {
|
|||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(top: 20),
|
padding: const EdgeInsets.only(top: 20),
|
||||||
child: Text(mapContext.getSelectedMarker().title, style: TextStyle(fontWeight: FontWeight.w600, fontSize: kIsWeb ? kWebTitleSize : kTitleSize)),
|
child: HtmlWidget(
|
||||||
|
mapContext.getSelectedMarker().title,
|
||||||
|
customStylesBuilder: (element) {
|
||||||
|
return {'text-align': 'center'};
|
||||||
|
},
|
||||||
|
textStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: kIsWeb ? kWebTitleSize : kTitleSize)
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
@ -193,7 +200,13 @@ class _MarkerInfoWidget extends State<MarkerViewWidget> {
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(15.0),
|
padding: const EdgeInsets.all(15.0),
|
||||||
child: Text(mapContext.getSelectedMarker().description, textAlign: TextAlign.center, style: TextStyle(fontSize: kIsWeb ? kWebDescriptionSize : kDescriptionSize)),
|
child: HtmlWidget(
|
||||||
|
mapContext.getSelectedMarker().description,
|
||||||
|
customStylesBuilder: (element) {
|
||||||
|
return {'text-align': 'center'};
|
||||||
|
},
|
||||||
|
textStyle: TextStyle(fontSize: kIsWeb ? kWebDescriptionSize : kDescriptionSize)
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -204,7 +204,7 @@ boxDecoration(SectionDTO section, bool isSelected) {
|
|||||||
borderRadius: BorderRadius.circular(30.0),
|
borderRadius: BorderRadius.circular(30.0),
|
||||||
image: section.imageSource != null ? new DecorationImage(
|
image: section.imageSource != null ? new DecorationImage(
|
||||||
fit: kIsWeb ? BoxFit.cover : BoxFit.contain,
|
fit: kIsWeb ? BoxFit.cover : BoxFit.contain,
|
||||||
colorFilter: !isSelected? new ColorFilter.mode(Colors.black.withOpacity(kIsWeb ? 0.3 : 0.5), BlendMode.dstATop) : null,
|
colorFilter: !isSelected? new ColorFilter.mode(Colors.black.withOpacity(0.3), BlendMode.dstATop) : null,
|
||||||
image: new NetworkImage(
|
image: new NetworkImage(
|
||||||
section.imageSource!,
|
section.imageSource!,
|
||||||
),
|
),
|
||||||
|
|||||||
68
lib/Screens/Puzzle/correct_overlay.dart
Normal file
68
lib/Screens/Puzzle/correct_overlay.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'dart:math' as math;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CorrectOverlay extends StatefulWidget {
|
||||||
|
final bool _isCorrect;
|
||||||
|
final VoidCallback _onTap;
|
||||||
|
|
||||||
|
CorrectOverlay(this._isCorrect, this._onTap);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State createState() => new CorrectOverlayState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class CorrectOverlayState extends State<CorrectOverlay>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
late Animation<double> _iconAnimation;
|
||||||
|
late AnimationController _iconAnimationController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_iconAnimationController = new AnimationController(
|
||||||
|
duration: new Duration(seconds: 2), vsync: this);
|
||||||
|
_iconAnimation = new CurvedAnimation(
|
||||||
|
parent: _iconAnimationController, curve: Curves.elasticOut);
|
||||||
|
_iconAnimation.addListener(() => this.setState(() {}));
|
||||||
|
_iconAnimationController.forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_iconAnimationController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Material(
|
||||||
|
color: Colors.black54,
|
||||||
|
child: new InkWell(
|
||||||
|
onTap: () => widget._onTap(),
|
||||||
|
child: new Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
new Container(
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
color: Colors.white, shape: BoxShape.circle),
|
||||||
|
child: new Transform.rotate(
|
||||||
|
angle: _iconAnimation.value * 2 * math.pi,
|
||||||
|
child: new Icon(
|
||||||
|
widget._isCorrect == true ? Icons.done : Icons.clear,
|
||||||
|
size: _iconAnimation.value * 80.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
new Padding(
|
||||||
|
padding: new EdgeInsets.only(bottom: 20.0),
|
||||||
|
),
|
||||||
|
new Text(
|
||||||
|
widget._isCorrect == true ? "Correct!" : "Wrong!",
|
||||||
|
style: new TextStyle(color: Colors.white, fontSize: 30.0),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
245
lib/Screens/Puzzle/puzzle_piece.dart
Normal file
245
lib/Screens/Puzzle/puzzle_piece.dart
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class PuzzlePiece extends StatefulWidget {
|
||||||
|
final Image image;
|
||||||
|
final Size imageSize;
|
||||||
|
final int row;
|
||||||
|
final int col;
|
||||||
|
final int maxRow;
|
||||||
|
final int maxCol;
|
||||||
|
final Function bringToTop;
|
||||||
|
final Function sendToBack;
|
||||||
|
|
||||||
|
static PuzzlePiece fromMap(Map<String, dynamic> map) {
|
||||||
|
return PuzzlePiece(
|
||||||
|
image: map['image'],
|
||||||
|
imageSize: map['imageSize'],
|
||||||
|
row: map['row'],
|
||||||
|
col: map['col'],
|
||||||
|
maxRow: map['maxRow'],
|
||||||
|
maxCol: map['maxCol'],
|
||||||
|
bringToTop: map['bringToTop'],
|
||||||
|
sendToBack: map['SendToBack'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PuzzlePiece(
|
||||||
|
{Key? key,
|
||||||
|
required this.image,
|
||||||
|
required this.imageSize,
|
||||||
|
required this.row,
|
||||||
|
required this.col,
|
||||||
|
required this.maxRow,
|
||||||
|
required this.maxCol,
|
||||||
|
required this.bringToTop,
|
||||||
|
required this.sendToBack})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PuzzlePieceState createState() => _PuzzlePieceState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PuzzlePieceState extends State<PuzzlePiece> {
|
||||||
|
// the piece initial top offset
|
||||||
|
double? top;
|
||||||
|
// the piece initial left offset
|
||||||
|
double? left;
|
||||||
|
// can we move the piece ?
|
||||||
|
bool isMovable = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// the image width
|
||||||
|
final imageWidth = MediaQuery.of(context).size.width;
|
||||||
|
// the image height
|
||||||
|
final imageHeight = MediaQuery.of(context).size.height *
|
||||||
|
MediaQuery.of(context).size.width /
|
||||||
|
widget.imageSize.width;
|
||||||
|
final pieceWidth = imageWidth / widget.maxCol;
|
||||||
|
final pieceHeight = imageHeight / widget.maxRow;
|
||||||
|
|
||||||
|
if (top == null) {
|
||||||
|
top = Random().nextInt((imageHeight - pieceHeight).ceil()).toDouble();
|
||||||
|
var test = top!;
|
||||||
|
test -= widget.row * pieceHeight;
|
||||||
|
top = test;
|
||||||
|
}
|
||||||
|
if (left == null) {
|
||||||
|
left = Random().nextInt((imageWidth - pieceWidth).ceil()).toDouble();
|
||||||
|
var test = left!;
|
||||||
|
test -= widget.col * pieceWidth;
|
||||||
|
left = test;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Positioned(
|
||||||
|
top: top,
|
||||||
|
left: left,
|
||||||
|
width: imageWidth,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (isMovable) {
|
||||||
|
widget.bringToTop(widget);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onPanStart: (_) {
|
||||||
|
if (isMovable) {
|
||||||
|
widget.bringToTop(widget);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onPanUpdate: (dragUpdateDetails) {
|
||||||
|
if (isMovable) {
|
||||||
|
setState(() {
|
||||||
|
var testTop = top!;
|
||||||
|
var testLeft = left!;
|
||||||
|
testTop = top!;
|
||||||
|
testLeft = left!;
|
||||||
|
testTop += dragUpdateDetails.delta.dy;
|
||||||
|
testLeft += dragUpdateDetails.delta.dx;
|
||||||
|
top = testTop!;
|
||||||
|
left = testLeft!;
|
||||||
|
|
||||||
|
if (-10 < top! && top! < 10 && -10 < left! && left! < 10) {
|
||||||
|
top = 0;
|
||||||
|
left = 0;
|
||||||
|
isMovable = false;
|
||||||
|
widget.sendToBack(widget);
|
||||||
|
|
||||||
|
//ScoreWidget.of(context).allInPlaceCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: ClipPath(
|
||||||
|
child: CustomPaint(
|
||||||
|
foregroundPainter: PuzzlePiecePainter(
|
||||||
|
widget.row, widget.col, widget.maxRow, widget.maxCol),
|
||||||
|
child: widget.image),
|
||||||
|
clipper: PuzzlePieceClipper(
|
||||||
|
widget.row, widget.col, widget.maxRow, widget.maxCol),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this class is used to clip the image to the puzzle piece path
|
||||||
|
class PuzzlePieceClipper extends CustomClipper<Path> {
|
||||||
|
final int row;
|
||||||
|
final int col;
|
||||||
|
final int maxRow;
|
||||||
|
final int maxCol;
|
||||||
|
|
||||||
|
PuzzlePieceClipper(this.row, this.col, this.maxRow, this.maxCol);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Path getClip(Size size) {
|
||||||
|
return getPiecePath(size, row, col, maxRow, maxCol);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this class is used to draw a border around the clipped image
|
||||||
|
class PuzzlePiecePainter extends CustomPainter {
|
||||||
|
final int row;
|
||||||
|
final int col;
|
||||||
|
final int maxRow;
|
||||||
|
final int maxCol;
|
||||||
|
|
||||||
|
PuzzlePiecePainter(this.row, this.col, this.maxRow, this.maxCol);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
final Paint paint = Paint()
|
||||||
|
..color = Color(0x80FFFFFF)
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1.0;
|
||||||
|
|
||||||
|
canvas.drawPath(getPiecePath(size, row, col, maxRow, maxCol), paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is the path used to clip the image and, then, to draw a border around it; here we actually draw the puzzle piece
|
||||||
|
Path getPiecePath(Size size, int row, int col, int maxRow, int maxCol) {
|
||||||
|
final width = size.width / maxCol;
|
||||||
|
final height = size.height / maxRow;
|
||||||
|
final offsetX = col * width;
|
||||||
|
final offsetY = row * height;
|
||||||
|
final bumpSize = height / 4;
|
||||||
|
|
||||||
|
var path = Path();
|
||||||
|
path.moveTo(offsetX, offsetY);
|
||||||
|
|
||||||
|
if (row == 0) {
|
||||||
|
// top side piece
|
||||||
|
path.lineTo(offsetX + width, offsetY);
|
||||||
|
} else {
|
||||||
|
// top bump
|
||||||
|
path.lineTo(offsetX + width / 3, offsetY);
|
||||||
|
path.cubicTo(
|
||||||
|
offsetX + width / 6,
|
||||||
|
offsetY - bumpSize,
|
||||||
|
offsetX + width / 6 * 5,
|
||||||
|
offsetY - bumpSize,
|
||||||
|
offsetX + width / 3 * 2,
|
||||||
|
offsetY);
|
||||||
|
path.lineTo(offsetX + width, offsetY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (col == maxCol - 1) {
|
||||||
|
// right side piece
|
||||||
|
path.lineTo(offsetX + width, offsetY + height);
|
||||||
|
} else {
|
||||||
|
// right bump
|
||||||
|
path.lineTo(offsetX + width, offsetY + height / 3);
|
||||||
|
path.cubicTo(
|
||||||
|
offsetX + width - bumpSize,
|
||||||
|
offsetY + height / 6,
|
||||||
|
offsetX + width - bumpSize,
|
||||||
|
offsetY + height / 6 * 5,
|
||||||
|
offsetX + width,
|
||||||
|
offsetY + height / 3 * 2);
|
||||||
|
path.lineTo(offsetX + width, offsetY + height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row == maxRow - 1) {
|
||||||
|
// bottom side piece
|
||||||
|
path.lineTo(offsetX, offsetY + height);
|
||||||
|
} else {
|
||||||
|
// bottom bump
|
||||||
|
path.lineTo(offsetX + width / 3 * 2, offsetY + height);
|
||||||
|
path.cubicTo(
|
||||||
|
offsetX + width / 6 * 5,
|
||||||
|
offsetY + height - bumpSize,
|
||||||
|
offsetX + width / 6,
|
||||||
|
offsetY + height - bumpSize,
|
||||||
|
offsetX + width / 3,
|
||||||
|
offsetY + height);
|
||||||
|
path.lineTo(offsetX, offsetY + height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (col == 0) {
|
||||||
|
// left side piece
|
||||||
|
path.close();
|
||||||
|
} else {
|
||||||
|
// left bump
|
||||||
|
path.lineTo(offsetX, offsetY + height / 3 * 2);
|
||||||
|
path.cubicTo(
|
||||||
|
offsetX - bumpSize,
|
||||||
|
offsetY + height / 6 * 5,
|
||||||
|
offsetX - bumpSize,
|
||||||
|
offsetY + height / 6,
|
||||||
|
offsetX,
|
||||||
|
offsetY + height / 3);
|
||||||
|
path.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
149
lib/Screens/Puzzle/puzzle_view.dart
Normal file
149
lib/Screens/Puzzle/puzzle_view.dart
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:manager_api/api.dart';
|
||||||
|
import 'puzzle_piece.dart';
|
||||||
|
import 'score_widget.dart';
|
||||||
|
|
||||||
|
const IMAGE_PATH = 'image_path';
|
||||||
|
|
||||||
|
class PuzzleView extends StatefulWidget {
|
||||||
|
final SectionDTO? section;
|
||||||
|
PuzzleView({this.section});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PuzzleViewWidget createState() => _PuzzleViewWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PuzzleViewWidget extends State<PuzzleView> {
|
||||||
|
SliderDTO sliderDTO = SliderDTO();
|
||||||
|
final int rows = 3;
|
||||||
|
final int cols = 3;
|
||||||
|
|
||||||
|
//File? _image;
|
||||||
|
String? _imagePath;
|
||||||
|
List<Widget> pieces = [];
|
||||||
|
|
||||||
|
bool _overlayVisible = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
sliderDTO = SliderDTO.fromJson(jsonDecode(widget.section!.data!))!;
|
||||||
|
|
||||||
|
sliderDTO.images!.sort((a, b) => a.order!.compareTo(b.order!));
|
||||||
|
super.initState();
|
||||||
|
splitImage(Image.network(sliderDTO.images![1].source_!));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void savePrefs() async {
|
||||||
|
await prefs!.setString(IMAGE_PATH, _imagePath!);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*Future getImage(ImageSource source) async {
|
||||||
|
var image = await ImagePicker.platform.(source: source);
|
||||||
|
|
||||||
|
if (image != null) {
|
||||||
|
setState(() {
|
||||||
|
_image = image;
|
||||||
|
_imagePath = _image!.path;
|
||||||
|
pieces.clear();
|
||||||
|
ScoreWidget
|
||||||
|
.of(context)
|
||||||
|
.allInPlaceCount = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
splitImage(Image.file(image));
|
||||||
|
savePrefs();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// we need to find out the image size, to be used in the PuzzlePiece widget
|
||||||
|
Future<Size> getImageSize(Image image) async {
|
||||||
|
final Completer<Size> completer = Completer<Size>();
|
||||||
|
|
||||||
|
image.image
|
||||||
|
.resolve(const ImageConfiguration())
|
||||||
|
.addListener(ImageStreamListener((ImageInfo info, bool _) {
|
||||||
|
completer.complete(
|
||||||
|
Size(info.image.width.toDouble(), info.image.height.toDouble()));
|
||||||
|
}));
|
||||||
|
|
||||||
|
final Size imageSize = await completer.future;
|
||||||
|
|
||||||
|
return imageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// here we will split the image into small pieces
|
||||||
|
// using the rows and columns defined above; each piece will be added to a stack
|
||||||
|
void splitImage(Image image) async {
|
||||||
|
Size imageSize = await getImageSize(image);
|
||||||
|
|
||||||
|
for (int x = 0; x < rows; x++) {
|
||||||
|
for (int y = 0; y < cols; y++) {
|
||||||
|
setState(() {
|
||||||
|
pieces.add(
|
||||||
|
PuzzlePiece(
|
||||||
|
key: GlobalKey(),
|
||||||
|
image: image,
|
||||||
|
imageSize: imageSize,
|
||||||
|
row: x,
|
||||||
|
col: y,
|
||||||
|
maxRow: rows,
|
||||||
|
maxCol: cols,
|
||||||
|
bringToTop: this.bringToTop,
|
||||||
|
sendToBack: this.sendToBack,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// when the pan of a piece starts, we need to bring it to the front of the stack
|
||||||
|
void bringToTop(Widget widget) {
|
||||||
|
setState(() {
|
||||||
|
pieces.remove(widget);
|
||||||
|
pieces.add(widget);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// when a piece reaches its final position,
|
||||||
|
// it will be sent to the back of the stack to not get in the way of other, still movable, pieces
|
||||||
|
void sendToBack(Widget widget) {
|
||||||
|
setState(() {
|
||||||
|
pieces.remove(widget);
|
||||||
|
pieces.insert(0, widget);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
//savePrefs();
|
||||||
|
|
||||||
|
return SafeArea(
|
||||||
|
child: sliderDTO.images![0].source_! == null
|
||||||
|
? Center(child: Text('No image selected.'))
|
||||||
|
: Stack(
|
||||||
|
children: pieces,
|
||||||
|
),
|
||||||
|
); /*ScoreWidget
|
||||||
|
.of(context)
|
||||||
|
.allInPlaceCount ==
|
||||||
|
rows * cols
|
||||||
|
? Overlay(
|
||||||
|
initialEntries: [
|
||||||
|
OverlayEntry(builder: (context) {
|
||||||
|
return CorrectOverlay(true, () {
|
||||||
|
setState(() {
|
||||||
|
ScoreWidget
|
||||||
|
.of(context)
|
||||||
|
.allInPlaceCount = 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
],
|
||||||
|
)
|
||||||
|
:*/
|
||||||
|
}
|
||||||
|
}
|
||||||
14
lib/Screens/Puzzle/score_widget.dart
Normal file
14
lib/Screens/Puzzle/score_widget.dart
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ScoreWidget extends InheritedWidget {
|
||||||
|
ScoreWidget({Key? key, required Widget child}) : super(key: key, child: child);
|
||||||
|
|
||||||
|
int allInPlaceCount = 0;
|
||||||
|
|
||||||
|
static ScoreWidget of(BuildContext context) {
|
||||||
|
return context.dependOnInheritedWidgetOfExactType<ScoreWidget>() as ScoreWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool updateShouldNotify(ScoreWidget oldWidget) => false;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user