I have created a list view with images in flutter. it works but the images is wrong size. It looks like this:
But what I want is this:
This is the code I am using:
SizedBox(
height: 300,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext ctx, int index) {
return SizedBox(
width: MediaQuery.of(context).size.width * 0.5,
child: Card(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.file(
File(_imageFileListM[index].path),
fit: BoxFit.fitWidth,
),
),
margin: const EdgeInsets.all(10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
));
},
itemCount: _imageFileListM.length,
))
What am I doing wrong?
CodePudding user response:
try this:
SizedBox(
height: 300,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext ctx, int index) {
return SizedBox(
width: MediaQuery.of(context).size.width * 0.5,
child: Card(
elevation: 0,
color: Colors.transparent,
surfaceTintColor: Colors.transparent,
child: Align(
alignment: Alignment.center,
child: Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(10),
),
child: Image.file(
File(_imageFileListM[index].path),
fit: BoxFit.contain,
),
),
),
margin: const EdgeInsets.all(10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
));
},
itemCount: _imageFileListM.length,
)),
CodePudding user response:
use container widget Box decoration property like this may help you
Container( height: 200.h, width: double.infinity, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("Enter your path") ), color: baseColor2, borderRadius: BorderRadius.only( bottomLeft:Radius.circular(20.r), bottomRight:Radius.circular(20.r))),
),
CodePudding user response:
Just wrap your list element with FittedBox
like this:
SizedBox(
height: 300,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext ctx, int index) {
return SizedBox(
width: MediaQuery.of(context).size.width * 0.5,
child: FittedBox(
child: Card(
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.file(
File(_imageFileListM[index].path),
fit: BoxFit.fitWidth,
),
),
margin: const EdgeInsets.all(10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
),
));
},
itemCount: _imageFileListM.length,
)))
CodePudding user response:
A simple way to achieve this is to use Stack and position.
Stack allows widgets to overlap each other. Positioned allows you to render its child at a specific location within the stack.
The stack is pretty much like a column but the widgets are rendered on top of each other therefore you need to specify how they should render.
This would be your main Image Widget:
The image is wrapped in an expanded-sized box to cover the whole space.
positioned is set to bottom 0 will stick the widget to the bottom. left and right are specified to be 0 so the widget also expands horizontally.
class ImageWidget extends StatelessWidget {
final String url;
const ImageWidget({super.key, required this.url});
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Stack(
children: [
SizedBox.expand(
child: Image.network(
url,
fit: BoxFit.contain,
),
),
const Positioned(
left: 0,
right: 0,
bottom: 0,
child: ImageChildWidget(),
),
],
),
);
}
}
This would be the bottom part. you can replace this with anything you'd like.
class ImageChildWidget extends StatelessWidget {
const ImageChildWidget({super.key});
@override
Widget build(BuildContext context) {
return const ColoredBox(
color: Color.fromARGB(155, 0, 0, 0),
child: Padding(
padding: EdgeInsets.all(8),
child: Text(
'Some Long Text',
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
),
),
);
}
}
You also have a grid view, it's easy with gridDelegate
- crossAxisCount: 2, says that you want 2 elements per row
- mainAxisSpacing: 16, says that you want a padding of 16 vertically
- crossAxisSpacing: 16, says that you want a padding of 16 horizontally
class GridExample extends StatefulWidget {
const GridExample({super.key});
@override
State<GridExample> createState() => GridExampleState();
}
class GridExampleState extends State<GridExample> {
// Generate a random list of images
List<String> urls = List.generate(
10,
(_) {
int random = Random().nextInt(500) 250; // 250-500
return 'https://picsum.photos/$random/$random';
},
);
@override
Widget build(BuildContext context) {
return GridView.builder(
key: widget.key,
itemCount: urls.length,
padding: const EdgeInsets.all(16),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
),
itemBuilder: (context, index) {
return ImageWidget(
key: ValueKey(urls[index]),
url: urls[index],
);
},
);
}
}
Full code sample.
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: GridExample(
key: ValueKey('grid'),
),
),
),
);
}
}
class GridExample extends StatefulWidget {
const GridExample({super.key});
@override
State<GridExample> createState() => GridExampleState();
}
class GridExampleState extends State<GridExample> {
// Generate a random list of images
List<String> urls = List.generate(
10,
(_) {
int random = Random().nextInt(500) 250; // 250-500
return 'https://picsum.photos/$random/$random';
},
);
@override
Widget build(BuildContext context) {
return GridView.builder(
key: widget.key,
itemCount: urls.length,
padding: const EdgeInsets.all(16),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
),
itemBuilder: (context, index) {
return ImageWidget(
key: ValueKey(urls[index]),
url: urls[index],
);
},
);
}
}
class ImageWidget extends StatelessWidget {
final String url;
const ImageWidget({super.key, required this.url});
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Stack(
children: [
SizedBox.expand(
child: Image.network(
url,
fit: BoxFit.contain,
),
),
const Positioned(
left: 0,
right: 0,
bottom: 0,
child: ImageChildWidget(),
),
],
),
);
}
}
class ImageChildWidget extends StatelessWidget {
const ImageChildWidget({super.key});
@override
Widget build(BuildContext context) {
return const ColoredBox(
color: Color.fromARGB(155, 0, 0, 0),
child: Padding(
padding: EdgeInsets.all(8),
child: Text(
'Some Long Text',
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
),
),
);
}
}
End result: