how to go back to previous page when refresh the screen in pageview flutter - flutter

I want to keep the current page, when i refersh the screen or navigating back in page view
here is the code , actually i want display the particular index screen programmatically with out clicking the button. Some times iam getting controller.hasClients getting empty. If page view has 3 screens , if iam on 2ndscreen when i refresh the second screen should display second screen, instead it always display 1st screen . Iam using page controller to display , but not able to instantiate page controller becacuse i want to access from top widgets of page view. Please help
Container(
// width: 370,
height: MediaQuery.of(context).size.height * 0.685,
child: Stack(children: <Widget>[
_pages(),
Stack(
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Container(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
for (int i = 0; i < 3; i++)
(i == currentPage
? circleBar(true)
: circleBar(false))
],
),
),
),
],
),
]),
),
Widget _pages() {
List _pagesList = [
FirstScreen(
),
SecondScreen(
),
ThirdScreen(
),
];
return PageView.builder(
controller: _pageController,
itemCount: _pagesList.length,
// restorationId: currentPage.toString(),
itemBuilder: (BuildContext context, int index) {
// _pageController=PageController(initialPage: currentPage);
return _pagesList[index];
},
onPageChanged: (int page) {
setState(() {
currentPage = page;
selected = analyticsList[currentPage].anlyticName;
isIndexChanged = true;
page;
});
},
);
}

For a named route, you can use this code.
Navigator.pushNamed(context, '/screen2').then((_) {
// This block runs when you have returned back from screen 2.
setState(() {
// code here to refresh data
});
});

first saving the current page and instantiating page controller in pages() it worked for me
i just instantiated the page controller in pages() in my code as if declare on the top it is not getting read every refresh so i declared where the pageview get build .
Widget _pages() {
_pageController= PageController(initialPage: currentPage, keepPage: true);
List _pagesList = [
FirstScreen(
),
SecondScreen(
),
ThirdScreen(
),
];
return PageView.builder(
controller: _pageController,
itemCount: _pagesList.length,
// restorationId: currentPage.toString(),
itemBuilder: (BuildContext context, int index) {
return _pagesList[index];
},
onPageChanged: (int page) {
setState(() {
currentPage = page;
selected = analyticsList[currentPage].anlyticName;
isIndexChanged = true;
page;
});
},
);
}

Related

How to handle *CUSTOM* back button on Flutter with *BOTTOM NAVIGATION BAR*?

I have a bottom navigation bar in flutter:
class _HomeState extends State<Home> {
int index = 1;
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: CurvedNavigationBar(
index: index,
items: barItems,
onTap: (index) {
setState(() {
this.index = index;
});
...
...
);
}
}
where barItems is a list of widgets.
One of the screens of the navigation bar is routing to a different screen, which a would like to make a custom back button to the previous screen:
GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
padding: const EdgeInsets.all(5),
children: _allSongs.map((currentSong) {
return InkWell(
onTap: ()=> Navigator.pushReplacementNamed(context, '/singleSong', arguments: currentSong),
...
...)
On that new screen I have a cutom back button:
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(left: 10),
child: IconButton(
onPressed: () {
**Navigator.of(context).pop();**
},
icon: const Icon(Icons.arrow_back_ios))),
I added all the necassary routes as well, but when that button is clicked all I get is a blank black screen.
Any help?
Thanks
In the new page, you are using Navigator.pushReplacementNamed(context, '/singleSong', arguments: currentSong) to go to new page. At the same time, it also replaces the main route ("/") with the new route ("/singleSong").
If you try to go back from there, there would not be any route available for you as you have made "/singleSong" as the main route.
so, instead of
Navigator.pushReplacementNamed(context, '/singleSong', arguments: currentSong)
you should use
Navigator.pushNamed(context, '/singleSong', arguments: currentSong)

Flutter Chat Reply to Message

I'm trying to build a Chat UI with ListView. My first version was a ListView.build that works fine.
I want to upgrade my chat view for "replyTo message" option (similar to whatsapp). This requires the user to be able to click the "replyTo" message and scroll backwards to the original message. The ListView.build does not allow to scroll up to a message that is outside the screen view (as it is not even built).
body: Column(
children: [
Expanded(
child: EasyRefresh.custom(
...
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
ChatMessage _currMsg = vm.chat[index]!;
...
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
...
SwipeTo(
onRightSwipe: () {
setState(() {
isReplying = true;
replyMessage = _currMsg;
});
},
child: ShowMessage(
key: Key(_currMsg.id!),
msg: _currMsg,
myMessage: _currMsg.postById == vm.user!.uid,
onTapReply: (id) async {
final ctx = _itemKey.currentContext;
if (ctx != null)
await Scrollable.ensureVisible(ctx);
},
),
),
],
);
},
childCount: vm.chat.length,
),
),
],
),
),
It seems like the only way is to build all the list items at first build itself.
My question is, is there a way I can retain the already built items, and only add new incoming items rather than rebuilding all items every time.
Thanks.

