I am making a game where users can drag some portion - which is highligted with RED in the image - of String while not hurting rest of the String. To specify which text can be draggable, I encoded draggable portion in this format: x{String}x. And I decoded it in _constructGame function. I expected a well-organized String but it turns out it didn't happen. I encountered with a logical error, rather than a system error. But I can't just figure out. I tried making research but they are irrelevant with my issue.
To reach my goal, I also used a list of widget that goes like fixed text, draggable portion, fixed text, ...
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:schoolproject/GameTextList.dart';
class GameRoute extends StatefulWidget {
@override
State<StatefulWidget> createState() => _GameRouteState();
}
class _GameRouteState extends State<GameRoute>{
// Random().nextInt(GameTextList.texts.length)
String gameText = GameTextList.texts[0];
Draggable _createDraggableText(String text) {
return Draggable<String>(
data: text,
child: Text(
text,
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.red),
),
feedback: Text(
text,
style: TextStyle(fontSize: 16.0,fontWeight: FontWeight.bold, color: Colors.red),
),
childWhenDragging: Text(
text,
style: TextStyle(color: Colors.grey),
),
);
}
// Precondition: There must be at least one draggable
List<Widget> _constructGame(String mes) {
List<Widget> widgets = <Widget>[];
// Decode the message
int i = 0;
int j = 0;
while (i != mes.length - 1) {
if (mes[i] == "x" && mes[i 1] == "{") {
var last = mes.indexOf("}x", i);
widgets.add(Text(mes.substring(j, i))); // Bugün hava çok
widgets.add(_createDraggableText(mes.substring(i 2, last))); // soğuktu
j = last 2;
}
i ;
}
// add the remaining part of the text
widgets.add(Text(mes.substring(j, mes.length)));
return widgets;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Egzersiz")),
body: Wrap(
children: _constructGame(gameText),
)
);
}
}
class GameTextList {
static List<String> texts = [
"Bugün hava çok x{soğuktuuuuuuuuuuuuuuu}x. Fakat üstümüze mont giymeyi x{unuttuk}x. Şu an yağmur x{yağıyor}x. Son zamanlarda"
" hava düzensiz olabileceğinden tedbirli olmak x{gerekecekmiş}x.",
"Planktonların varlığı ekosistem için x{mühimdir}x hatta onlar x{olmasaydı}x Dünyadaki canlıların bir çoğu yok "
"x{olurdu}x. Nitekim bu canlılar atmosferdeki oksijenin P'sini x{oluştururlar}x. Yine de insanlar bilinçsizce"
" denize atık bırakmaya devam x{ederse}x solunulacak bir x{kalmayacak}x.",
"Uranyumun keşfedildiği tarih x{1789'dur}x.",
"""
Yapma x{ne olursun}x, bırak o yerimi x{doldursun}x. Bana ihtiyacın x{olursa}x sarıl ona, elbet x{unutursun}x.x{Girmişşe}x kalbine bambaşka biri...""",
];
}
CodePudding user response:
after analyse your code, I made some changes in _constructGame
in your method now its working. i simply debug and identify that you need add only one word at time in widgets list just like you do for extract x{Draggable Word}x
.so i add code for normal string & commented old lines for the same.
Added code:
final noramlStringArray = normalString.split(" ");
noramlStringArray.asMap().forEach((index, word) {
if (index != (noramlStringArray.length - 1)) {
widgets.add(Text("$word ")); // add word with trailing space
} else {
widgets.add(Text(word)); // add last word without space
}
});
Added String extension
for remove extra white spaces if string contains double or more spaces which replace with single white space.
extension on String {
String removeExtraWhiteSpace() {
return replaceAll(RegExp("[ \t\r\f]"), " ");
}
}
used removeExtraWhiteSpace() extension in below line.
_constructGame(gameText.removeExtraWhiteSpace())
replace your _constructGame
method with below code.
// Precondition: There must be at least one draggable
List<Widget> _constructGame(String mes) {
List<Widget> widgets = <Widget>[];
try {
// Decode the message
int i = 0;
int j = 0;
while (i != mes.length - 1) {
if (mes[i] == "x" && mes[i 1] == "{") {
var last = mes.indexOf("}x", i);
final normalString = mes.substring(j, i);
final noramlStringArray = normalString.split(" ");
noramlStringArray.asMap().forEach((index, word) {
if (index != (noramlStringArray.length - 1)) {
widgets.add(Text("$word ")); // add word with trailing space
} else {
widgets.add(Text(word)); // add last word without space
}
});
//widgets.add(Text(mes.substring(j, i))); // Bugün hava çok
widgets
.add(_createDraggableText(mes.substring(i 2, last))); // soğuktu
j = last 2;
}
i ;
}
// add the remaining part of the text
//widgets.add(Text(mes.substring(j, mes.length)));
final normalString = mes.substring(j, mes.length);
final noramlStringArray = normalString.split(" ");
noramlStringArray.asMap().forEach((index, word) {
if (index != (noramlStringArray.length - 1)) {
widgets.add(Text("$word "));
} else {
widgets.add(Text(word));
}
});
return widgets;
} catch (ex) {
debugPrint("Error: $ex");
return widgets;
}
}
if your word will not set in remain width then only it will set in newline automatically.