'Find the width of every single item in list in flutter
I need to develope feature which paint the text by syllables (like screenshot shows). Bows and dots represent syllables (dot - 1 letter syllable, bow - 2 letter syllable). The painting is provided by dragging of green slider.
There is a variant of getting syllable position with the help of GlobalKey. I use the method List.generate for creating numerous GlobalKeys but get the exception Multiple widgets used the same GlobalKey. How can help me to resolve this task?
There is method for creating Row of Columns which include letter and bow or dot.
List<Widget> createDotAndBows(String sentence, List<GlobalKey> keys) {
DetailedScreenBloc _bloc = DetailedScreenBloc();
List<String> syllablesRow = [];
List<Widget> dotAndBows = [];
List<String> splittedText = sentence.split(' ');
for (int i = 0; i < splittedText.length; i++) {
syllablesRow.addAll(_bloc.syllables(splittedText[i]));
}
_syllablesTotal.add(syllablesRow.length);
for (int index = 0; index < syllablesRow.length; index++) {
dotAndBows.add(
(syllablesRow[index] != ' ')
? IntrinsicWidth(
key: keys[index],
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.only(
bottom: FairyTaleSizes.tinyPadding4,
),
child: Text(
syllablesRow[index],
style: FairyTaleStyle(
fontWeight: FontWeight.w800,
fontSize: getProportionateScreenWidth(22),
color: FairyTaleColors.fullBlack,
),
textAlign: TextAlign.center,
maxLines: 1,
),
),
(_bloc.getSyllableType(syllablesRow[index]) == 2)
? Padding(
padding: const EdgeInsets.symmetric(
horizontal: FairyTaleSizes.theMostTinyPadding2,
),
child: CustomPaint(
painter: BowPainter(),
child: Center(
child: Container(
height: getProportionateScreenHeight(20),
),
),
),
)
: (_bloc.getSyllableType(syllablesRow[index]) == 1)
? Center(
child: Container(
height: getProportionateScreenHeight(23),
width: getProportionateScreenHeight(23),
decoration:
const BoxDecoration(shape: BoxShape.circle, color: FairyTaleColors.fullBlack),
),
)
: Container(),
],
),
),
)
: Text(
' ',
key: keys[index],
),
);
}
return dotAndBows;
}
This is the implementation of the method above in UI
class DetailedScreen extends StatefulWidget {
final String? detailedBanner;
final List<String>? fullText;
const DetailedScreen({this.detailedBanner, this.fullText});
@override
State<DetailedScreen> createState() => _DetailedScreenState();
}
class _DetailedScreenState extends State<DetailedScreen> {
final ItemScrollController _itemScrollController = ItemScrollController();
final ItemPositionsListener _itemPositionsListener = ItemPositionsListener.create();
int currentIndex = 1;
final _bloc = DetailedScreenBloc();
List<GlobalKey> keysList = [];
final GlobalKey _sliderKey = GlobalKey();
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
_bloc.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
child: Stack(
children: <Widget>[
Container(
width: SizeConfig.screenWidth,
height: SizeConfig.screenHeight,
decoration: const BoxDecoration(
color: FairyTaleColors.lightGold,
),
),
Column(
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
height: SizeConfig.screenHeight / 2,
width: SizeConfig.screenWidth,
decoration: BoxDecoration(
image: DecorationImage(
image: Image.asset(widget.detailedBanner ?? '').image,
fit: BoxFit.fitWidth,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: ArrowWidget(
height: getProportionateScreenHeight(84),
width: getProportionateScreenWidth(36),
isForward: false,
onTap: () => Navigator.of(context).pop(),
),
),
StreamBuilder<bool>(
stream: _bloc.isVoiceOnStream,
builder: (context, snapshot) {
bool? _isVoiceOn = snapshot.data;
return Padding(
padding: const EdgeInsets.only(
right: FairyTaleSizes.bigHorizontalPadding36,
),
child: Align(
alignment: Alignment.topRight,
child: VoiceSwitcher(
isVoiceOn: _isVoiceOn,
onPressed: () {
if (_isVoiceOn != null && _isVoiceOn) {
_bloc.switchVoice(false);
} else {
_bloc.switchVoice(true);
}
}),
),
);
}),
],
),
),
),
Padding(
padding: const EdgeInsets.only(
top: FairyTaleSizes.middleHorizontalPadding22,
),
child: Stack(
children: [
StreamBuilder<int>(
stream: _bloc.syllablesTotalStream,
builder: (context, snapshot) {
return SizedBox(
height: MediaQuery.of(context).size.height,
child: ScrollablePositionedList.builder(
shrinkWrap: true,
padding: const EdgeInsets.only(
bottom: FairyTaleSizes.twoHundredPadding216,
),
physics: const NeverScrollableScrollPhysics(),
itemScrollController: _itemScrollController,
itemPositionsListener: _itemPositionsListener,
itemCount: widget.fullText!.length,
itemBuilder: (_, index) {
int total = snapshot.data ?? 0;
keysList.addAll(
List.generate(
total,
(index) => GlobalKey(),
),
);
print('$index - $keysList');
return Container(
padding: const EdgeInsets.only(
bottom: FairyTaleSizes.itemsMassivePadding140,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _bloc.createDotAndBows(
widget.fullText![index],
keysList,
),
),
);
},
),
);
}),
StreamBuilder<double>(
initialData: 0.0,
stream: _bloc.shadowPositionStream,
builder: (context, snapshot) {
double _position = snapshot.data ?? 0.0;
return Positioned(
left: _position,
child: Container(
color: FairyTaleColors.lightGold.withOpacity(0.9),
height: getProportionateScreenWidth(23),
width: MediaQuery.of(context).size.width,
),
);
}),
StreamBuilder<List>(
stream: CombineLatestStream.list([
_bloc.sliderValueStream,
_bloc.shadowPositionStream,
]),
builder: (context, snapshot) {
double _sliderValue = snapshot.data?[0] ?? 0.0;
double _shadowPosition = snapshot.data?[1] ?? 0.0;
return Padding(
padding: const EdgeInsets.symmetric(
vertical: FairyTaleSizes.hundredPadding100,
horizontal: FairyTaleSizes.massivePadding64,
),
child: SliderTheme(
data: const SliderThemeData(
trackShape: GradientRectSliderTrackShape(),
trackHeight: 14.0,
thumbShape: GradientSliderThumbShape(
enabledThumbRadius: 16,
pressedElevation: 5.1,
),
),
child: Slider(
key: _sliderKey,
min: 0.0,
max: 200.0,
value: _sliderValue,
inactiveColor: FairyTaleColors.inactiveGrey,
onChanged: (value) {
_sliderValue = value;
_shadowPosition = value * 4.5;
_bloc.changeSliderValue(_sliderValue);
_bloc.stepBySyllable(keysList);
// _bloc.changeShadowPosition(_shadowPosition);
},
onChangeEnd: (value) {
if (value == 200) {
keysList.clear();
_bloc.changeSliderValue(0.0);
_shadowPosition = 0;
_bloc.scrollString(_itemScrollController, currentIndex);
_bloc.changeShadowPosition(0.0);
currentIndex++;
}
},
),
),
);
}),
],
),
),
],
),
],
),
),
),
);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
