I have an application that it’s showing some text on a background. Also i’m playing an audio that is reading that text. The video ratio is 16:9 so i have some problem in showing text alongside audio because some texts are large and i can’t show it on screen one-time.
what i should do to handle this?
I also tried this methods but haven’t fixed yet:
- created a ListView and scrolled each item when its audio completed
- created a ListView and calculated total duration of all audios and scrolled total list by that duration
- created a CarouselSlider and scrolled each item when its audio have been finished.
<code>
class _VideoMakerScreenState extends State<VideoMakerScreen> {
AudioPlayer? _audioPlayer = AudioPlayer();
StreamSubscription? playerListener;
ValueNotifier<int> currentSourehIndex = ValueNotifier(-1);
CarouselController _scrollController = CarouselController();
@override
Widget build(BuildContext context) {
const aspectRatio = 9 / 16;
final width = MediaQuery.of(context).size.width;
final ratioWidth = width;
final ratioHeight = width * aspectRatio;
return BlocProvider(
create: (context) {
final bloc = VideoMakerBloc(quranRepository);
bloc.add(PrepareVideoMaker(
widget.soureh,
widget.sourehItems[++currentSourehIndex.value],
widget.sourehItems));
return bloc;
},
child: BlocConsumer<VideoMakerBloc, VideoMakerState>(
listenWhen: (previous, current) =>
current is VideoMakerPrepared ||
current is VideoMakerPlayAudioState ||
current is VideoMakerError,
listener: (context, state) async {
if (state is VideoMakerPrepared) {
await _audioPlayer?.setFilePath(state.audioSource);
_audioPlayer?.play();
_scrollController.jumpToPage(0);
playerListener = _audioPlayer?.playbackEventStream.listen((state) {
if (state.processingState == ProcessingState.completed &&
widget.sourehItems.isNotEmpty) {
if (currentSourehIndex.value >= widget.sourehItems.length) {
releasePlayer();
currentSourehIndex.value = -1;
return;
}
currentSourehIndex.value++;
if (currentSourehIndex.value < widget.sourehItems.length) {
BlocProvider.of<VideoMakerBloc>(context).add(
VideoMakerPlayAudio(
widget.soureh,
widget.sourehItems[currentSourehIndex.value],
),
);
} else {
releasePlayer();
currentSourehIndex.value = -1;
return;
}
}
});
} else if (state is VideoMakerPlayAudioState) {
duration = await _audioPlayer?.setFilePath(state.audioSource);
_audioPlayer?.play();
_scrollController.animateToPage(
currentSourehIndex.value,
duration: duration,
);
} else if (state is VideoMakerError) {
showSnackBar(context, state.appException.message);
}
},
buildWhen: (previous, current) =>
current is VideoMakerPrepared || current is VideoMakerLoading,
builder: (context, state) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: SizedBox(
width: ratioWidth,
height: ratioHeight,
child: Center(
child: state is VideoMakerPrepared
? Stack(
children: [
Assets.videos.back.image(
width: ratioWidth,
height: ratioHeight,
),
Center(
child: Container(
width: 150,
height: 100,
child: CarouselSlider.builder(
carouselController: _scrollController,
itemBuilder: (context, index, spad) {
if (index < widget.sourehItems.length)
return ValueListenableBuilder(
builder: (context, value, child) {
return AnimatedOpacity(
opacity:
currentSourehIndex.value ==
index
? 1
: 0,
duration:
Duration(milliseconds: 250),
child: Container(
color: Colors.transparent,
alignment: Alignment.center,
child: Text(
widget.sourehItems[index]
.arabic +
"(${widget.sourehItems[index].chapter.arabicNumber})",
textAlign: TextAlign.center,
textDirection:
TextDirection.rtl,
style: TextStyle(
color: Colors.white,
fontFamily:
FontFamily.nabi,
fontSize: 14,
),
),
),
);
},
valueListenable: currentSourehIndex,
);
else
return Container(
height: 50,
);
},
itemCount: widget.sourehItems.length + 1,
options: CarouselOptions(
scrollDirection: Axis.vertical),
),
),
),
],
)
: const CircularProgressIndicator(),
),
),
),
],
),
);
},
),
);
}
</code>
<code>
class _VideoMakerScreenState extends State<VideoMakerScreen> {
AudioPlayer? _audioPlayer = AudioPlayer();
StreamSubscription? playerListener;
ValueNotifier<int> currentSourehIndex = ValueNotifier(-1);
CarouselController _scrollController = CarouselController();
@override
Widget build(BuildContext context) {
const aspectRatio = 9 / 16;
final width = MediaQuery.of(context).size.width;
final ratioWidth = width;
final ratioHeight = width * aspectRatio;
return BlocProvider(
create: (context) {
final bloc = VideoMakerBloc(quranRepository);
bloc.add(PrepareVideoMaker(
widget.soureh,
widget.sourehItems[++currentSourehIndex.value],
widget.sourehItems));
return bloc;
},
child: BlocConsumer<VideoMakerBloc, VideoMakerState>(
listenWhen: (previous, current) =>
current is VideoMakerPrepared ||
current is VideoMakerPlayAudioState ||
current is VideoMakerError,
listener: (context, state) async {
if (state is VideoMakerPrepared) {
await _audioPlayer?.setFilePath(state.audioSource);
_audioPlayer?.play();
_scrollController.jumpToPage(0);
playerListener = _audioPlayer?.playbackEventStream.listen((state) {
if (state.processingState == ProcessingState.completed &&
widget.sourehItems.isNotEmpty) {
if (currentSourehIndex.value >= widget.sourehItems.length) {
releasePlayer();
currentSourehIndex.value = -1;
return;
}
currentSourehIndex.value++;
if (currentSourehIndex.value < widget.sourehItems.length) {
BlocProvider.of<VideoMakerBloc>(context).add(
VideoMakerPlayAudio(
widget.soureh,
widget.sourehItems[currentSourehIndex.value],
),
);
} else {
releasePlayer();
currentSourehIndex.value = -1;
return;
}
}
});
} else if (state is VideoMakerPlayAudioState) {
duration = await _audioPlayer?.setFilePath(state.audioSource);
_audioPlayer?.play();
_scrollController.animateToPage(
currentSourehIndex.value,
duration: duration,
);
} else if (state is VideoMakerError) {
showSnackBar(context, state.appException.message);
}
},
buildWhen: (previous, current) =>
current is VideoMakerPrepared || current is VideoMakerLoading,
builder: (context, state) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: SizedBox(
width: ratioWidth,
height: ratioHeight,
child: Center(
child: state is VideoMakerPrepared
? Stack(
children: [
Assets.videos.back.image(
width: ratioWidth,
height: ratioHeight,
),
Center(
child: Container(
width: 150,
height: 100,
child: CarouselSlider.builder(
carouselController: _scrollController,
itemBuilder: (context, index, spad) {
if (index < widget.sourehItems.length)
return ValueListenableBuilder(
builder: (context, value, child) {
return AnimatedOpacity(
opacity:
currentSourehIndex.value ==
index
? 1
: 0,
duration:
Duration(milliseconds: 250),
child: Container(
color: Colors.transparent,
alignment: Alignment.center,
child: Text(
widget.sourehItems[index]
.arabic +
"(${widget.sourehItems[index].chapter.arabicNumber})",
textAlign: TextAlign.center,
textDirection:
TextDirection.rtl,
style: TextStyle(
color: Colors.white,
fontFamily:
FontFamily.nabi,
fontSize: 14,
),
),
),
);
},
valueListenable: currentSourehIndex,
);
else
return Container(
height: 50,
);
},
itemCount: widget.sourehItems.length + 1,
options: CarouselOptions(
scrollDirection: Axis.vertical),
),
),
),
],
)
: const CircularProgressIndicator(),
),
),
),
],
),
);
},
),
);
}
</code>
class _VideoMakerScreenState extends State<VideoMakerScreen> {
AudioPlayer? _audioPlayer = AudioPlayer();
StreamSubscription? playerListener;
ValueNotifier<int> currentSourehIndex = ValueNotifier(-1);
CarouselController _scrollController = CarouselController();
@override
Widget build(BuildContext context) {
const aspectRatio = 9 / 16;
final width = MediaQuery.of(context).size.width;
final ratioWidth = width;
final ratioHeight = width * aspectRatio;
return BlocProvider(
create: (context) {
final bloc = VideoMakerBloc(quranRepository);
bloc.add(PrepareVideoMaker(
widget.soureh,
widget.sourehItems[++currentSourehIndex.value],
widget.sourehItems));
return bloc;
},
child: BlocConsumer<VideoMakerBloc, VideoMakerState>(
listenWhen: (previous, current) =>
current is VideoMakerPrepared ||
current is VideoMakerPlayAudioState ||
current is VideoMakerError,
listener: (context, state) async {
if (state is VideoMakerPrepared) {
await _audioPlayer?.setFilePath(state.audioSource);
_audioPlayer?.play();
_scrollController.jumpToPage(0);
playerListener = _audioPlayer?.playbackEventStream.listen((state) {
if (state.processingState == ProcessingState.completed &&
widget.sourehItems.isNotEmpty) {
if (currentSourehIndex.value >= widget.sourehItems.length) {
releasePlayer();
currentSourehIndex.value = -1;
return;
}
currentSourehIndex.value++;
if (currentSourehIndex.value < widget.sourehItems.length) {
BlocProvider.of<VideoMakerBloc>(context).add(
VideoMakerPlayAudio(
widget.soureh,
widget.sourehItems[currentSourehIndex.value],
),
);
} else {
releasePlayer();
currentSourehIndex.value = -1;
return;
}
}
});
} else if (state is VideoMakerPlayAudioState) {
duration = await _audioPlayer?.setFilePath(state.audioSource);
_audioPlayer?.play();
_scrollController.animateToPage(
currentSourehIndex.value,
duration: duration,
);
} else if (state is VideoMakerError) {
showSnackBar(context, state.appException.message);
}
},
buildWhen: (previous, current) =>
current is VideoMakerPrepared || current is VideoMakerLoading,
builder: (context, state) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: SizedBox(
width: ratioWidth,
height: ratioHeight,
child: Center(
child: state is VideoMakerPrepared
? Stack(
children: [
Assets.videos.back.image(
width: ratioWidth,
height: ratioHeight,
),
Center(
child: Container(
width: 150,
height: 100,
child: CarouselSlider.builder(
carouselController: _scrollController,
itemBuilder: (context, index, spad) {
if (index < widget.sourehItems.length)
return ValueListenableBuilder(
builder: (context, value, child) {
return AnimatedOpacity(
opacity:
currentSourehIndex.value ==
index
? 1
: 0,
duration:
Duration(milliseconds: 250),
child: Container(
color: Colors.transparent,
alignment: Alignment.center,
child: Text(
widget.sourehItems[index]
.arabic +
"(${widget.sourehItems[index].chapter.arabicNumber})",
textAlign: TextAlign.center,
textDirection:
TextDirection.rtl,
style: TextStyle(
color: Colors.white,
fontFamily:
FontFamily.nabi,
fontSize: 14,
),
),
),
);
},
valueListenable: currentSourehIndex,
);
else
return Container(
height: 50,
);
},
itemCount: widget.sourehItems.length + 1,
options: CarouselOptions(
scrollDirection: Axis.vertical),
),
),
),
],
)
: const CircularProgressIndicator(),
),
),
),
],
),
);
},
),
);
}
Note 1: The texts are for Quran and audio is reading each part of a Soureh.
Note 2: The text should show in the center of screen and only reading text should be visible and i hide others.