Flutter how to show/hide container in specing listview

I am showing my data in ListView.builder issue is i need to show/Hide widget in specific list but its applying on all list.
My code
ListView.builder(
itemCount: 3,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
print('show');
setState(() {
showQty = !showQty;
});
},
child: Column(
children: [
Text('Always'),
showQty ? Text('onClick') : Container()
],
),
);
})
You can see I have 2 Text. Second Text I am showing when showQty is true its working fine but issue is its changing on all itemBuilder I need to show only on which item its clicking right now its applying on all.
Its because you are applying click to all the items of list view. For implementing collapse and show on click you have apply bool to the specific index of list. Try as follows
List<bool> showQty=[];
#override
void initState() {
super.initState();
for(int i=0;i<data.length;i++){
showQty.add(false);
}
}
void showHide(int i){
setState((){
showQty[i]=!showQty[i];
});
}
ListView.builder(
itemCount: data.length,
shrinkWrap:true,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
print('show');
showHide( index);
},
child: Column(
children: [
Text('Always'),
showQty[index] ? Text('onClick') : Container()
],
),
);
}
)
For show and hide widget you can use Visibility widget.
For more info about Visibility
Hopefully can help you.

Flutter - Add Layers on top of ListView to scroll

I am making a reader app and I have a ListView.builder which is loading multiple Images from the API. Now I want to add a layer on top of the ListView with 2 transparent containers so that when I click the left container the list goes up and when I click the right container the list goes down. I tried adding the ListView to stack but then the scrolling ability of the list is gone. This is my code so far:
return Scaffold(
body: Stack(
children: [
ListView.builder(
controller: _scrollViewController,
cacheExtent: 1000,
itemCount: _picLinkMap.length,
itemBuilder: (BuildContext ctx, int index) {
return buildImageLoader(
_picLinkMap[index], index + 1);
},
),
Row(
children: [
GestureDetector(
child: Container(
width: mySize.width * 0.5,
color: Colors.black38,
),
onTap: () {
print("Tap Left");
},
),
GestureDetector(
child: Container(
width: mySize.width * 0.5,
color: Colors.red.withOpacity(0.5),
),
onTap: () {
print("Tap RIGHT");
},
),
],
),
],
),
);
I only want to scroll about half the height of the screen on tap.
I searched the web but did not find a suitable solution.
ScrollController _scrollViewController = ScrollController();
...
var jumpTo = (MediaQuery.of(context).size.height - 104)/2;
//104 is random number for the rest of the screen widgets (e.g. appbar ..)
_scrollViewController.jumpTo(jumpTo); //pixel value
...
ListView.builder(
controller: _scrollViewController,

Flutter: How to smooth PageView onPageChanged animation

If you follow the example codes found online, when building a scaffold, under body, you can have:
body: PageView(
controller: _pageController,
onPageChanged: (index) {
setState(() => _selectedPage = index);
},
children: <Widget>[
Container(color: Colors.pink,),
Container(color: Colors.cyan,),
Container(color: Colors.deepPurple,),
],
)
When you are on the page that shows the color pink and you swipe left, a page of color cyan comes from the right. However, right now I extended it for my usecase and now have:
body: PageView(
controller: _pageController,
onPageChanged: (index) {
setState(() => _selectedPage = index);
},
children: <Widget>[
Container(child: _pageOptions[_selectedPage],),
Container(child: _pageOptions[_selectedPage],),
Container(child: _pageOptions[_selectedPage],),
],
)
The "_pageOptions[]" is defined as follows:
final _pageOptions = [
Page1(),
Page2(),
Page3(),
];
My issue is as follows: When, for example, you are on Page1 and swipe left, Page2 is supposed to come from the right and become the new page you are looking at. However, when you swipe from Page1 to Page2 slowly, you can see that the page that is coming from the right is Page1 rather than Page2. Up until you swipe halfway that the incoming page becomes Page2. However, by this point, the page that you are swiping away into the left side (which is supposed to be Page1) becomes Page2 as well.
How can I fix this? Page1() and the rest return a widget. For example, class Page1 is coded as:
class Page1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(25.0),
child: Text('Page1', style: TextStyle(fontSize: 36.0),)
);
}
}
In:
children: <Widget>[
Container(child: _pageOptions[_selectedPage],),
Container(child: _pageOptions[_selectedPage],),
Container(child: _pageOptions[_selectedPage],),
],
the children are changing depending on _selectedPage which changes when onPageChanged.
If you are in Page1, _selectedPage = 1 and thus all children are _pageOptions[1] which are Page1. Change code to:
children: <Widget>[
Container(child: _pageOptions[0],),
Container(child: _pageOptions[1],),
Container(child: _pageOptions[2],),
],