How to set static gradient background for PageView in Flutter? - mobile

Currently I have a PageView set up with 3 pages, scrollable from top to bottom, all with the same background gradient, yet with every page change I'm scrolling away the gradient. As you can imagine it looks somewhat unasthetic to see the beginning and end of the gradient while scrolling. I'd like it to stay put and not move.
That's where I'm lost.
I tried removing the gradient container from each page and put it into a positioned widget in the class that's being rendered, as shown below.
I tried simply returning a Container(being the gradient of my choice - "Background(null)"), and returning intropageview as a child of it.
class TestGenderSelection extends StatefulWidget {
_TestGenderSelection createState() => _TestGenderSelection();
}
class _TestGenderSelection extends State<TestGenderSelection> {
var account = Account();
#override
Widget build(BuildContext context) {
return Material(
child: Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 50.0,left: 20.0),
child: SvgPicture.asset(
"assets/images/rocker.svg",
width: 70,
height: 70,
alignment: Alignment.topLeft),
),
Padding(
padding: EdgeInsets.only(top: 20.0,left: 20.0),
child: Text(
"May I Assume your gender?\nYou tell me.",
style: TextStyle(
fontSize: 25,
fontFamily: "IntroBlackCaps",
fontWeight: FontWeight.w300,
color: Colors.white
),
),
),
Padding(
padding: const EdgeInsets.only(top: 250.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
InkWell(onTap: () { BamRemote.goToHome(context);print(account.username);},child: SvgPicture.asset("assets/images/baby-boy.svg",width: 150, height: 150,)),
InkWell(onTap: () => BamRemote.goToHome(context),child: SvgPicture.asset("assets/images/baby-girl.svg",width: 150, height: 150,)),
InkWell(onTap: () => BamRemote.goToHome(context),child: SvgPicture.asset("assets/images/newborn.svg",width: 150, height: 150,))
],),
)
],
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 20.0, bottom: 20.0),
child: Align(
alignment: Alignment.bottomRight,
child: InkWell(
onTap: () => introcontroller.previousPage(duration: Duration(milliseconds: 900), curve: Curves.linearToEaseOut),
child: RotatedBox(
quarterTurns: 1,
child: Icon(Icons.arrow_back_ios,color: Colors.white,size: 25.0,)),
))),
Padding(
padding: const EdgeInsets.only(right: 20.0, bottom: 20.0),
child: Align(
alignment: Alignment.bottomRight,
child: InkWell(
onTap: () => introcontroller.nextPage(duration: Duration(milliseconds: 900), curve: Curves.linearToEaseOut),
child: RotatedBox(
quarterTurns: 3,
child: Icon(Icons.arrow_back_ios,color: Colors.white,size: 25.0)),
)))]),
]),
),
);
}
}
final intropageview = PageView(
scrollDirection: Axis.vertical,
controller: introcontroller,
children: <Widget>[
TestSplashScreen(),
TestNameSelection(),
TestGenderSelection(),
//TestThemeSelection(),
],
);
class Intro extends StatelessWidget{
#override
Widget build(BuildContext context) {
// TODO: implement build
return Stack(
children: <Widget>[
Positioned(
top: 0.0,
child: Background(null)
),
intropageview,
],
);
}
}
I'm not getting any error messages. It simply renders the background black, as its the primary color in my theme, i'm guessing.

Solved it
Wrapped each Material with a Container and set each's color to Colors.transparent
Then returned the gradient Background with the pageview as a child.

Add the stack inside a container. You should use this under your Container.
decoration: BoxDecoration(
// Box decoration takes a gradient
gradient: LinearGradient(
// Where the linear gradient begins and ends
begin: Alignment.topRight,
end: Alignment.bottomLeft,
// Add one stop for each color. Stops should increase from 0 to 1
stops: [0.1, 0.4, 0.7, 1.0],
colors: [
// Colors are easy thanks to Flutter's Colors class.
const Color(0xff0D37C1),
Colors.deepPurpleAccent,
Colors.deepPurple,
Colors.purple,
],
),
),
finally You will have to change like this
class Intro extends StatelessWidget{
#override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
decoration: BoxDecoration(
// Box decoration takes a gradient
gradient: LinearGradient(
// Where the linear gradient begins and ends
begin: Alignment.topRight,
end: Alignment.bottomLeft,
// Add one stop for each color. Stops should increase from 0 to 1
stops: [0.1, 0.4, 0.7, 1.0],
colors: [
// Colors are easy thanks to Flutter's Colors class.
const Color(0xff0D37C1),
Colors.deepPurpleAccent,
Colors.deepPurple,
Colors.purple,
],
),
),
child: Stack(
children: <Widget>[
Positioned(
top: 0.0,
child: Background(null)
),
intropageview,
],
),
);
}
}

Related

The data from Firebase appears randomly, and it is not the last item I add that appears at the top

