flutter : 무한 스크롤을위한 TabController의 NotificationListener
4 개의 탭이 있고 여기에 지연로드 또는 무한 스크롤 옵션을 추가하고 싶습니다. 이전에 Scroll Controller로 시도했지만 끝에 도달했을 때. 이벤트가 두 번 이상 발생합니다. 따라서 API에 대한 여러 Future http 요청이 있습니다.
그래서 몇 가지 질문을 읽고 NotificationListener를 사용해야 할 수도 있음을 알았습니다. 한 번 또는 모든 탭에 대해 정의해야할지 모르겠습니다. NotificationListener를 사용하는 방법을 모릅니다.
class _Searchstate extends State<Search> with SingleTickerProviderStateMixin{
ScrollController _scrollController = new ScrollController();
final _scaffoldKey = GlobalKey<ScaffoldState>();
TabController _controller;
TabBarView(
controller: _controller,
children: [
// Text("TAB ONE CONTENT"),
RefreshIndicator(
onRefresh: refreshData,
child:Container(
decoration: BoxDecoration(
color: Colors.black87,
),
padding: EdgeInsets.only(top: 10, bottom: 5),
height: MediaQuery.of(context).size.height,
width: double.infinity,
child: ListView.builder(
controller: _scrollcontroller,
itemCount: (recommended) ? lists.length : searchlists.length,
itemBuilder: (BuildContext context, int index) {
return buildList1(context, index);
}),
),
),
//Text("TAB TWO CONTENT"),
RefreshIndicator(
onRefresh: refreshData1,
child:Container(
decoration: BoxDecoration(
color: Colors.black54,
),
padding: EdgeInsets.only(top: 10, bottom: 5),
height: MediaQuery.of(context).size.height,
width: double.infinity,
child: ListView.builder(
controller: _scrollcontroller,
itemCount: (nearme) ? lists1.length : searchlists1.length,
itemBuilder: (BuildContext context, int index) {
return buildList2(context, index);
}),
),
),
아래는 Listview.Builder를 사용하여 데이터베이스에서 오는 데이터를 표시하는 buildList입니다. 나는 이것도 아래와 같이 ScrollController를 사용하려고했습니다.
Widget buildList1(BuildContext context, int index) {
_scrollController.addListener((){
print(_scrollController.position.pixels);
print(_scrollController.position.maxScrollExtent);
if(_scrollController.position.pixels == _scrollController.position.maxScrollExtent){
print(recommended);
if(recommended){
//getData();
print('getData()1;');
}
// getData();
}
});
전체 코드가 매우 길기 때문에이 질문에만 관련 코드를 추가했습니다. 더 많은 코드가 필요하면 알려주세요.
편집하다:
나는 알림 리스너를 사용해 보았고 SCaffold 주위에 한 번 정의하면 적어도 스크롤 이벤트를 볼 수 있지만 4 개의 탭이 있으며 어떻게 모두를 구현할 수 있는지 잘 모르겠습니다. 4 개의 탭 모두에 대한 조건을 설정하는 것은 매우 어렵 기 때문입니다.
@override
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
child:Scaffold(
---- -- - - - - - More Codes -----
onNotification: (notificationInfo) {
if (notificationInfo is ScrollEndNotification) {
print("scroll");
print("detail:"+notificationInfo.dragDetails.toString());
/// your code
}
return true;
},
);
동일한 코드를 탭 안에 넣으려고했지만 스크롤 이벤트를 감지하지 못합니다.
답변
나는 그것을 작동시킬 수 있었지만 이것이 효율적인 방법인지 확실하지 않습니다. 비슷한 문제에 직면했을 수도있는 다른 사람들이 될 수도 있습니다.
아래 코드는 활성 탭을 식별하는 데 도움이됩니다.
void initState(){
_controller = TabController(vsync: this, length: 4);
currentTab = (_controller.index);
_controller.addListener(() {
if(_controller.indexIsChanging) {
print("tab is animating. from active (getting the index) to inactive(getting the index) ");
}else {
//tab is finished animating you get the current index
print(_controller.index);
currentTab = (_controller.index);
_handleTabSelection();
}
});
코드 아래에 NotificationListner에 추가했습니다.
onNotification: (notificationInfo) {
if (notificationInfo is ScrollEndNotification && notificationInfo.metrics.pixels == notificationInfo.metrics.maxScrollExtent) {
print("scroll");
if(currentTab == 0){
if(recommended == true && tab0 == 'Suggested' ){
// getData();
print('fire the 1 event');
}else{
print('Name()1;');
}
}
if(currentTab == 1){
if(nearme == true && tab1 == 'Near Me'){
//getData();
print('fire the 2nd event ');
}else{
}
}
if(currentTab == 2){
if(byRating == true && tab2 == 'By Rating'){
//getData();
print('fire the 3rd event');
}else{
}
}
if(currentTab == 3){
if(byprice == true && tab3 == 'Active'){
//getData();
print('fire the 4 event');
}else{
}
}
/// your code
}
return true;
},
);
편집 : 여러 탭이 있으므로 위의 코드가 왼쪽 및 오른쪽 스크롤에서도 실행됩니다. 이를 방지하기 위해 코드를 아래와 같이 변경했습니다.
if (notificationInfo is ScrollEndNotification && notificationInfo.metrics.axisDirection == AxisDirection.down && notificationInfo.metrics.pixels == notificationInfo.metrics.maxScrollExtent) {