Remove extra part after clipping in Flutter - android

Clipping allows me to draw only the part which I want to show. How do I remove the extra part which is not drawn but still takes up space?
The code
import 'package:flutter/material.dart';
class ClipTut extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: <Widget>[
ClipRect(
clipper: CustomRect(),
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 4, color: Colors.black),
color: Colors.blue,
),
width: 200.0,
height: 200.0,
),
),
Container(
height: 200,
width: 100,
decoration: BoxDecoration(
border: Border.all(width: 4, color: Colors.black),
color: Colors.green,
),
)
],
),
),
);
}
}
class CustomRect extends CustomClipper<Rect> {
#override
Rect getClip(Size size) => Rect.fromLTRB(0, 0.0, size.width/2, size.height);
#override
bool shouldReclip(CustomRect oldClipper) => true;
}

My Solution
I had a similar problem recently (I needed to clip the image in half) and found this sample code on the flutter api site (use the other alignment points to change slicing behaviors) - no extra space left over:
ClipRect(
child: Align(
alignment: Alignment.topCenter,
heightFactor: 0.5,
child: Image.network(userAvatarUrl),
),
)

Related

How to make a transparent container stand out from the background?

I'm trying to make my containers transparent and still want them to easily standout from the background color, just like below image. (this is PSD image)
Desired Layout
I tried wrapping Container inside a Material widget like this:
class customBar extends StatelessWidget {
const customBar({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
elevation: 2,
borderRadius: BorderRadius.circular(10),
child: Container(
width: double.infinity,
height: 65,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
//color: Color(0xff0a4873),
),
child: Text(
'',
textAlign: TextAlign.left,
),
),
);
}
}
but it gives it too much elevation
also tried using a solid color but that doesn't give me what is required either,
Expanded(
flex: 4,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
customBar(),
Container(
width: double.infinity,
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Color(0xff0a4873),
),
child: Text(
'',
textAlign: TextAlign.left,
),
),
],
),
),
),
here is the output:
Output
Material is not necessary. If you want to adjust color transparency either use Colors.YOUR_COLOR.withOpacity(0.0 .. to .. 1.0) or Color.fromRGBO(RED, BLUE, GREEN, 0.0 .. to .. 1.0)
Examples:
Colors.blue.withOpacity(0.3);
// OR
Color.fromRGBO(50, 45, 220, 0.3);
Edit
You can simplify your layout like this.
HomePage
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomContainer(
child: Column(
children: [
// other widgets and your containers here
],
),
),
);
}
}
Your CustomContainer Widget
class CustomContainer extends StatelessWidget {
final Widget child;
CustomContainer({this.child});
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomLeft,
colors: [
Color(0xFF1187be),
Color(0xff061465),
],
),
),
child: child,
);
}
}

quadraticBezierTo Mirroring in Flutter

I'm very new to flutter and I have been trying to create a modern drawer, and I have found one, the problem is the one I have found usesquadraticBezierTo and enddrawerwhich opens the drawer on the right to left but want to usedrawer which opens the drawer form left to right. here is my code
Widget build(BuildContext context) {
width = MediaQuery.of(context).size.width - 50;
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
drawerScrimColor: Colors.grey.shade900.withOpacity(0.5),
drawer: ClipPath(
clipper: _DrawerClipper(),
child: Drawer(
child: Container(
padding: const EdgeInsets.only(top: 48, bottom: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
color: Colors.blue.shade200,
child: DrawerHeader(
child:Wrap(
children:<Widget>[
Container(
alignment: Alignment.topCenter,
child: CircleAvatar(
maxRadius: 40,
child: Image.asset("assets/profile.png"),
),
),
Container(padding: EdgeInsets.fromLTRB(0, 10, 0, 0), alignment: Alignment.center,
child:Text("Name",style: TextStyle(fontSize: 20,color: Colors.white),
),
),
Container( alignment: Alignment.center,
child:Text("E-mail Address",style: TextStyle(fontSize: 20,color: Colors.white),
),
),
],
),
),
),
ListTile(
title: Center(
child: Text(
"Item1",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
)),),],
)),),),
and I use the following class for the clipper:
class _DrawerClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
Path path = Path();
path.moveTo(50, 0);
path.quadraticBezierTo(0, size.height / 2, 50, size.height);
path.lineTo(size.width, size.height);
path.lineTo(size.width, 0);
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}
and here is a photo of how it looks:
If I use endDraweit looks normal but in my case I want to use drawer. I assume it has something to do with the quadraticBezierTo parameters but i'm not sure. how can I fix this?
Thanks for the help