I need to show the data that I add at the top, but it does not happen, I thought that the data is arranged according to the date it was added to the Firebase Firestore,
I think the data is sorted by document ID
After I almost finished the application, I could not solve this problem, I am not very skilled in Firebase and I did not find the solution
class News extends StatefulWidget {
News({Key? key}) : super(key: key);
#override
State<News> createState() => _NewsState();
}
class _NewsState extends State<News> {
final Stream<QuerySnapshot> data =
FirebaseFirestore.instance.collection('news').snapshots();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromARGB(255, 102, 102, 102),
appBar: AppBar(
backgroundColor: Colors.blueAccent,
title: Center(
child: Text(
'أخبار الأنمي',
style: TextStyle(fontSize: 30),
),
),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: StreamBuilder<QuerySnapshot>(
stream: data,
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('حدث خطأ');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Column(
children: [
Center(child: Text('جاري التحميل')),
CircularProgressIndicator()
],
);
}
final anime = snapshot.requireData;
return ListView.builder(
physics: BouncingScrollPhysics(),
padding:
EdgeInsets.only(top: 3, left: 3, right: 3, bottom: 80),
itemCount: anime.size,
itemBuilder: (context, index) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.blue, width: 3),
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 3.5,
spreadRadius: 1,
)
],
),
margin: EdgeInsets.all(5),
child: Row(
children: [
Expanded(
flex: 3,
child: Container(
alignment: Alignment.centerRight,
child: Text(
textDirection: TextDirection.rtl,
'${anime.docs[index]['title']}',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700),
),
)),
Expanded(
flex: 1,
child: Card(
child: Image.network(
'${anime.docs[index]['image']}',
fit: BoxFit.fill,
height: 120,
),
),
)
],
),
),
],
);
});
})),
);
}
}
Yes, firestore will return base on alphabetically sorting based on document ID.
Use the .orderBy("FieldToOrderBy") to return it in your desired order.
Order and limit data - Firestore

Flutter Images in a List (Flutter)

so I want to have a List/Array that contains images and where each image has his own title.
The image and the title should be shown in two different buttons and the title should change when I tap on the image.
I already could solve the first two points (to show in different places and that the title changes)
But I don't know how to add images to my List, could you help me?
In addition to that, the List should be randomized, but the title should always "stay" with his image.
I hope you understand what I want and thank you for your help.
class Sachen {
String title;
String image;
Sachen(this.title, this.image);
}
final List<Sachen> infoBank = [
Sachen("Chips", "images/snack1.png",),
Sachen("Erdnussflips", "images/snack2.png",),
];
int bankNumber = Random().nextInt(2) +1;
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
Card(
margin: EdgeInsets.fromLTRB(50, 35, 50, 0),
elevation: 8,
color: Color(0xFF4caf50),
child: SizedBox(
height: 80,
width: 150,
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 18),
child: GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Rezept('Rezept'),
),
);
},
child: SizedBox(
height: 125,
width: 150,
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 18),
child: Text(
infoBank[bankNumber].title,
style: GoogleFonts.rubik(
fontSize: 20,
color: Colors.white,
),
),
),
),
),
),
),
),
),
),
Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
setState(() {
bankNumber++;
});
changeDiceNumber();
print('LeftDiceNumber = $DiceNumber');
},
child: Container(
margin: EdgeInsets.fromLTRB(10, 20, 10, 20),
decoration: BoxDecoration(
border: Border.all(
width: 2,
color: Colors.grey.shade700,
),
),
height: 350,
width: 350,
child: Image.asset('images/snack$DiceNumber.png',
fit: BoxFit.cover,
),
),
),
),
],
),
],
),
);
}
}
have you tried using Flutter's ListViewBuilder?
Like alread said ListView().builder will be a good usage.
Instead of building the widget you can just use ListTile or Card there you already have trailing, leading, and title for the positioning of your images.
Althou i would change the class Sachen with a final Icon or IconData to directly add it to your List. In The Constructor please use required for the parameters its for better reading and don't do mistakes
This is my first idea to use this
class Sachen {
final String title;
final String image;
Sachen({
required this.title,
required this.image,
});
}
final List<Sachen> liste = [
Sachen(title: "title", image: "name"),
Sachen(title: "title1", image: "name1"),
];
return ListView.builder(itemBuilder: (context, index) {
return ListTile(
leading: Image.asset(liste[index].image),
title: Text(liste[index].title),
onTap: (){
//Do On Tap
//remember to use SetState when you want to rebuild some changes
},
);
});
Other Idea maybe a little bit better:
class Sachen {
final String title;
final Image image;
Sachen({
required this.title,
required this.image,
});
}
final List<Sachen> liste = [
Sachen(title: "title", image: Image.asset("name")),
Sachen(title: "title1", image: Image.asset("name1")),
];
#override
Widget build(BuildContext context) {
return ListView.builder(itemBuilder: (context, index) {
return ListTile(
leading: liste[index].image,
title: Text(liste[index].title),
onTap: () {
//Do On Tap
//remember to use SetState when you want to rebuild some changes
},
);
});
}

Randomly display values from an array excluding value in index 0 in flutter

I am a beginner in flutter. I was building an app as a part of learning and came across this confusion. I have an array with some names and I wanna display those names randomly on button press. I left the index 0 value as null so that every time the app loads no names are displayed. The problem is when i press the button this null value is also displaying. Please help me.
class _FoodieState extends State<Foodie> {
List<String> foodieName = ['','foodie1', 'foodie2', 'foodie3', 'foodie4', 'foodie5','foodie6','foodie7'];
int foodieNumber=0;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircleAvatar(
radius: 120.0,
backgroundImage: AssetImage('images/burger.jpg'),
),
ElevatedButton(
child: Text('Who will buy today\'s\ lunch ?'),
style: ElevatedButton.styleFrom(
primary: Colors.yellow[800],
onPrimary: Colors.white,
shape: const BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5)),
),
textStyle: TextStyle(
fontFamily: 'Rancho',
fontSize: 35,
color: Colors.grey,
),
),
onPressed: () {
setState(() {
foodieNumber=Random().nextInt(foodieName.length);
});
},
),
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
foodieName[foodieNumber],
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 30,
color: Colors.red,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
);
}
}
This doesnt display first index:
foodieNumber=Random().nextInt(foodieName.length - 1) + 1;

Use while loop to repeat 3 widgets. in flutter

I want to repeat the following code with index values from 1 to n. How to do it in flutter ?
return ListView(
children: <Widget>[
SizedBox(
height: 15.0,
),
new Image.asset(
"assets/$name/$index.jpg",
fit: BoxFit.cover,
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("$name $index",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 23,
fontFamily: 'Raleway',
color: Colors.black)),
Container(
margin: EdgeInsets.only(left: 100.0),
width: 150.0,
height: 50.0,
child: FlatButton(
onPressed: null,
child: Text('Download',
style: TextStyle(color: Colors.black, fontSize: 20)),
textColor: Colors.white,
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.teal, width: 2, style: BorderStyle.solid),
borderRadius: BorderRadius.circular(50)),
),
),
],
),
],
);
To show 3 times simple text using while loop.
Widget getWidgets() {
List<Widget> list = new List<Widget>();
int i = 0;
while (i < 3) {
list.add(new Text(strings[i]));
i++;
}
return Row(children:list);
}
You can copy paste run full code below
You can use ListView.builder with itemCount and wrap Column
code snippet
ListView.builder(
itemCount: 10,
itemBuilder: (BuildContext ctxt, int index) {
return Column(
children: <Widget>[
working demo
full code
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,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
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> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView.builder(
itemCount: 10,
itemBuilder: (BuildContext ctxt, int index) {
return Column(
children: <Widget>[
SizedBox(
height: 15.0,
),
Image.network(
"https://picsum.photos/50?image=$index",
fit: BoxFit.cover,
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("$index",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 23,
fontFamily: 'Raleway',
color: Colors.black)),
Container(
margin: EdgeInsets.only(left: 100.0),
width: 150.0,
height: 50.0,
child: FlatButton(
onPressed: null,
child: Text('Download',
style:
TextStyle(color: Colors.black, fontSize: 20)),
textColor: Colors.white,
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.teal,
width: 2,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(50)),
),
),
],
),
],
);
}),
);
}
}

How to dynamically arrange cards in a row?

I want to put two cards in a row and have them dynamically resized based on phone size. As seen in the image, the right card has overflow error because the phone dimension is small. Looks fine on a bigger phone.
Ignore the first overflow error
I have tried wrapping the container using Expanded() or Flexible() but it gives an error saying my parent is using a GestureDetector() and it does not allow that.
Widget _showSecondRow(){
return new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new GestureDetector(
child: Card(
elevation: 1,
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Container(
color: Colors.grey.shade200,
padding: EdgeInsets.all(45.0),
child: new Column(
children: <Widget>[
new Icon(Icons.drafts, size: 30.0, color: Colors.black),
new Text("Private\nMessages", textAlign: TextAlign.center, style: TextStyle(color: widget.appModel.getPrimaryTextColor, fontSize: 18.0, fontWeight: FontWeight.bold),)
],
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
)
),
new GestureDetector(
onTap: () => Navigator.push(context, new MaterialPageRoute(builder: (context) =>
new SubscribedScreen()
)),
child: Card(
elevation: 1.0,
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Container(
color: Colors.grey.shade200,
padding: EdgeInsets.all(45.0),
child: new Column(
children: <Widget>[
new Icon(Icons.star, size: 30.0, color: Colors.black),
new Text("Subscribed\nThreads", textAlign: TextAlign.center, style: TextStyle(color: Colors.black, fontSize: 18.0, fontWeight: FontWeight.bold), overflow: TextOverflow.ellipsis,)
],
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
)
),
],
);
}
I expect both cards to be dynamically resized regardless of phone size and fit the width of the phone. Doesnt matter if there's gap in the middle.
Wrap each GestureDetector in Expanded or Flexible

Resources