Flutter : When I rotate a horizontal ListView by Transform.rotate, the left and right edges are cut off - flutter

When I use Transform.rotate to make a horizontal ListView diagonal as shown below, it becomes diagonal, but the left and right edges are cut off.
Is there a way to display without clipping the left and right edges, or is there a widget that can be used for that?
I came up with a way to use the Stack widget to overlay the left and right edges with strips of gradation and make them invisible.
I've actually tried it and it's fine, but I thought I'd ask if there is another way.
I think this is happening because the screen width is passed from the parent as a constraint, but is there any way to disable the constraint?
Thank you.
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Animated Icons',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.greenAccent,
body: Column(
children: [
Expanded(
child: Center(
child: SizedBox(
width: double.infinity,
height: 200.0,
child: Transform.rotate(
angle: -math.pi / 20,
child: Container(
color: Colors.white,
height: 200.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 6,
itemBuilder: (context, innerIndex) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
//padding: EdgeInsets.all(4.0),
height: 50.0,
width: 200.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color:
Colors.red.withOpacity(1.0 - 0.1 * innerIndex),
),
child:Center(child:Text(innerIndex.toString()),),
),
),
),
),
),
),
),
),
Container(
height:100.0,
color: Colors.white,
child:Center(
child:Text('title'),
),
)
],
),
);
}
}

With the following code using OverflowBox, the left and right corners are no longer cut off.
Expanded(
child: Center(
child: OverflowBox(
maxWidth: MediaQuery.of(context).size.width*1.2,
child: Transform.rotate(
angle: -math.pi / 20,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.white,
),
height: 200.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 6,
itemBuilder: (context, innerIndex) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
//padding: EdgeInsets.all(4.0),
height: 50.0,
width: 200.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color:
Colors.red.withOpacity(1.0 - 0.1 * innerIndex),
),
child:Center(child:Text(innerIndex.toString()),),
),
),
),
),
),
),
),
),

Related

Flutter wrong size of image in list view

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?
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,
)),
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))),
),
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,
)))
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:

How to put two containers on the same screen without page scrolling?

I have a search page. I display 2 containers with information on the search page. But I ran into a problem, my bottom station container goes off the screen and I need to scroll the page to see the information. How can I put 2 containers on the screen and not have to scroll the page so that 2 containers fit on the same screen?
1
Widget _addresses(Size size, StationCubit stationCubit) => ConstrainedBox(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height / 2,
),
child: SizedBox(
width: size.width,
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
child: Container(
padding: const EdgeInsets.only(left: 20, top: 17),
decoration: BoxDecoration(
color: constants.Colors.greyXDark.withOpacity(0.8),
borderRadius: BorderRadius.circular(24),
),
child: SingleChildScrollView(
controller: _addressesController,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Addresses',
style: constants.Styles.smallBookTextStyleWhite,
),
const SizedBox(height: 25),
2
Widget _station(Size size, StationCubit stationCubit) => ConstrainedBox(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height / 2,
),
child: SizedBox(
width: size.width,
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
child: Container(
padding: const EdgeInsets.only(left: 20, top: 17),
decoration: BoxDecoration(
color: constants.Colors.greyXDark.withOpacity(0.8),
borderRadius: BorderRadius.circular(24),
),
child: SingleChildScrollView(
controller: _stationController,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Station',
style: constants.Styles.smallBookTextStyleWhite,
),
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: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter 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> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: [
Expanded(
child: Container(
color: Colors.deepPurple,
child: ListView.builder(itemBuilder: (c, i) {
return Text("Test $i");
})),
),
Expanded(
child: Container(
color: Colors.deepOrange,
child: ListView.builder(itemBuilder: (c, i) {
return Text("Test $i");
})),
),
],
));
}
}
Try placing both containers in column and wrap both container with flexible/expanded to expand containers in full screen.
Example code:
column(
children: [
Expanded(
child: Container(child: Text("Container 1")
),
Expanded(
child: Container(child: Text("Container 2")
)
]
)
Use 2 Expanded container in single column
column( children: [ Expanded( child: Container(child: Text("Container 1") ), Expanded( child: Container(child: Text("Container 2") ) ] ).
Abdul Rahman Panhyar your answer is right but Max need to show data came from any API so there is a chance of bulk data and just wrapping the container with expanded will disrupt the UI. so what is suggest you can divide your screen in two parts then in each part you can use Listview builder so it will be inner scrollable.

How can I make only the constrained box scrollable or any other kind of box for the given scenario

Current State of the problem
UI:
Make this Yellow Boxes Scroll
Code:
This is the Code
How can I make only the yellow boxes... and keep the red box positioned as it is.
or any other alternative as I'm using a custom navigation container in the bottom and that cannot be scrolled.
Thank you.
Please refer to below code
class YellowBox extends StatefulWidget {
const YellowBox({Key key}) : super(key: key);
#override
_YellowBoxState createState() => _YellowBoxState();
}
class _YellowBoxState extends State<YellowBox> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("Hello World"),
),
bottomNavigationBar: Container(
height: 80.0,
width: ScreenUtil().screenWidth,
color: Colors.red,
),
body: Column(
children: [
Container(
height: 80.0,
width: ScreenUtil().screenWidth,
color: Colors.red,
),
Expanded(
child: ListView.builder(
itemCount: 10,
itemBuilder: (BuildContext ctx, int index) {
return Container(
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
height: 80.0,
width: 100.0,
color: Colors.yellow,
);
},
),
),
],
),
);
}
}

Drag and drop images from left to right side Flutter

I am working on Flutter application and I want to the functionality of toolbox. Drag and drop the elements from left panel to right panel. Currently I can drag drop element from left to right but the issue is once the element is dropped anywhere in the right panel I cannot drag drop it further in the same panel i.e. right. I want to change the location of dropped element but cannot do so. It remain there where is dropped it.
This is me code.
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
drawer: DrawerWidget(),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Table Layout',
style: Theme.of(context).textTheme.title.merge(
TextStyle(letterSpacing: 1.3),
),
),
centerTitle: true,
elevation: 0,
),
body: Container(
child: Row(
children: [
Container(
color: Colors.blue[100],
width: MediaQuery.of(context).size.width * 0.30,
child: ListView.separated(
padding: const EdgeInsets.all(16.0),
itemCount: 3,
separatorBuilder: (context, index) {
return const SizedBox(
height: 12.0,
);
},
itemBuilder: (context, index) {
return MenuListItem(
photoProvider: images[index],
);
},
),
),
Expanded(
child: Container(
color: Colors.blue[200],
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 6.0,
),
child: Container(
height: double.infinity,
width: double.infinity,
color: Colors.grey,
child: DragTarget(
builder: (context, candidateItems, rejectedItems) {
return Container();
},
onAccept: (item) {
return Container(
height: 100,
width: 100,
color: Colors.pink,
);
},
),
),
),
),
),
],
),
),
);
}
}
class MenuListItem extends StatelessWidget {
MenuListItem({
Key key,
#required this.photoProvider,
this.isDepressed = false,
}) : super(key: key);
final String photoProvider;
final bool isDepressed;
final GlobalKey _draggableKey = GlobalKey();
#override
Widget build(BuildContext context) {
return Draggable(
dragAnchor: DragAnchor.pointer,
feedback: DraggingListItem(
dragKey: _draggableKey,
photoProvider: photoProvider,
),
child: Material(
elevation: 12.0,
borderRadius: BorderRadius.circular(20),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(12.0),
child: SizedBox(
width: 120,
height: 120,
child: Center(
child: AnimatedContainer(
duration: const Duration(milliseconds: 100),
curve: Curves.easeInOut,
height: isDepressed ? 115 : 120,
width: isDepressed ? 115 : 120,
child: Image.asset(
photoProvider,
fit: BoxFit.cover,
),
),
),
),
),
),
),
);
}
}
Can anyone help me how to achieve drag drop like I want. Thanks

Clip Container with transparent icon

I'm wondering what the best approach could be to achieve the effect of the rounded icon button on the bottom right.
Do notice the icon is transparent and reveals the image background.
I tried using the Stack widget, but I could not position it properly nor get the color to be transparent.
Currently I have this:
class Banner extends StatelessWidget {
final String src;
const Banner(this.src, {Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 16 / 9,
child: Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
child: Stack(
children: <Widget>[
Image.network(src),
LayoutBuilder(
builder: (context, constraints) {
var calculatedOverlay = constraints.maxHeight / 3;
return Align(
alignment: Alignment.bottomRight,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(calculatedOverlay),
),
color: Colors.white,
),
height: calculatedOverlay,
width: calculatedOverlay,
),
);
},
),
],
),
),
Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
),
),
]),
);
}
}
Which results in this:
Thanks in advance.