I want to have a scrollbar view like the one in the picture.
So how can I have it using flutter?
I've tried
SingleChildScrollView(
....
),
But no scroll bars appeared and I don't know to make them
You can use this project
The pubspec.yaml
dev_dependencies:
flutter_test:
sdk: flutter
draggable_scrollbar: 0.0.4
The code:
import 'package:flutter/material.dart';
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
ScrollController _rrectController = ScrollController();
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Test",
home: Scaffold(
body: Center(
child: DraggableScrollbar.rrect(
controller: _rrectController,
backgroundColor: Colors.blue,
child: ListView.builder(
controller: _rrectController,
itemCount: 100,
itemExtent: 100.0,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.all(8.0),
child: Material(
elevation: 4.0,
borderRadius: BorderRadius.circular(4.0),
color: Colors.green[index % 9 * 100],
child: Center(
child: Text(index.toString()),
),
),
);
},
),
),
),
),
);
}
}
The result:
Flutter now has Scrollbar widget.
Just wrap SingleChildScrollView or any ScrollView widget with Scrollbar.
Code sample:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Scrollbar(
// Child can also be SingleChildScrollView, GridView, etc.
child: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(
title: Text('Index $index'),
);
},
),
),
);
}
}
Scrollbar (Widget of the week) : https://youtu.be/DbkIQSvwnZc
Wrap the scrollable widget with Scrollbar widget.
child: Scrollbar(
isAlwaysShown: true,
child: ListView(
....)
)
You can make it always shown.
watch this for further explanation.
https://www.youtube.com/watch?v=DbkIQSvwnZc
Scrollbar(
isAlwaysShown: true,
showTrackOnHover: true,
radius: Radius.circular(5),
interactive: true,
child: ListView.builder(shrinkWrap: true, itemCount: data.productionReportModel!.data!.length, itemBuilder: (context, index) {
return Container();
}),
),
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
my app build test app blog with flutter ,back end wordpress but I don’t know where to add
Can you help?
my app build test app blog with flutter ,back end wordpress but I don’t know where to add
Can you help?
main.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'blog',
home: HomeScreen(),);}}
home.dart
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
List<SinglePost> parsePosts(response) {
final parsed = jsonDecode(response)['posts'].cast<Map<String, dynamic>>();
return parsed.map<SinglePost>((json) => SinglePost.fromJson(json)).toList();
}
Future<List<SinglePost>> _getPosts() async {
final response = await http.get(baseUrl);
return compute(parsePosts, response.body);
}
class _HomeScreenState extends State<HomeScreen> {
Future<List<SinglePost>> _postsFuture;
#override
void initState() {
super.initState();
_postsFuture = _getPosts();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: FutureBuilder<List<SinglePost>>(
future: _postsFuture,
builder: (context, snapshot) {
if (snapshot.hasError)
return Scaffold(
body: Center(
child: Text("Error"),
),
);
if (snapshot.hasData) {
return Scaffold(
appBar: AppBar(
elevation: 0,
title: Text(
"blog",
style: Theme.of(context)
.textTheme
.title
.copyWith(color: Colors.black),
),
actions: <Widget>[
Padding(
padding: const EdgeInsets.all(9.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(9),
child: Image.network(
"${snapshot.data[0].avatarURL}",
fit: BoxFit.cover,
),
),
)
],
),
body: ListView(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * .35,
margin: const EdgeInsets.symmetric(vertical: 15.0),
child: PageView.builder(
controller: PageController(viewportFraction: .76),
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.length,
itemBuilder: (context, i) => OverlayedContainer(
authorAvatar: "${snapshot.data[i].avatarURL}",
author: "${snapshot.data[i].authorName}",
image: "${snapshot.data[i].featuredImage}",
title: "${snapshot.data[i].title}",
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
PostScreen(postData: snapshot.data[i]),
),
),
),
),
),
Padding(
padding: const EdgeInsets.all(9),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"All Posts",
style: Theme.of(context).textTheme.subtitle,
),
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 5,
itemBuilder: (context, i) => PostContainer(
author: "${snapshot.data[i].authorName}",
image: "${snapshot.data[i].featuredImage}",
title: "${snapshot.data[i].title}",
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
PostScreen(postData: snapshot.data[i]),
),
),
),
)
],
),
)
],
),
);
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
),
);
}
}
I don’t know where to add
Can you help?
my app build test app blog with flutter ,back end wordpress but I don’t know where to add
Can you help?
I know that
Add in pubsec.yaml
And import package
..
..
but writing the code inside home.dart I don't know
I have a NestedScrollView whose body contains a TabBarView. And one of the tabs has a column with an image and a scrollable widget(GridView.builder). When scrolling this scrollable widget, the images get stuck halfway(as if it was pinned in that position).
Here's the code
//home.dart
class _HomePage extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Container( //this is the image that gets stuck
child: Column(
children: <Widget>[
new Container(
child: new Image.asset(
"images/product.jpg",
fit: BoxFit.fitWidth,
),
),
Expanded(
child: FreshFinds(), //this is the scrollable widget
),
],
),
);
}
}
// Freshfind.dart
#override
Widget build(BuildContext context) {
return Card(
child: GridView.builder(
// shrinkWrap: true,
itemCount: 50,
physics: ScrollPhysics(),
gridDelegate:
new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return FutureBuilder(
future: fetchdata(index),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData)
return buildfake(index);
else
return buildcard(snapshot.data, index);
},
);
},
),
);
}
Here is a video of the problem
I think you need to use SliverAppBar() widget alongside with TabBar().
Here's a resource that might help you
I'm struggling with the ListView.
My problem is that I've a Listview inside another Listview and the second Listview items height are not always the same. I want to get rid of the itemExtent and create an automatically height for the first Listview.
What I really want to acomplish is something like this:
#override
Widget build(BuildContext context) {
return
Column(
children: <Widget>[
TextField(),
Expanded(
child: ListView.builder(
key: new Key("ditisdekeyvoordelistview"),
itemBuilder: _makeMovieList,
padding: EdgeInsets.all(0.0),
itemCount: _movies.length,
itemExtent: 300.0,
),
),
],
);
}
//FIRST LIST
Widget _makeMovieList(BuildContext context, int index) {
return Container(
child: ListTile(
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
leading: Container(
child: Column(mainAxisSize: MainAxisSize.max, children: <Widget>[
Image.network(
_movies[index].movieImage,
fit: BoxFit.cover,
width: 100.0,
)
])),
title: Text(
_movies[index].movieTitle,
),
subtitle: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_makeStarRating(_movies[index].movieRating),
Text(_movies[index].movieDescription),
_makeCardDates(index)
],
),
),
);
}
//SECOND LIST
Widget _makeCardDates(int index) {
return Expanded(
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(0.0),
itemCount: _movies[index].dateTimeList.length,
itemBuilder: (context, indexx) {
return GestureDetector(
onTap: () {
print(_movies[index].dateTimeList[indexx].toString());
},
child: Card(
elevation: 8.0,
color: Color.fromRGBO(64, 75, 96, .9),
child: Column(
children: <Widget>[
Text(_movies[index].cinema),
Text(((dateFormatMovieHours
.format(_movies[index].dateTimeList[indexx]))
.toString())),
],
)));
},
itemExtent: 40.0,
),
);
}
Using itemExtent on a ListView isn't required, though ListView needs to have a finite height set for vertical scroll (default) and finite width is needed for horizontal scroll. Otherwise, the ListView will throw a "constraints are unbounded" error.
For your use case, you can either set height on the list items in the first ListView, or set height on the second ListView. However, if you'd like the second ListView to be non-scrollable and the list items in the first ListView will adapt dynamically, you can use a Column of Widgets similar to this sample.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final items = [
'Apple',
'Banana',
'Carrot',
'Dog',
'Egg',
'Flower',
'Goat',
'Honey'
];
final subItems = ['1.00', '2.00', '3.00', '4.00'];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: firstList(),
),
);
}
firstList() {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.all(8.0),
child: Card(
child: Container(
color: Colors.lightBlue[50],
padding: EdgeInsets.all(16.0),
child: Row(
children: [
Expanded(
flex: 2,
child: Text('${items[index]}'),
),
Expanded(
flex: 1,
child: secondList(subItems),
),
],
),
),
),
);
},
);
}
secondList(List item) {
// Create List<Widget> for the second "List"
var subList = List<Widget>();
item.forEach((data) {
subList.add(
Card(
child: Container(
padding: EdgeInsets.all(16.0),
color: Colors.lightBlueAccent,
child: Text('$data'),
),
),
);
});
// Populate Column instead of ListView
return Column(
children: subList,
);
}
}
Nested scrolling?
I have three vertical pages in a PageView that I want to be able to flip between.
The pages consists of scrollable ListViews.
When a page is in focus the displayed list should be vertically scrollable, but when the list is scrolled to either end I want the pageView scrolling to take over the scroll behaviour and handle the page flipping to next page (like a web page with scrollable elements).
Example with scrolling lists below.
If the list scrolling is disabled the page flipping works.
How can I make both work?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: VerticalPageView(),
);
}
}
class VerticalPageView extends StatelessWidget {
VerticalPageView({Key key}) : super(key: key);
final PageController pageController = PageController();
final ScrollController scrollController = ScrollController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: PageView(
controller: pageController,
pageSnapping: true,
scrollDirection: Axis.vertical,
children: <Widget>[
Container(
color: Colors.pinkAccent,
child: ListView.builder(
controller: scrollController,
itemCount: 100,
physics: ClampingScrollPhysics(),
itemBuilder: (context, index) {
return Text('page 0 item $index');
},
),
),
Container(
color: Colors.lightBlue,
child: ListView.builder(
controller: scrollController,
itemCount: 100,
physics: ClampingScrollPhysics(),
itemBuilder: (context, index) {
return Text('page 1 item $index');
},
),
),
Container(
color: Colors.lightGreen,
child: ListView.builder(
controller: scrollController,
itemCount: 100,
physics: ClampingScrollPhysics(),
itemBuilder: (context, index) {
return Text('page 2 item $index');
},
),
),
],
),
),
);
}
}
I think what you are trying to achieve is not impossible but needs a lot of study and care.
I have been trying to use several NotificationListener<ScrollNotification>'s to adapt the reaction depending on the position of the scroll but did not get anywhere.
Give a look to the Animation sample home.dart file in the Gallery App. It is full of insight in this regard.
The problem with this approach is basically what you say. When you disable programmatically the scrolling when reaching the end of the list to enable page scrolling, then you can switch to the other page but can't scroll the list in the other direction any more.
So, either you scroll the list or you scroll the pages, but not both.
Maybe you could add a GestureDetector() above everything and check on every drag update what is your situation below to configure accordingly the different scrollers.
Anyway, in case it is helpful to you I let you here an alternate solution using a CustomScrollView and SliverList's.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: VerticalPageView(),
);
}
}
class VerticalPageView extends StatelessWidget {
final ScrollController _scrollController = ScrollController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: Colors.pinkAccent,
child: Text('page 0 item $index'),
);
},
childCount: 100,
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: Colors.lightBlue,
child: Text('page 1 item $index'),
);
},
childCount: 100,
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: Colors.lightGreen,
child: Text('page 2 item $index'),
);
},
childCount: 100,
),
),
],
),
);
}
}
I want to make a full screen dialog box. Dialog box background must be opaque.
Here is an example:
How to make like this in Flutter?
You can use the Navigator to push a semi-transparent ModalRoute:
import 'package:flutter/material.dart';
class TutorialOverlay extends ModalRoute<void> {
#override
Duration get transitionDuration => Duration(milliseconds: 500);
#override
bool get opaque => false;
#override
bool get barrierDismissible => false;
#override
Color get barrierColor => Colors.black.withOpacity(0.5);
#override
String get barrierLabel => null;
#override
bool get maintainState => true;
#override
Widget buildPage(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
// This makes sure that text and other content follows the material style
return Material(
type: MaterialType.transparency,
// make sure that the overlay content is not cut off
child: SafeArea(
child: _buildOverlayContent(context),
),
);
}
Widget _buildOverlayContent(BuildContext context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
'This is a nice overlay',
style: TextStyle(color: Colors.white, fontSize: 30.0),
),
RaisedButton(
onPressed: () => Navigator.pop(context),
child: Text('Dismiss'),
)
],
),
);
}
#override
Widget buildTransitions(
BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
// You can add your own animations for the overlay content
return FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: animation,
child: child,
),
);
}
}
// Example application:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Playground',
home: TestPage(),
);
}
}
class TestPage extends StatelessWidget {
void _showOverlay(BuildContext context) {
Navigator.of(context).push(TutorialOverlay());
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Test')),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Center(
child: RaisedButton(
onPressed: () => _showOverlay(context),
child: Text('Show Overlay'),
),
),
),
);
}
}
Well here is my implementation which is quite straightforward.
from first screen
Navigator.of(context).push(PageRouteBuilder(
opaque: false,
pageBuilder: (BuildContext context, _, __) =>
RedeemConfirmationScreen()));
at 2nd screen
class RedeemConfirmationScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white.withOpacity(0.85), // this is the main reason of transparency at next screen. I am ignoring rest implementation but what i have achieved is you can see.
.....
);
}
}
and here are the results.
Screenshot (Flutter's native dialog)
Call this method to show the dialog in fullscreen.
showGeneralDialog(
context: context,
barrierColor: Colors.black12.withOpacity(0.6), // Background color
barrierDismissible: false,
barrierLabel: 'Dialog',
transitionDuration: Duration(milliseconds: 400),
pageBuilder: (_, __, ___) {
return Column(
children: <Widget>[
Expanded(
flex: 5,
child: SizedBox.expand(child: FlutterLogo()),
),
Expanded(
flex: 1,
child: SizedBox.expand(
child: ElevatedButton(
onPressed: () => Navigator.pop(context),
child: Text('Dismiss'),
),
),
),
],
);
},
);
Note: This answer does not discuss making the modal transparent, but is an answer is for the stated question of "How to make a full screen dialog in flutter?". Hopefully this helps other that find this question through a search like I did, that don't need a transparent modal.
Create your modal dialog class:
class SomeDialog extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text('Dialog Magic'),
),
body: new Text("It's a Dialog!"),
);
}
}
In the class that needs to open the dialog, add something like this:
void openDialog() {
Navigator.of(context).push(new MaterialPageRoute<Null>(
builder: (BuildContext context) {
return new SomeDialog();
},
fullscreenDialog: true));
}
If fullscreenDialog above is true, then the app bar will have an "x" close button. If false, it will have a "<-" back arrow.
If you need to get the result of a dialog action, add a button to your dialog that returns a value when popping the navigation stack. Something like this:
onPressed: () {
Navigator
.of(context)
.pop(new MyReturnObject("some value");
}
then in your class opening the dialog, do capture the results with something like this:
void openDialog() async {
MyReturnObject results = await Navigator.of(context).push(new MaterialPageRoute<MyReturnObject>(
builder: (BuildContext context) {
return new SomeDialog();
},
fullscreenDialog: true));
}
You can use showGeneralDialog method with any widget extends from Material like Scaffold, Card, ..etc.
For example I am going to it with Scaffold like this:
showGeneralDialog(
context: context,
pageBuilder: (context, animation, secondaryAnimation) => Scaffold(
backgroundColor: Colors.black87,
body: //Put your screen design here!
),
);
And now you can set your design as a normal screen by using Scaffold.
Note: if you want to go back you can Navigator like this:
Navigator.of(context).pop(null)
Different ways to show fullscreen dialog
A. Material Dialog
showDialog<void>(
context: context,
useSafeArea: false,
builder: (BuildContext context) {
return const SomeScaffoldView();
},
);
B. Cupertino Dialog
showCupertinoDialog<void>(
context: context,
builder: (BuildContext context) {
return const SomeScaffoldView();
},
);
C. Custom Dialog
Flutter uses this under-the-hood when displaying dialogs.
Can customize transition animation with transitionBuilder, here's a random guide with example animations.
showGeneralDialog(
context: context,
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return const SomeScaffoldView();
},
);
Sample Scaffold View used in above snippets.
class SomeScaffoldView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sample Fullscreen Dialog'),
),
body: const Center(child: Text('Dialog Body')),
);
}
}
You can use AlertDialog with zero insetPadding like below:
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return StatefulBuilder(builder: (context, setState) {
return AlertDialog(
insetPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0))),
content: SizedBox.expand(
child: Column(
children: <Widget>[
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Wrap(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
flex: 1,
child: Text(
"Sample type",
style: TextStyle(fontWeight: FontWeight.w700),
),
),
Expanded(flex: 1, child: Text(""))
],
),
],
)),
],
),
));
});
},
);
RFlutter Alert is super customizable and easy-to-use alert/popup dialogs for Flutter. You may create reusable alert styles or add buttons as much as you want with ease.
Alert(context: context, title: "RFLUTTER", desc: "Flutter is awesome.").show();
RFlutter
It's easy to use! :)
you can do like this if you use popular flutter library getx
getx link
void showAlertDialogg(
String body,
String? confirmButtonText,
String? cancelButtonText,
Function(bool onConfirm, bool onCancel) clickEvent,
{barrierDismissible = false}) {
Get.dialog(
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextComponent(
body,
textAlign: TextAlign.center,
fontSize: textSmallFontSize,
fontWeight: titleFontWeight,
color: Colors.white,
),
Row(
//crossAxisAlignment : CrossAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: OutlineButtonComponent(
text: cancelButtonText,
borderColor: kPrimaryColor,
onPressed: () {
Get.back();
clickEvent(false, true);
},
textColor: kPrimaryColor,
padding: EdgeInsets.fromLTRB(16, 16, 8, 16),
),
),
Expanded(
flex: 1,
child: ButtonComponent(
text: confirmButtonText,
buttonColor: kPrimaryColor,
onPressed: () {
Get.back();
clickEvent(true, false);
},
textColor: Colors.white,
padding: EdgeInsets.fromLTRB(8, 16,16, 16),
),
),
],
)
],
),
barrierColor: Colors.black12.withOpacity(0.8),
useSafeArea: true
);
}
you can pas params as you want & call this method where you need it. it supports widget so you can setup the widget as you want.
Wrap your top-level widget with Navigator widget like so:
return Navigator(
pages: [
MaterialPage(
child: MainScreen(
child: widgets...
then call showDialog and because useRootNavigator is set to true in default it will use the root navigator that we added above the MainScreen