My current project has a scrollable row which works fine, but I can't find a way to make some kind of static scroll, where when you scroll to an item, the item is centered automatically.
This is what I currently have:
When the cards are scrolled they stay in the position when the scroll finish:
The effect I want to accomplish is the card aligning itself in the center when scrolling to the next card.
Is there a widget that actually works like that?
Try this,
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final List<String> images = ["Me", "You", "Foo", "Baa"];
final PageController controller = PageController(viewportFraction:0.8);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: PageView.builder(
controller: controller,
itemCount: images.length,
itemBuilder: (context,index){
return Container(
margin: EdgeInsets.all(16),
child: Center(child:Text(images[index])),
color: Colors.grey.shade200
);
}
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text('Hello, World!', style: Theme.of(context).textTheme.headline4);
}
}
The solution was simple:
Padding(
padding: const EdgeInsets.symmetric(vertical: 80),
child: Container(
child: PageView(
controller: controller,
scrollDirection: Axis.horizontal,
pageSnapping: true,
physics: BouncingScrollPhysics(),
children: [CardMovie(), CardMovie(), CardMovie()],
),
),
)
using PageView widget and giving a padding top because the height of the widget was the full screen.
Related
The issue is on web when we try to scroll the vertically scrollable widget which is a child of horizontally scrollable widget where scroll bar is always visible.
When we scroll the horizontally scrollable widget the scroll bar for horizontal scroll is correctly displayed as shown in picture
horizontal scroll
But when we scroll the vertically scrollable widget the horizontal scrollbar disappears and new vertical scroll bar is seen at right as shown in screenshot
vertical scroll
Code to reproduce the issue.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scroll Issue Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Scroll Issue Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final ScrollController _horizontalController = ScrollController();
final List<ScrollController> _verticalController = [];
#override
void initState() {
super.initState();
for (int i = 0; i < 6; i++) {
_verticalController.add(ScrollController());
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Row(
children: <Widget>[
Expanded(
child: _buildHorizontalScroll(),
)
],
),
);
}
Widget _buildHorizontalScroll() {
return Scrollbar(
isAlwaysShown: true,
controller: _horizontalController,
notificationPredicate: (predicate) {
return predicate.depth == 0;
},
child: ListView.separated(
controller: _horizontalController,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => Container(
margin: const EdgeInsets.all(30),
width: 300,
color: Colors.black12,
child: Column(
children: [
Expanded(
child: _buildVerticalScroll(index),
)
],
),
),
separatorBuilder: (context, index) => const Divider(
height: 30,
),
itemCount: 6),
);
}
Widget _buildVerticalScroll(int index) {
return Scrollbar(
scrollbarOrientation: ScrollbarOrientation.right,
isAlwaysShown: true,
controller: _verticalController[index],
child: ListView.separated(
controller: _verticalController[index],
itemBuilder: (context, index) => Container(
margin: const EdgeInsets.all(30),
height: 100,
color: Colors.green,
),
separatorBuilder: (context, index) => const Divider(
height: 30,
),
itemCount: 200),
);
}
}
Checking the notification predicate in the horizontal scroll bar, it detects the depth of scroll as both 0 and 1 when scrolling the vertically scrollable list. Is there a workaround for this problem? The problem started to appear since the upgrade to 2.5.0 for stable channel of flutter.
Maybe this package will help you easily customize your thumb and scrolling track both horizontally and vertically
https://pub.dev/packages/cross_scroll
I am attempting to put a ListView.builder widgets in a Column widget however the common solution provided by the flutter team is to place the unbounded ListView.builder in a Expanded or Flexible widget. The problem with this is the ListView.builder now fills as much space as it can in the column (as seen bellow).
Is there a way to have the ListView.builder only take up the space it requires?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
// This widget is the root of your application.
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Text> lst = [Text('first'), Text('second')];
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter ListView',
home: SafeArea(
child: Scaffold(
body: Column(
children: <Widget>[
Flexible(
child: ListView.builder(
itemCount: lst.length,
itemBuilder: (context, index) {
return Center(
child: lst[index],
);
},
),
),
FlatButton(
color: Colors.blue,
child: Text("Add Third"),
onPressed: () {
setState(() {
lst.add(Text("Third"));
});
},
),
Text("Next Item"),
],
),
),
),
);
}
}
You can use shrinkWrap: true property of listview to limit the list view size.
child: ListView.builder(
shrinkWrap: true, //added line
itemCount: lst.length,
I would like to create my own safe area view but instead of just cutting off the overflown area, I would like to have the overflowing area blocked by a semi transparent background.
I realise this question is somewhat similar to Allowing a widget to overflow to another widget but the answer there can solve that question in particular but not mine.
So how do I make the flutter widget overflow?
I used stack to place a container above the view when there's a top overflow and below if there's a bottom overflow. The result works good except that its overflowing to the semi transparent background.
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Didian',
home: Scaffold(
body: OpacitySafeArea(
child: RandomWords()
),
),
);
}
}
class OpacitySafeArea extends StatelessWidget {
final Widget child;
OpacitySafeArea({
#required this.child
});
#override
Widget build(BuildContext context) {
var deviceData = MediaQuery.of(context);
var height = deviceData.size.height;
var width = deviceData.size.width;
var top = deviceData.padding.top;
var bottom = deviceData.padding.bottom;
print(deviceData);
return Stack(
overflow: Overflow.visible,
children: <Widget>[
this.child,
top > 0? Container(
color: Color.fromRGBO(255, 255, 255, 0.9),
height: top,
width: width
):null,
bottom > 0? Positioned(
bottom: 0,
child: Container(
color: Color.fromRGBO(255, 255, 255, 0.9),
height: bottom,
width: width
)
):null
].where((child) => child != null).toList()
);
}
}
class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
Widget buildSuggestions() {
return ListView.separated(
padding: EdgeInsets.all(16),
itemCount: 100,
itemBuilder: (context, index) {
if(index >= _suggestions.length) {
_suggestions.add(WordPair.random());
}
return ListTile(
title: Text(
_suggestions[index].asPascalCase,
style: TextStyle(fontSize: 18)
)
);
},
separatorBuilder: (context, index) => Divider(),
);
}
#override
Widget build(BuildContext context) {
return buildSuggestions();
}
}
class RandomWords extends StatefulWidget {
#override
RandomWordsState createState() => RandomWordsState();
}
I was looking for same, and finally used a simple solution without using SafeArea():
Just apply a padding to ListView itself, which you can get using MediaQuery.of(context).viewPadding.bottom
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
padding: EdgeInsets.all(0).copyWith(bottom: MediaQuery.of(context).viewPadding.bottom),
itemCount: 2000,
itemBuilder: (BuildContext context, int index) {
return Text("Item: $index");
},
),
);
}
Is there any built in widget in flutter to implement a widget like(red border in picture below) ?
which we can drag it change the value.
That's simply a horizontal ListView with predefined height.
SizedBox(
height: 56, // height of ListView
child: ListView.builder(
scrollDirection: Axis.horizontal, // makes it scroll in horizontal direction
itemBuilder: (_, index) {
// build your years
},
),
)
The desired output can be brought using the ListView.
Flutter just uploaded a video on ListView in which you can find your answer:
https://www.youtube.com/watch?v=KJpkjHGiI5A
Example code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
bool change ;
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int i=0;
void fxn(){
setState(() {
i++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('List View'),),
body: ListView.builder(
itemCount: 30,
itemBuilder: (_, index)=>Padding(
padding: const EdgeInsets.fromLTRB(0, 270, 0, 270),
child: MaterialButton(
child:
Text('200$index',style: TextStyle(fontSize: 25),),
onPressed: (){
},
color: Colors.white70,
),
),
scrollDirection: Axis.horizontal,
)
);
}
}
Output: Output
i am trying to recreate App bar scrolling with overlapping content in Flexible space using flutter.
the behavior is demonstrated here:
http://karthikraj.net/2016/12/24/scrolling-behavior-for-appbars-in-android/
I created collapsing AppBar using SliverAppBar already, using the code I pasted here, I am trying to create THIS
i cant use Stack for it because i cant find any onScroll callback, so far i created appbar with flexibleSpace, the app bar collapse on scroll:
Scaffold(
body: NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) => <Widget>[
SliverAppBar(
forceElevated: innerBoxIsScrolled,
pinned: true,
expandedHeight: 180.0,
),
],
body: ListView.builder(
itemCount: 30,
itemBuilder: (context, index) => Text(
"Item $index",
style: Theme.of(context).textTheme.display1,
),
),
),
);
edit: Example of what i want to create
ScrollViews take a ScrollController which is a Listenable that notifies on scroll offset updates.
You can listen to the ScrollController and use a Stack to achieve the effect you're interested in based on the scroll offset.
Here's a quick example:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Scroll demo',
home: new Scaffold(
appBar: new AppBar(elevation: 0.0),
body: new CustomScroll(),
),
);
}
}
class CustomScroll extends StatefulWidget {
#override
State createState() => new CustomScrollState();
}
class CustomScrollState extends State<CustomScroll> {
ScrollController scrollController;
double offset = 0.0;
static const double kEffectHeight = 100.0;
#override
Widget build(BuildContext context) {
return new Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget> [
new Container(
color: Colors.blue,
height: (kEffectHeight - offset * 0.5).clamp(0.0, kEffectHeight),
),
new Positioned(
child: new Container(
width: 200.0,
child: new ListView.builder(
itemCount: 100,
itemBuilder: buildListItem,
controller: scrollController,
),
),
),
],
);
}
Widget buildListItem(BuildContext context, int index) {
return new Container(
color: Colors.white,
child: new Text('Item $index')
);
}
void updateOffset() {
setState(() {
offset = scrollController.offset;
});
}
#override
void initState() {
super.initState();
scrollController = new ScrollController();
scrollController.addListener(updateOffset);
}
#override
void dispose() {
super.dispose();
scrollController.removeListener(updateOffset);
}
}
I think the SliverAppbar widget is what you are looking for.
Take a look at this article which shows you how to achieve your goal.
https://flutterdoc.com/animating-app-bars-in-flutter-cf034cd6c68b
Your should also take a look at https://medium.com/#diegoveloper/flutter-collapsing-toolbar-sliver-app-bar-14b858e87abe