I want the second widget(container) to be aligned to the left but it's aligned to the center. How can I align it to the left along other widgets?

I want to align the container commented "// add student button" to the left but it aligns to center.
I have also tried using a raised button insted but in that case it extends to the full parent container length but I only want it to clip to the button content.
import 'package:educewebsite/SizeConfig.dart';
import 'package:flutter/material.dart';
class StudentsScreen extends StatefulWidget {
#override
_StudentsScreenState createState() => _StudentsScreenState();
}
class _StudentsScreenState extends State<StudentsScreen> {
#override
Widget build(BuildContext context) {
return Container(
height: SizeConfig.blockSizeVertical * 90,
width: SizeConfig.blockSizeHorizontal * 80,
margin: EdgeInsets.all(SizeConfig.blockSizeVertical * 2),
child:
Column(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
// top title
ListTile(
leading: Icon(
Icons.people,
size: 40,
),
title: Text(
'Students',
style: TextStyle(fontSize: 22),
)),
// add new student button
Container(
alignment: Alignment.center,
height: SizeConfig.blockSizeVertical * 8,
width: SizeConfig.blockSizeHorizontal * 15,
decoration: BoxDecoration(
color: Colors.blue, borderRadius: BorderRadius.circular(10)),
child: ListTile(
leading: Icon(Icons.person_add, color: Colors.white, size: 35),
title: Text(
'Add Student',
style: TextStyle(color: Colors.white, fontSize: 20),
)),
),
//search student form
Container(
child: Text('this is here'),
margin: EdgeInsets.symmetric(
vertical: SizeConfig.blockSizeVertical * 2.5,
horizontal: SizeConfig.blockSizeHorizontal * 1),
height: SizeConfig.blockSizeVertical * 65,
width: SizeConfig.blockSizeHorizontal * 80,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(width: 1, color: Colors.black12),
borderRadius: BorderRadius.circular(10)),
)
]),
);
}
}
wrap your "Add student button" container in Align Widget.
Ex:-
Align(
alignment: Alignment.centerLeft,
child: Container() // Add Student Button Container,
),

Splash flows outside of Container/FlatButton - Flutter

I'm trying to get the splash to match the same shape as my Container that has a FlatButton as its child.
When pressed, the splash currently fills a different shape as shown here:
My code for the widget is below:
import 'package:flutter/material.dart';
class RoundedButton extends StatelessWidget {
const RoundedButton( {this.buttonColor, this.buttonTitle, #required this.onPressed});
final Color buttonColor;
final String buttonTitle;
final Function onPressed;
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: 16.0),
height: 42.0,
width: 200.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: buttonColor,
),
child: FlatButton(
onPressed: onPressed,
child: Text(
buttonTitle,
style: TextStyle(
color: Colors.white
),
),
),
);
}
}
You can use ClipRRect widget which clips the underlying widget with rounded corners and by using borderRadius property and passing same radius as of parent widget ie, Container, ie, wrap the FlatButton with ClipRRect to achieve desired effect. Sample working code below:
body: Container(
margin: EdgeInsets.symmetric(vertical: 16.0),
height: 42.0,
width: 200.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: Colors.red,
),
child: ClipRRect(
borderRadius: BorderRadius.circular(30),
child: FlatButton(
onPressed: () {
print('pressed');
},
child: Text(
'Send',
style: TextStyle(
color: Colors.white
),
),
),
)
),
Hope this answers your question.

