Why I am using reverse is true, Its for achieving fetch messages from realtime database sorted by time added. after doing this, New messages at ToP and old messages lies down in listview. Everything works well, this is the condition I wanted. But The list view is always scrolling to bottom instead of lying on top.If user enters the page, he is will see old posts first, instead of new posts. Here is my ocde
return ListView.builder(
controller: _scrollController,
shrinkWrap: true,
//physics: const AlwaysScrollableScrollPhysics(),
itemCount: nots.length,
reverse: true,
itemBuilder: (context, index) {
return Container(
color: Colors.amber[50],
child: Padding(
padding: const EdgeInsets.all(0.0),
child: Row(
children: <Widget>[
column(nots[index].title,nots[index].date,nots[index].body,nots[index].photourl),
//column,
],
),
),
);
},
);
If I remove reverse: True. then old posts lies on top and new messages lies on bottom. But in this case listview is not scrolling to bottom. In short words, When I use both cases. Users can only see old posts first. But I want to see them new posts first.
ListView reverse: true displays the List fed to it from the bottom. If you'd like for the ListView to start at the top, you'd need to sort the List to be displayed on the ListView instead.
Related
I have a very simple animation for a splash screen of a shaking jar that I made in Adobe After Effects and exported it via LottieFiles extension as json, it works normal but every couple of times when I open the app the animation glitches (see pictures below), I can't figure it out and have tried searching for a solution without any success. The problem is the glitching happens random (sometimes it's a couple of times in row when I open app, sometimes it's every x times). This was tested on multiple android devices with same result.
Code for splash screen:
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: isDarkMode()? const Color(0xFF31302f) : const Color(0xFFfcfaf6),
body:
Align(
alignment: Alignment.topCenter,
child: Column(
children: [
SizedBox(height: height(context)*0.08),
Stack(
children: [
Image.asset(
isDarkMode()? 'assets/crnikruh.png' : 'assets/bijelikruh.png',
height: height(context)*0.3,
width: height(context)*0.3,
),
Padding(
padding: EdgeInsets.only(top: height(context)*0.01),
child: Lottie.asset(
'lottie/jaranimation.json',
width: height(context)*0.3,
height: height(context)*0.3,
frameRate: FrameRate.max,
fit: BoxFit.fill,
),
)
],
),
],
),
),
);
}
}
This is the normal view
This is the animation with the problem
I've found a workaround for this issue. It's not quite the solution but it works. So, I think the problem was it wasn't loading properly every time and the trick that helped me was that I wrapped the lottie asset with visibility widget and delayed the visibility by 50 milliseconds, so it got that extra 50 milliseconds on startup to properly load the asset.
I want to add webview inside customScrollView.
child: CustomScrollView(
slivers: <Widget>[
setAppBar(),
SliverFillRemaining(
child: InAppWebView(
initialUrl: "https://www.google.com/",
)),
],
)
the problem is only visble area is webview loading ...remaining content is not visible/scrollable..
Try wrapping InAppwebView Widget with a SingleChildScrollView and set physics like this... The FillRemaining is not needed
...
slivers: <Widget>[
setAppBar(),
SliverList(
delegate: SliverChildListDelegate([
SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child:InAppWebView(
...
UPDATED Answer:
This will work in simple cases. But in your case, I think you need NestedScrollView() widget to show a dynamic height widget like PageView / WebView below the SliverAppBar. You can check this code https://flutteragency.com/nestedscrollview-widget/
The problem is that I have a RichText inside a Scrollable Widget(SingleChildScrollView or ListView) and I need to Scroll to a specific TextSpan inside the RichText. Also, I cannot use ScrollablePositionedList because the texts should write in the end of the last one and if there was no space to continue the text should go to the next line so I have to use RichText.
Similar to
Sample Code:
ListView(
children:[
RichText(
children: AListOfTextSpansThatICreateWithIndexes(),
),
],
),
Sample Text That I want to show:
This is TextSpan1 and it is a bit
long. This is TextSpan2 and its ok.
Similar to Scrollable position of a TextSpan within a RichText
There is a way to make sure a key is visible on the screen using the Scrollable.ensureVisible method. (credits to the person who deleted their comment)
you should first generate keys for your list:
var keys = List.generate(LENGTH, (i) => GlobalKey());
Then use the keys behind each TextSpan:
Text.rich(
TextSpan(
children: Iterable.generate(LENGTH, (i) => i)
.expand((i) => [
WidgetSpan(
child: SizedBox.fromSize(
size: Size.zero,
key: keys[i],
),
),
TextSpan(
text: 'this is text number $i',
),
])
.toList(),
),
),
Finally, call this function(where there is access to the context) to scroll to the desired key:
Scrollable.ensureVisible(
keys[i].currentContext,
alignment: 0.2,
duration: Duration(milliseconds: 500),
),
I followed this tutorial which explores creating a ui for a movie app
https://www.youtube.com/watch?v=OgSLd2lH1FM&feature=youtu.be
While most of the design I was able to recreate and add my own settings to,I face a problem in the Poster display side of the tutorial, Mainly that in the builder, It is specified that the pages to the right and left of the one in focus are inclined at 15 degrees.:
The poster view should look like this
The transform.rotate part works, but only after the user starts scrolling horizontally in the poster list.
before the scroll it looks like this:
What the carousel looks like before scrolling
This happens both in the simulator and a real device. Also I tried using transform.translate to see if that gives the same problem but it does not.
Below is a code snippet of the Animated builder.
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.symmetric(
vertical: kDefaultPadding / 2, horizontal: 0),
child: AspectRatio(
aspectRatio: 0.85,
child: PageView.builder(
itemCount: movies.length,
controller: _pageController // declared PageController type in class//,
onPageChanged: (value) {
setState(() {
// initialPage was initialised with value 1
initialPage = value;
});
},
itemBuilder: (context, index) => buildMovieCard(index),
),
),
);
}
The animatedBuilder calling function is below.
Widget buildMovieCard(int index) => AnimatedBuilder(
animation: _pageController,
builder: (context, child) {
double value = 0;
if (_pageController.position.haveDimensions) {
value = index - _pageController.page;
//0.038 since it time pi gives 7 so 7 rotaitons
value = (value * 0.038).clamp(-1, 1);
}
return Transform.rotate(
child: MovieCard(movie: movies[index]),
angle: math.pi * value,
);
});
(Sorry if the information above is Convoluted.. )
Do tell me if there are any errors in the way I have framed this question
EDIT: I tried searching a bit more, and found a similar question.
it seems that animations won't be executed until an animation plays for an animated builder.
I dont have too much experience in animated builder stuff so if I find something ill add it
Here is the link to the question
I Tried using a SingleTickerProvider and an animation controller with .repeat() to continuously run the animatedBuilder. The rotation now does appear automatically, but it takes some time.
Is your _pageController.page set correctly at the start?
What happens if you print value inside your if:
if (_pageController.position.haveDimensions) {
...
print(value);
}
(sorry I don't have the reputation to comment directly on the question on this account)
I did not quite understand the code, but according to the description you might try to simulate a scroll or see what exactly the scroll affects, and try to implement it.
Hope I helped.
Check out this video for problem demo
https://youtu.be/GsdWcTEbUbg
As there is a large number of code, I will try to summarize the structure of the code here.
In a nutshell:
Scaffold(
appBar: AppBar(),
body: StreamBuilder<dynamic>(
stream: globals.chatRoomBloc.threadScreen,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Column(
crossAxisAlignment:
CrossAxisAlignment.stretch, // sticks to the keyboard
children: <Widget>[
Expanded(
child: Scrollbar(
child: ListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return TileWidget();
},
),
),
),
],
);
},
),
)
TileWidget is stateful, appends the TextField and resize the widget when the reply button is pressed. Then when the user clicks on the Textfield, the keyboard pops up.
Now my problem is that the screen is reloaded when the keyboard pops up.
I tried the following solutions:
Using TextField inside a Streambuilder : I am setting up the stream only once, that is when the page is loaded the first time. Any changes to the stream is made when a new chat or entry is added. In my case, this does not happen.
Flutter Switching to Tab Reloads Widgets and runs FutureBuilder I am not sure if this is the same problem, but the solution does not change anything for me.
Issue #11895 - I went through this as well, but is not helping.
I think the screen is trying to resize and redraw to accommodate the keyboard drawer. But it is for some reason failing to do that and loading everything over again. Am I missing something ? Is there a way around this ?
As one of the links you provides points out your buildmethod fires whenever the state of the app changes i.e the keyboard pops up, so move the streambuilder outside of it. There are a few more changes you could do. Try the following,
create a variable outside of the build method.
var myStreamBuilder;
//....
//inside initialstate method
myStreamBuilder = StreamBuilder<dynamic>(
stream: globals.chatRoomBloc.threadScreen,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Column(
crossAxisAlignment:
CrossAxisAlignment.stretch, // sticks to the keyboard
children: <Widget>[
Expanded(
child: Scrollbar(
child: ListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return TileWidget();
},
),
),
),
],
);
},
),
Then in your build method call the variable.
Scaffold(
appBar: AppBar(),
resizeToAvoidBottomInset: false, //don't forget this!
body: myStreamBuilder
)
EDIT: Make sure you check your snapshot that it hasData or not. If there is no data then something should be returned until it does have data, this way the user is informed what the app is doing.
Also this property might also be helpful to you. resizeToAvoidBottomInset - https://api.flutter.dev/flutter/material/Scaffold/resizeToAvoidBottomInset.html
I think if you use of MediaQuery So that's why Probleam create and one more Solution is Create constructor and getList again.
class Demo(){
getlist(); // get list again
}
I faced similar issue when keyboard open or closed the page reloads
basically I just delete the following line from MainActivity.XML
and all works fine
android:windowSoftInputMode="adjustResize">