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()),),
),
),
),
),
),
),
),
),
Help me, any idea how to remove the space between yellow and green Container?
It's caused by the Container have additional height after transform translate.
I need CustomSrollView with SliverAppBar and a child below it.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: Scaffold(
body: Example(),
),
);
}
}
class Example extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CustomScrollView(slivers: [
SliverSafeArea(
top: false,
sliver: SliverAppBar(
backgroundColor: Colors.black.withOpacity(0.2),
floating: true,
toolbarHeight: 0,
bottom: const PreferredSize(
preferredSize: Size.fromHeight(30), child: Text("AppBar")),
),
),
SliverToBoxAdapter(
child: Transform.translate(
offset: const Offset(0.0, -30.0),
child: Container(height: 500, color: Colors.yellow),
),
),
SliverToBoxAdapter(
child: Align(child: Container(height: 500, color: Colors.green))),
]);
}
}
Ok, you want to move the yellow container, but you don't want to take translate spaces the space. I don't know what design you are doing, I may just reduce the height in this case. Or use padding in extra spaces.
According to the question, we can use stack like.
SliverToBoxAdapter(
child: Container(
color: Colors.amber,
height: 500 + 500,
child: Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 500,
color: Colors.green,
),
),
Positioned(
bottom: 500 - 30,
child: Transform.translate(
offset: const Offset(0.0, -30.0),
child: Container(
height: 500,
color: Colors.yellow,
),
),
),
],
),
),
),
But in this case we are overlapping with green container.
We can
reduce the size,
use stack, will overlap with green container
I am trying to add a header card which will be displayed on the upper-left edge of a flutter card, so far I haven't been able to achieve that. This is an example of what I want
Being new to flutter, I didn't know there was a Stack widget. The solution is to stack two cards wrapped in Positioned widgets.
class SummaryCard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
left: 0,
top: 40,
height: 200,
width: 350,
child: Card(
color: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
),
),
),
Positioned(
left: 20,
top: 0,
height: 100,
width: 100,
child: Card(
color: Colors.green,
elevation: 10.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
),
),
),
],
);
}
}
You need to wrap header card with Align Widget.
Here is a full code:
class Cards extends StatefulWidget {
#override
_CardsState createState() => _CardsState();
}
class _CardsState extends State<Cards> {
#override
Widget build(BuildContext context) {
return Container(
height: 200,
width: 200,
child: Card(
elevation: 20,
child: Align(
alignment: Alignment.topLeft,
child: Container(
width:100,
height: 60,
child: Card(
elevation: 10,
child: Text("header"),
),
),
),
),
);
}
}
Containers are just for height and width control.
And here is a screenshot:
I am using SliverAppBar and SliverListView in my project.
I need BorderRadius to my SliverList that is coming bottom of my SliverAppBar.
Here is screenshot what I need :
And here is my code:
Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
backgroundColor: Colors.transparent,
brightness: Brightness.dark,
actions: <Widget>[
IconButton(icon: Icon(Icons.favorite), onPressed: () {}),
IconButton(icon: Icon(Icons.share), onPressed: () {})
],
floating: false,
pinned: false,
//title: Text("Flexible space title"),
expandedHeight: getHeight(context) - MediaQuery.of(context).padding.top,
flexibleSpace: Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage("assets/images/Rectangle-image.png")
)
),
),
bottom: _bottomWidget(context),
),
SliverList(
delegate: SliverChildListDelegate(listview),
),
],
),
)
So, with this code the UI is coming like this...
can suggest any other approach that i can take to achieve this kind of design...
I achieved this design using SliverToBoxAdapter my code like this.
final sliver = CustomScrollView(
slivers: <Widget>[
SliverAppBar(),
SliverToBoxAdapter(
child: Container(
color: Color(0xff5c63f1),
height: 20,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
height: 20,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(20.0),
topRight: const Radius.circular(20.0),
),
),
),
],
),
),
),
SliverList(),
],
);
I used 2 containers inside SliverToBoxAdapter.
SliverToBoxAdapter is between the Sliver Appbar and the Sliver List.
first I create a blue (should be Appbar color) container for the corner edge.
then I create the same height white container with border-radius inside the blue container for list view.
Preview on dartpad
Solution
At the time of writing, there is no widget that would support this functionality. The way to do it is with Stack widget and with your own SliveWidget
Before:
Here is your default code:
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(
title: 'Flexible space title',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
backgroundColor: Colors.transparent,
brightness: Brightness.dark,
actions: <Widget>[IconButton(icon: Icon(Icons.favorite), onPressed: () {}), IconButton(icon: Icon(Icons.share), onPressed: () {})],
floating: false,
pinned: false,
expandedHeight: 250 - MediaQuery.of(context).padding.top,
flexibleSpace: Container(
height: 550,
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'https://images.unsplash.com/photo-1561752888-21eb3b67eb4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=967&q=80'))),
),
//bottom: _bottomWidget(context),
),
SliverList(
delegate: SliverChildListDelegate(_listview(50)),
),
],
),
),
);
}
}
List _listview(int count) {
List<Widget> listItems = List();
listItems.add(Container(
color: Colors.black,
height: 50,
child: TabBar(
tabs: [FlutterLogo(), FlutterLogo()],
),
));
for (int i = 0; i < count; i++) {
listItems.add(new Padding(padding: new EdgeInsets.all(20.0), child: new Text('Item ${i.toString()}', style: new TextStyle(fontSize: 25.0))));
}
return listItems;
}
After
And here is your code done with Stack and SliveWidget widgets:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flexible space title',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
body: Stack(
children: [
Container(
height: 550,
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'https://images.unsplash.com/photo-1561752888-21eb3b67eb4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=967&q=80'))),
),
CustomScrollView(
anchor: 0.4,
slivers: <Widget>[
SliverWidget(
child: Container(
width: double.infinity,
height: 100,
decoration: BoxDecoration(
color: Colors.yellow, borderRadius: BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))),
child: TabBar(
tabs: [FlutterLogo(), FlutterLogo()],
),
),
),
SliverList(
delegate: SliverChildListDelegate(_listview(50)),
),
],
),
],
),
),
);
}
}
List _listview(int count) {
List<Widget> listItems = List();
for (int i = 0; i < count; i++) {
listItems.add(
Container( //NOTE: workaround to prevent antialiasing according to: https://github.com/flutter/flutter/issues/25009
decoration: BoxDecoration(
color: Colors.white, //the color of the main container
border: Border.all(
//apply border to only that side where the line is appearing i.e. top | bottom | right | left.
width: 2.0, //depends on the width of the unintended line
color: Colors.white)),
child: Container(
padding: EdgeInsets.all(20),
color: Colors.white,
child: new Text(
'Item ${i.toString()}',
style: new TextStyle(fontSize: 25.0),
),
),
),
);
}
return listItems;
}
class SliverWidget extends SingleChildRenderObjectWidget {
SliverWidget({Widget child, Key key}) : super(child: child, key: key);
#override
RenderObject createRenderObject(BuildContext context) {
// TODO: implement createRenderObject
return RenderSliverWidget();
}
}
class RenderSliverWidget extends RenderSliverToBoxAdapter {
RenderSliverWidget({
RenderBox child,
}) : super(child: child);
#override
void performResize() {}
#override
void performLayout() {
if (child == null) {
geometry = SliverGeometry.zero;
return;
}
final SliverConstraints constraints = this.constraints;
child.layout(constraints.asBoxConstraints(/* crossAxisExtent: double.infinity */), parentUsesSize: true);
double childExtent;
switch (constraints.axis) {
case Axis.horizontal:
childExtent = child.size.width;
break;
case Axis.vertical:
childExtent = child.size.height;
break;
}
assert(childExtent != null);
final double paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: childExtent);
final double cacheExtent = calculateCacheOffset(constraints, from: 0.0, to: childExtent);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = SliverGeometry(
scrollExtent: childExtent,
paintExtent: 100,
paintOrigin: constraints.scrollOffset,
cacheExtent: cacheExtent,
maxPaintExtent: childExtent,
hitTestExtent: paintedChildSize,
);
setChildParentData(child, constraints, geometry);
}
}
Use Stack. It's the best and smooth way I found and used.
Preview
import 'dart:math';
import 'package:agro_prep/views/structure/constant.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class CropDetailsPage extends StatelessWidget {
const CropDetailsPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
backgroundColor: Colors.white,
actions: <Widget>[
IconButton(icon: Icon(Icons.share), onPressed: () {})
],
floating: false,
pinned: false,
//title: Text("Flexible space title"),
expandedHeight: 281.h,
flexibleSpace: Stack(
children: [
const Positioned.fill(
child: FadeInImage(
image: NetworkImage(tempImage),
placeholder: const NetworkImage(tempImage),
// imageErrorBuilder: (context, error, stackTrace) {
// return Image.asset('assets/images/background.jpg',
// fit: BoxFit.cover);
// },
fit: BoxFit.cover,
),
),
Positioned(
child: Container(
height: 33.h,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(
top: Radius.circular(40),
),
),
),
bottom: -7,
left: 0,
right: 0,
)
],
),
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return ListTile(
tileColor: whiteColor,
title: Text(Random().nextInt(100).toString()),
);
}, childCount: 15))
],
),
);
}
}
Worked for me!
SliverAppBar(
pinned: true,
floating: false,
centerTitle: true,
title: TextWidget(detail.title,
weight: FontWeight.bold
),
expandedHeight: MediaQuery.of(context).size.height/2.5,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
collapseMode: CollapseMode.parallax,
background: Stack(
children: [
// Carousel images
Swiper(
itemWidth: MediaQuery.of(context).size.width,
itemHeight: MediaQuery.of(context).size.height /3.5,
itemCount: 2,
pagination: SwiperPagination.dots,
loop: detail.banners.length > 1,
itemBuilder: (BuildContext context, int index) {
return Image.network(
'https://image.com?image=123.png',
fit: BoxFit.cover
);
}
),
//Border radius
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Colors.transparent,
height: 20,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
height: 10,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(10),
topRight: const Radius.circular(10),
),
),
),
],
),
),
)
],
),
),
)
So the best way to achieve your result is to use "bottom" poperty inside SliverAppBar. This will add your rounded container to bottom of appbar / start of sliverlist
bottom: PreferredSize(
preferredSize: const Size.fromHeight(24),
child: Container(
width: double.infinity,
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(
top: Radius.circular(12),
),
color: Colors.white,
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(2),
),
),
),
],
),
),
),
The idea is good but it looks odd in some cases.
You could give a borderRadius to your first element in your list
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(index == 0 ? 15 : 0),
topLeft: Radius.circular(index == 0 ? 15 : 0),
),
),
)
Hope this helps someone
Try This, It's a Simple Solution
import 'package:flutter/material.dart';
class SliveR extends StatelessWidget {
const SliveR({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
SizedBox(
width: double.infinity,
child: Image.network(
'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2700&q=80',
fit: BoxFit.cover,
height: MediaQuery.of(context).size.height * 0.35,
),
),
Align(
alignment: Alignment.topCenter,
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(30)),
),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(30)),
child: CustomScrollView(
anchor: 0.3,
slivers: [
SliverToBoxAdapter(
child: Container(
height: 900,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40.0),
topRight: Radius.circular(40.0),
),
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 16.0,
),
],
),
child: const Center(
child: Text(
'Hello',
style: TextStyle(color: Colors.grey),
),
),
),
)
],
),
),
),
),
],
),
);
}
}
FlexibleSpaceBar(
title: CustomText(
text: "Renaissance Concourse Hotel",
textSize: kSubtitle3FontSize,
fontWeight: kBold),
centerTitle: true,
collapseMode: CollapseMode.pin,
background: Stack(
children: [
CachedNetworkImage(
imageUrl:
"url",
width: DeviceUtils.getWidth(context),
fit: BoxFit.cover,
placeholder: (context, url) => const Center(
child: CircularProgressIndicator(),
),
errorWidget: (context, url, error) =>
const Icon(Icons.error_rounded),
),
Positioned(
bottom: 50,
right: 0,
left: 0,
child: ContainerPlus(
color: kWhiteColor,
child: const SizedBox(
height: 20,
),
radius: RadiusPlus.only(
topLeft: kBorderRadiusValue10,
topRight: kBorderRadiusValue10,
),
),
)
],
))
I am trying to apply image in the background of the status bar in an flutter project. So which widget can help me to apply the following expected result.
detailpage.dart
import 'package:flutter/material.dart';
class MyDetailPage extends StatefulWidget {
#override
_MyDetailPageState createState() => _MyDetailPageState();
}
class _MyDetailPageState extends State<MyDetailPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
height: 300,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/image2.png"),
fit: BoxFit.fitHeight,
),
),
)
],
),
);
}
}
Use Scaffold property
extendBodyBehindAppBar: true, and
set statusBarColor: Colors.transparent
This code is for status bar colour.
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent
));
Here is an example of code in my current project.
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent
));
return Scaffold(
extendBodyBehindAppBar: true,
body: Column(
children: [
Container(
height: 250,
child: Container(
child: Stack(
alignment: Alignment.topLeft,
children: [
Container(
width: screenWidthPercentage(context,percentage: 1),
child: Image.network(
contentImage,
fit: BoxFit.cover,
),
),
Padding(
padding: const EdgeInsets.only(top: 48.0,left: 12),
child: Icon(Icons.arrow_back,color: Colors.white,),
),
],
),
),
),
],
),
);
}
}
you can do it by not keeping SafeArea widget and set statusbar color as transparent.
I have created an example as below.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class FullScreen extends StatefulWidget {
const FullScreen({Key? key}) : super(key: key);
#override
_FullScreenState createState() => _FullScreenState();
}
class _FullScreenState extends State<FullScreen> {
#override
void initState() {
super.initState();
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light
//color set to transperent or set your own color
)
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: buildBody(),
);
}
Widget buildBody() {
return SizedBox(
height: 400,
width: double.infinity,
child: Card(
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.all(0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(40),
bottomRight: Radius.circular(40)),
),
child: Image.network(
'https://source.unsplash.com/random',
fit: BoxFit.cover,
),
),
);
}
}
I have added card as it gives nice elevation effect to the image 😎 .
FYI keep margin as 0 in card if you are using card.
You can achieve it using FlexibleSpaceBar, here is the example code.
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
expandedHeight: 300,
flexibleSpace: FlexibleSpaceBar(
background: Image.asset("assets/images/chocolate.jpg", fit: BoxFit.cover),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text("Item ${index}")),
childCount: 100,
),
),
],
),
);
}
When we using a ListView on a top tree,
The ListView makes a default padding.top even without a SafeArea.
So we need a
padding: EdgeInsets.zero.