Flutter shadow over other widgets

My base widget is a Column. The first element is a Container which has a BoxShadow. The second element is a ListView which builds several Card, depending on the context. If the scroll is 0 the shadow gets displayed. However when start scrolling, the card is "over" the shadow (higher z-index) and hides it.
unscrolled
scrolled
The shadow should stay always on top, over the Cards. How is this done?
EDIT
if you don't want container shadow to disappear on scroll remove the ScrollNotification and NotificationListener
There is a widget for that 😉
You can use ScrollNotification with NotificationListener. Try this;
Happy coding! 🤓
class TestPage extends StatefulWidget {
const TestPage({Key key}) : super(key: key);
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
double blurRadius = 10.0;
double spreadRadius = 1.0;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey,
title: Text('Title'),
),
body: Container(
width: Get.width,
height: Get.height,
child: Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0).copyWith(
top: 62.0,
),
child: NotificationListener<ScrollNotification>(
// ignore: missing_return
onNotification: (scrollNotification) {
if (scrollNotification is ScrollStartNotification) {
setState(() {
blurRadius = 0.0;
spreadRadius = 0.0;
});
} else if (scrollNotification is ScrollEndNotification) {
setState(() {
blurRadius = 10.0;
spreadRadius = 1.0;
});
}
},
child: ListView.builder(
// controller: _controller,
itemCount: 10,
itemBuilder: (context, index) {
return Card(
child: Container(
width: Get.width * .8,
height: 100.0,
child: Center(
child: Text('child # index : $index'),
)),
);
},
),
),
),
Positioned(
top: 0,
left: 0,
right: 0,
child: Container(
width: Get.width,
height: 60.0,
margin: EdgeInsets.only(),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20.0),
bottomRight: Radius.circular(20.0),
),
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: blurRadius,
spreadRadius: spreadRadius,
),
],
),
child: Center(
child: Text('TOP CONTAINER'),
),
),
),
],
),
),
);
}
}
According to your question, here is the concept of what is going wrong here.
The 1st child of Column is a Container with shadow. Shadow renders outside of the defined size. If you don't provide any spaces after this Container we won't be able to see the shadow. This space can be done by Container margin , SizedBox or wrapping our list with Padding. But now our main question is how we get shadow while index=0. I believe it is coming from ListChildren`. They contain upper spaces, that's why we can see only the 1st time.
On Ui render priority starts from bottom to Top.
How to solve this problem:
We can provide space at the bottom of our container or assign margin(not padding), or use a SizedBox after the container providing the same amount of height as shadow.
providing bottom margin on the container.
adding a SizedBox with height of shadow.
wrapping our list with Padding and providing top:.
In this image,
our shadow: white, background:amber.
Demo code:
import 'package:flutter/material.dart';
class ColumnWithContainerShadow extends StatelessWidget {
const ColumnWithContainerShadow({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
body: Column(
children: [
Container(
height: 50,
width: double.infinity,
////* we dont need margin if we have padding on ListView
// margin: EdgeInsets.only(bottom: 12),
decoration: BoxDecoration(
color: Colors.green,
boxShadow: [
BoxShadow(
offset: Offset(0, 12),
color: Colors.white,
)
],
),
child: Center(child: Text("Container A")),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 12),
child: ListView(
children: [
...List.generate(
333,
(index) => Container(
/// enable this margine and remove other spaces to see 1st child shadow.(shadow depend on children position)
// margin: EdgeInsets.only(top: 12),
height: 60,
color: Colors.deepPurple,
child: Text("$index"),
),
)
],
),
),
),
Container(
height: 50,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.green,
boxShadow: [
BoxShadow(
offset: Offset(0, 12),
color: Colors.white,
)
],
),
child: Text("Bottom Container"),
),
// Comment to close shadow
SizedBox(
height: 20,
)
],
),
);
}
}
Wrap this upper box in Material widget and provide an elevation.

Categories

Resources