Skip to content

Instantly share code, notes, and snippets.

@wtoalabi
Created April 26, 2019 04:57
Show Gist options
  • Save wtoalabi/51a045ea6a541a7d6ba2aaca6db3dfad to your computer and use it in GitHub Desktop.
Save wtoalabi/51a045ea6a541a7d6ba2aaca6db3dfad to your computer and use it in GitHub Desktop.
class _BiblePageState extends State<BiblePage> {
final scrollDirection = Axis.vertical;
AutoScrollController controller;
@override
void initState() {
super.initState();
controller = AutoScrollController(
viewportBoundaryGetter: () => Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
axis: scrollDirection
);
}
@override
Widget build(BuildContext context) {
return ScopedModelDescendant<BibleScope>(
builder: (BuildContext context, _, BibleScope model) {
/*
I found that I needed to delay a bit to allow the widget to be built and applied to the controller before I can scroll to it.
The verseIndex has been set within the state, universally.
The idea is that before this page is accessed, the user likely needs a particular portion of it. The verse.
So, on the search result page...or wherever the user is coming from, I set the verseIndex right there before coming here.
When this page loads, _scrollToIndex(model.verseIndex ?? 1); just makes use of that digit or if not set, defaults to 1.
model.currentChapter is the List containing all the verses.
And each verse is wrapped in its own class with its unique ID within the List.
This is the verse class:
class Verse{
final int verseID;
final String text;
final String book;
final int chapterID;
*/
Future.delayed(Duration(milliseconds: 200), (){
_scrollToIndex(model.verseIndex ?? 1);
});
return model.currentChapter.isNotEmpty ? Container(
color: Theme.of(context).backgroundColor,
padding: EdgeInsets.all(4.0),
child: Column(
children: <Widget>[
Expanded(
child: ListView(
scrollDirection: scrollDirection,
controller: controller,
children: model.currentChapter.map((verse){
return ListTile(
title: _eachVerse(verse: verse)
);
}).toList(),
),
),
],
),
):CircularProgressIndicator();
},
);
}
_eachVerse({Verse verse}) {
return _wrapScrollTag(
index: verse.verseID,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(right: 5.0),
child: Text(verse.verseID.toString(), style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 17.0
),
),
),
Expanded(
child: Text(verse.text,style: TextStyle(fontSize: 14.0),),
)
],
)
);
}
_wrapScrollTag({int index, Widget child}) {
return AutoScrollTag(
key: ValueKey(index),
controller: controller,
index: index,
child: child,
highlightColor: Theme.of(context).selectedRowColor,
);
}
Future _scrollToIndex(int verseID) async {
await controller.scrollToIndex(verseID, preferPosition: AutoScrollPosition.begin);
controller.highlight(verseID);
}
}
/*
From the diagram of your app, maybe you could use the same structure?
Can you give each paragraph within the list a unique id...more like a index?
Then whenever a user clicks on a particular paragraph on the search results page, the id of that paragrapgh is registered in your state
as the 'current_paragraph within the list'
So that when they arrive, it page scrolls straight to its location.
Thats why I love the way the package adds highlights to the exact index on arrival.
It tells the user...hey...this is the paragraph you asked for.
*/
@wtoalabi
Copy link
Author

We can discuss specific issues concerning the implementation here...

@oseiasmribeiro
Copy link

I got something. I'm testing! Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment