How to change position of Container inside Stack? - flutter

Im trying to displaying a button inside my stack but it not getting the correct position. The button is the reply Button . I added a foot how it looks at the moment you can check it what I want is displaying it on the right side of the window at the bottom with a bit of spacing between bottom and the button.
Hope anyone can help. if you need more information please leave a comment .
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
try {
return Scaffold(
body: StreamBuilder(
stream: mystreamofallvideos,
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState != ConnectionState.waiting) {
return PageView.builder(
itemCount: snapshot.data.docs.length,
controller:
PageController(initialPage: 0, viewportFraction: 1),
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
DocumentSnapshot videos = snapshot.data.docs[index];
return Stack(children: [
Videoplayeritem(widget.videoid),
Column(children: [
Align(
alignment: Alignment.bottomLeft,
child: Container(
height: 100,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
size: 35,
),
onPressed: () {
Navigator.of(context).pop();
}),
SizedBox(
width: 190,
),
],
),
),
),
Container(
color: Colors.red,
width: 210,
height: 94,
//color: Colors.blue.withOpacity(0.5),
child: InkWell(
onTap: () => sharevideo(
widget.videoid, videos.data()['id']),
child: Icon(Icons.reply,
size: 55, color: Colors.white),
),
),
]),
//starssonthe right
]);
});
} else {
return Center(child: CircularProgressIndicator());
}
}),
);
} catch (e) {
e.toString();
}
}
}
This is how it looks
enter image description here

Wrap it in an align and add a padding to the bottom:
Align(
alignment: Alignment.bottomRight,
child: Container(
height: 40,
padding: const EdgeInsets.only(bottom: 16),
child: OutlinedButton(
onPressed: () {},
child: Text('mybutton'),
),
)

you can wrap your container with either Positioned or Align widgets
like :
Positioned(
top: 0.0,
left: 0.0,
child: Icon(Icons.message,
size: 128.0, color: Colors.greenAccent[400]), //Icon
),

Related

How do i get the image path of selected images in a gridview in flutter?

I have a stateful widget called AddPhotosView that contains all the logic i am trying to achieve, i am using this package photo_manager to display images in the user's devices in a GridView.builder and i am trying to use image_cropper to be able to crop the image the user selects in the from the grid view.
This is the full code of my stateful widget :
class AddPhotosView extends StatefulWidget {
#override
State<AddPhotosView> createState() => _AddPhotosView();
}
class _AddPhotosView extends State<AddPhotosView> {
List<Widget> _mediaList = [];
int currentPage = 0;
int lastPage;
#override
void initState() {
super.initState();
_fetchNewMedia();
}
_handleScrollEvent(ScrollNotification scroll) {
if (scroll.metrics.pixels / scroll.metrics.maxScrollExtent > 0.33) {
if (currentPage != lastPage) {
_fetchNewMedia();
}
}
}
_fetchNewMedia() async {
var result = await PhotoManager.requestPermissionExtend();
if (result != null) {
// success
//load the album list
List<AssetPathEntity> albums =
await PhotoManager.getAssetPathList(onlyAll: true);
print(albums);
List<AssetEntity> media =
await albums[0].getAssetListPaged(page: currentPage, size: 60);
print(media);
List<Widget> temp = [];
for (var asset in media) {
temp.add(
FutureBuilder(
future: asset.thumbnailDataWithSize(
ThumbnailSize(200, 200),
),
builder: (BuildContext context, snapshot) {
if (snapshot.connectionState == ConnectionState.done)
return GestureDetector(
onTap: () async {
File file = await asset.file;
print(file.toString());
},
child: Stack(
children: <Widget>[
Positioned.fill(
child: Image.memory(
snapshot.data,
fit: BoxFit.cover,
),
),
if (asset.type == AssetType.video)
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: EdgeInsets.only(right: 5, bottom: 5),
child: Icon(
Icons.videocam,
color: Colors.white,
),
),
),
],
),
);
return Container();
},
),
);
}
setState(() {
_mediaList.addAll(temp);
currentPage++;
});
} else {
// fail
PhotoManager.openSetting();
}
}
#override
Widget build(BuildContext context) {
// final controller = Get.put(EServicesController());
return Scaffold(
appBar: AppBar(
toolbarHeight: 50,
backgroundColor: Colors.white,
title: Column(
children: [
Text(
"Add Photos".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 16,
fontWeight: FontWeight.w600),
),
],
),
centerTitle: false,
elevation: 0.5,
automaticallyImplyLeading: false,
leadingWidth: 15,
leading: new IconButton(
icon: new Icon(Icons.arrow_back_ios, color: Color(0xff3498DB)),
onPressed: () => {Get.back()},
),
),
body: Column(
children: [
Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.only(
left: 45.0, right: 45, top: 22, bottom: 35),
child: Container(
height: 280,
width: 280,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
child: Stack(
fit: StackFit.expand,
children: [
Image.asset(
'assets/icon/image-test.png',
fit: BoxFit.cover,
),
ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.white.withOpacity(0.3),
BlendMode.srcOut), // This one will create the magic
child: Stack(
fit: StackFit.expand,
children: [
Container(
decoration: BoxDecoration(
color: Colors.black,
backgroundBlendMode: BlendMode
.dstOut), // This one will handle background + difference out
),
Align(
alignment: Alignment.topCenter,
child: Container(
margin: const EdgeInsets.only(top: 80),
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(100),
),
),
),
],
),
),
],
),
),
),
),
Expanded(
child: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scroll) {
_handleScrollEvent(scroll);
return;
},
child: Padding(
padding: const EdgeInsets.all(22.0),
child: GridView.builder(
itemCount: _mediaList.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return _mediaList[index];
}),
),
),
),
],
),
//bottomNavigationBar: SendUpdateButton(),
);
}
}
My photo_manager package is working and displaying my images correctly, but i want to more with it.
Want i am trying to achieve :
Get the image path of an image selected by the user with the photo_manager package.
I also want to be able select multiple images at once or a single image when tapped from the grid view.
Then render the image selected by the user in the Container carrying the image.asset() widget.
Crop the image using the flutter package image_cropper.
Getting the file path of an image selected by the user is very important as i believe it can help me achieve many other logic.
I have tried getting the image path by wrapping the container carrying the image.asset with
GestureDetector(
onTap: () async {
File file = await asset.file;
print(file.toString());
},
But it don't to work :(
Please i would be entirely grateful if someone help me out with what i am trying to achieve as i have been struggling to achieve this for sometime now in my project.
NB: I am using the package: photo_manager because it helps me to customise the UI of where the user's gallery can be displayed, other packages has an out-of-the-box UI which i don't want. So i will be open to using another package for only cropping the image if possible.

How can i achieve 'add photo' logic in flutter?

Hey guys i am trying to achieve this image logic in flutter as i am new to flutter.
First off...
Images from the user gallery are being rendered in the 'Recent' Grid view UI (Should be in the UI provided and not come out as an overlay page as different pub.dev image picker packages does)
Images are selectable, both multiple selection and single selection.
Any image selected should be rendered inn the big container that has a round hole and an overlay, which can be cropped and zoomed.
any image selected would then be rendered in the sized boxes with the 'x'. when the 'x' is tapped, the image should be unselected.
This is what i am trying to achieve in a picture, the UI is not a problem but the logic has been giving me sleepless nights.
I tried using photo_manager
and it helped me to render the user's gallery image in the 'recent' but i am stuck at the rest logic.
Please help me :(
This is what i tried.
class AddPhotosView extends StatefulWidget {
#override
State<AddPhotosView> createState() => _AddPhotosView();
}
class _AddPhotosView extends State<AddPhotosView> {
List<Widget> _mediaList = [];
int currentPage = 0;
int lastPage;
#override
void initState() {
super.initState();
_fetchNewMedia();
}
_handleScrollEvent(ScrollNotification scroll) {
if (scroll.metrics.pixels / scroll.metrics.maxScrollExtent > 0.33) {
if (currentPage != lastPage) {
_fetchNewMedia();
}
}
}
_fetchNewMedia() async {
var result = await PhotoManager.requestPermissionExtend();
if (result != null) {
// success
//load the album list
List<AssetPathEntity> albums =
await PhotoManager.getAssetPathList(onlyAll: true);
print(albums);
List<AssetEntity> media =
await albums[0].getAssetListPaged(page: currentPage, size: 60);
print(media);
List<Widget> temp = [];
for (var asset in media) {
temp.add(
FutureBuilder(
future: asset.thumbnailDataWithSize(
ThumbnailSize(200, 200),
),
builder: (BuildContext context, snapshot) {
if (snapshot.connectionState == ConnectionState.done)
return GestureDetector(
onTap: () async {
File file = await asset.file;
print(file.toString());
},
child: Stack(
children: <Widget>[
Positioned.fill(
child: Image.memory(
snapshot.data,
fit: BoxFit.cover,
),
),
if (asset.type == AssetType.video)
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: EdgeInsets.only(right: 5, bottom: 5),
child: Icon(
Icons.videocam,
color: Colors.white,
),
),
),
],
),
);
return Container();
},
),
);
}
setState(() {
_mediaList.addAll(temp);
currentPage++;
});
} else {
// fail
PhotoManager.openSetting();
}
}
#override
Widget build(BuildContext context) {
// final controller = Get.put(EServicesController());
return Scaffold(
appBar: AppBar(
toolbarHeight: 50,
backgroundColor: Colors.white,
title: Column(
children: [
Text(
"Add Photos".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 16,
fontWeight: FontWeight.w600),
),
],
),
centerTitle: false,
elevation: 0.5,
automaticallyImplyLeading: false,
leadingWidth: 15,
leading: new IconButton(
icon: new Icon(Icons.arrow_back_ios, color: Color(0xff3498DB)),
onPressed: () => {Get.back()},
),
),
body: Column(
children: [
Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.only(
left: 45.0, right: 45, top: 22, bottom: 35),
child: Container(
height: 280,
width: 280,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
child: Stack(
fit: StackFit.expand,
children: [
Image.asset(
'assets/icon/image-test.png',
fit: BoxFit.cover,
),
ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.white.withOpacity(0.3),
BlendMode.srcOut), // This one will create the magic
child: Stack(
fit: StackFit.expand,
children: [
Container(
decoration: BoxDecoration(
color: Colors.black,
backgroundBlendMode: BlendMode
.dstOut), // This one will handle background + difference out
),
Align(
alignment: Alignment.topCenter,
child: Container(
margin: const EdgeInsets.only(top: 80),
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(100),
),
),
),
],
),
),
],
),
),
),
),
Expanded(
child: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scroll) {
_handleScrollEvent(scroll);
return;
},
child: Padding(
padding: const EdgeInsets.all(22.0),
child: GridView.builder(
itemCount: _mediaList.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return _mediaList[index];
}),
),
),
),
],
),
//bottomNavigationBar: SendUpdateButton(),
);
}
}

List view childs get out of container

I am trying to make a list view only occupy part of the screen, but it keeps growing till the end not respecting the contianer constraints. I tried to use a sizedbox too but it didn' work. List tiles outside the container are shown without any widget inside, but the background is shown anyways
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: pedidos,
builder: (context, AsyncSnapshot<List<Pedido>> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.6,
child: ListView.builder(
itemCount: snapshot.data!.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Hero(
tag:
"pedidos_card${snapshot.data![index].idPedido}",
child: ListTile(
tileColor: Colors.white,
leading: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle),
child: Center(
child: Text(
style: Theme.of(context)
.textTheme
.headlineSmall,
"${snapshot.data![index].idPedido}"),
),
),
title: Text(
'Pedido: ${snapshot.data![index].idPedido}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10),
Text(
'Estado: ${snapshot.data![index].estadoPedido.last.tipoEstadoPedido.name}'),
SizedBox(height: 10),
Text(
"Cliente: ${snapshot.data![index].cliente.nombre}")
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
trailing: Checkbox(
value: pedidosSeleccion
.contains(snapshot.data![index]),
onChanged: (bool? value) {
// value = checkboxList[index];
// setState(() {});
},
),
onTap: () {
bool isSelected = pedidosSeleccion
.contains(snapshot.data![index]);
if (isSelected) {
pedidosSeleccion
.remove(snapshot.data![index]);
} else {
pedidosSeleccion.add(snapshot.data![index]);
}
setState(() {});
},
),
));
}),
),
ElevatedButton(
onPressed: () {}, child: Text('Ver ultima milla')),
],
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
});
}
}
example
you can use Expanded instead of Sizedbox
eg:-
Column(
children:[
Expanded(flex:9,
child: ListView(
padding: const EdgeInsets.only(top: 10.0),
children: snapshot.map((data) => _buildListItem(context, data)).toList(),
),
),
Expanded(flex:1,
child:
ElevatedButton(
// fill in required params
),
)
])

Flutter Visibility with Condition (How can I hide only one widget with condition)

I have a problem with using Visibility widget.
What I want to do is hiding certain listview's by depending user's click on my Row. But when User click on row, all Listview is showing. When clicked again, all listview widget's are going away.
What I want to do is with images:
This is how my page looks
This is what happens when I click on arrow button or "Sezon 1" Text
This is what I want to do when I click on arrow button or "Sezon 1" Text
What I'm trying to do is When I click Season 2, it will show season 2 episodes. When I click season 3 it will show season 3 episodes etc.
Here is my code (I know It's a little messy for right now, apologize for that) :
GestureDetector is working same for every click.
bool viewVisible = false;
void hideWidget() {
setState(() {
viewVisible = !viewVisible;
print(viewVisible);
});
StreamBuilder<QuerySnapshot>(
stream: seasons.snapshots(),
builder:
(BuildContext context, AsyncSnapshot asyncSnapshot) {
if (asyncSnapshot.hasError) {
return Center(
child:
Text('Error'));
} else {
if (asyncSnapshot.hasData) {
List<DocumentSnapshot> listOfDocumentSnap =
asyncSnapshot.data.docs;
return Padding(
padding: const EdgeInsets.only(top: 0, left: 0),
child: Align(
alignment: Alignment.topLeft,
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
itemCount: listOfDocumentSnap.length,
itemBuilder: (context, index) {
var episodes = firestore
.collection('shows')
.doc(data.id)
.collection('Seasons')
.doc(listOfDocumentSnap[index].id)
.collection('Episodes');
return Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(
top: 0, left: 18, right: 18),
child: GestureDetector(
onTap: () {
hideWidget();
},
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(
8),
border: Border.all(
color: Colors.pink)),
child: Row(
children: [
SizedBox(
width: 20,
),
Text(
listOfDocumentSnap[index]
.get('name')
.toString()
.toUpperCase(),
style: TextStyle(
fontSize: 20,
color:
Colors.grey[800],
fontWeight:
FontWeight.w700),
),
Spacer(flex: 1),
Icon(
Icons.arrow_drop_down,
size: 45,
color: Colors.pink,
),
],
),
),
),
),
StreamBuilder<QuerySnapshot>(
stream: episodes.snapshots(),
builder: (BuildContext context,
AsyncSnapshot asyncSnapshot) {
if (asyncSnapshot.hasError) {
return Center(
child: Text(
'Error'));
} else {
if (asyncSnapshot.hasData) {
List<DocumentSnapshot>
listOfDocumentSnap =
asyncSnapshot.data.docs;
return Padding(
padding:
const EdgeInsets.only(
top: 5, left: 18.0),
child: Visibility(
visible: viewVisible,
child: Align(
alignment:
Alignment.topLeft,
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
itemCount:
listOfDocumentSnap
.length,
itemBuilder:
(context,
index) {
return ListTile(
onTap: () {
setState(
() {
selectedIndex =
index;
});
},
trailing:
Icon(Icons
.play_arrow),
title: Text(listOfDocumentSnap[
index]
.id
.toString()),
);
/* return Text(
listOfDocumentSnap[
index]
.get(
'name'));*/
},
),
],
),
),
),
);
} else {
return Center(
child:
CircularProgressIndicator());
}
}
},
),
SizedBox(
height: 30,
)
],
);
},
),
],
),
),
);
} else {
return Center(child: CircularProgressIndicator());
}
}
},
),
Sorry, I did not check what is wrong with your code. But, instead of writing your own hide/show logic for each row, try to use Flutter's ExpansionTile widget. It will handle the expanded/collapsed states for you:
https://medium.com/flutterdevs/expansion-tile-in-flutter-d2b7ba4a1f4b
There are two different way I know to handle widget visibility. Create a bool to switch visibility. I'm using _show.
Using if condition
inside (column or any widget)
if (_show) Container(),
Using Visibility Widget
Column(
children: [
Visibility(
visible: _show,
child: Container(),
),
)

Showing a BottomSheet on a dialog in flutter

Is there a way to show a bottom sheet on Dialogs?
Dialog(
child: Container(
width: 300,
height: 500,
child: Stack(children: [
Column(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
InkWell(
child: Image.asset(AppImages.mood_arrow_up, width: 100),
onTap: () {
showModalBottomSheet(
context: context,
builder: (builder) {
return new Container(
height: 350.0,
color: Colors.transparent,
child: new Container(
child: new Center(
child: new Text("This is a modal sheet"),
)),
);
});
})
])
])));
So I have a dialog at the center of the screen and I want to show a bottom sheet inside the dialog, this code is showing it in the whole scree.
After trying to do so, it seems that it's impossible, I created custom bottom sheet with animation.
double height = 0;
return Dialog(
backgroundColor: Colors.transparent,
child: StatefulBuilder(
builder: (BuildContext context, setState) => Container(
width: 300,
height: 500,
child: Stack(children: [
Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.red)),
Column(children: [
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
IconButton(icon: Image.asset(AppImages.share), iconSize: 35, onPressed: () => pop()),
IconButton(icon: Icon(Icons.close, color: AppColors.textButton), onPressed: () => pop()),
]),
Spacer(),
InkWell(
child: Image.asset(AppImages.mood_arrow_up, width: 100),
onTap: () {
setState(() {
if (height == 0)
height = 200;
else
height = 0;
});
}),
AnimatedContainer(
color: Colors.yellow,
duration: Duration(milliseconds: 200),
height: height,
)
])
]))));