My Home Page screen is not responsive at different size of the screens.
It got overlapped on other widgets.
I used MediaQuery.
How to resove this issue?
IOS Device
Android device
Code:
Size get size => Size(MediaQuery.of(context).size.width * 0.8,
MediaQuery.of(context).size.width * 0.8);
double _rotote(int index) => (index / widget.items.length) * 2 * pi;
build method:
Center(
child: Container(
// alignment: Alignment.center,
height: size.height/1.1,
width: size.width/1.1,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [BoxShadow(blurRadius: 20, color: Colors.black38)],
//border: Border.all(color: Colors.black)
),
child: Transform.rotate(
angle: -(widget.current + widget.angle) * 2 * pi,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
for (var luck in widget.items) ...[_buildCard(luck)],
for (var luck in widget.items) ...[_buildImage(luck)],
],
),
),
),
);
WHEEL CARD:
_buildCard(Luck luck) {
var _rotate = _rotote(widget.items.indexOf(luck));
var _angle = 2 * pi / widget.items.length;
return Transform.rotate(
angle: _rotate,
child: ClipPath(
clipper: _LuckPath(_angle),
child: Container(
height:size.height/1.1,
width: size.width/1.1,
decoration: BoxDecoration(
// border: Border.all(color: Colors.black),
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [luck.color, luck.color])),
),
),
);
}
IMAGE ON WHEEL
_buildImage(Luck luck) {
var _rotate = _rotote(widget.items.indexOf(luck));
return Transform.rotate(
angle: _rotate,
child: Container(
height: size.height,
width: size.width,
alignment: Alignment.topCenter,
child: ConstrainedBox(
constraints:
BoxConstraints.expand(height: size.height / 3, width: 44),
child: Image.asset(luck.asset),//Image.asset("asset/image/wheel.png")
),
),
);
}
}
These above methods are defined in a StatefulWidget class BoardView.dart
HomePage.dart
Center(
child: Column(
children: <Widget>[
ArrowView(),// for upper arrow
Stack(
alignment: Alignment.center,
children: <Widget>[
BoardView(items: _items, current: _current, angle: _angle),
_buildSpin(),
],
),
_buildResult(_value),
],
),
);
_buildSpin
_buildSpin() {
return Material(
color: Colors.white,
shape: CircleBorder(),
child: InkWell(
customBorder: CircleBorder(),
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(color: Colors.white),
color: Colors.blue,
borderRadius: BorderRadius.circular(80)
),
height: 70,
width: 70,
child: Text(
"SPIN",
style: TextStyle(fontSize: 22.0, fontWeight: FontWeight.bold, color: Colors.white),
),
),
onTap: (){},
),
);
}
I think you can have a look at this package. I have used it on one of my projects and it really makes life easy when dealing with different screens from mobile to tablets.
you can use FractionallySizedBox with widthFactor or heightFactor, see: https://www.youtube.com/watch?v=PEsY654EGZ0
and for orientation you can wrap your widget with OrientationBuilder: https://flutter.dev/docs/cookbook/design/orientation
Related
I have this video calling Application I am working on. Everything seems to be falling in place. I have a small issue with one UI effect I am trying to implement.
So here is the situation:
When on a live call, like on messenger or any other video calling application, I want user 0, to be able to drag and place their video frame at different positions in the screen.
I tried this using flutter draggable:
/// Video 0 View Customization to include draggable effect
Offset? position;
double prevScale = 1;
double scale = 1;
void updatePosition(Offset newPosition) =>
setState(() => position = newPosition);
ValueNotifier<Offset?> positionNotifier = ValueNotifier(null);
/// Video layout wrapper
Widget _viewRows() {
final views = _getRenderViews();
switch (views.length) {
case 1:
return Container(
child: Column(
children: <Widget>[_videoView(views[0])],
));
case 2:
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Stack(
children: <Widget>[
_expandedVideoRow([views[1]]),
Positioned(
left: position == null
? MediaQuery.of(context).size.width / 1.5
: position!.dx,
top: position == null ? 50 : position!.dy,
child: Draggable(
maxSimultaneousDrags: 1,
feedback: Transform.scale(
scale: scale,
child: Container(
height: MediaQuery.of(context).size.height / 4.5,
width: MediaQuery.of(context).size.width / 3.2,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(20.0),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: _expandedVideoRow([views[0]]))),
),
childWhenDragging: Opacity(
opacity: .3,
child: Transform.scale(
scale: scale,
child: Container(
height: MediaQuery.of(context).size.height / 4.5,
width: MediaQuery.of(context).size.width / 3.2,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(20.0),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: _expandedVideoRow([views[0]]))),
),
),
onDragEnd: (details) => updatePosition(details.offset),
child: Transform.scale(
scale: scale,
child: Container(
height: MediaQuery.of(context).size.height / 4.5,
width: MediaQuery.of(context).size.width / 3.2,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(20.0),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: _expandedVideoRow([views[0]]))),
),
),
),
],
));
default:
}
return Container();
}
These is then displayed in another main stack: #override
Widget build(BuildContext context) {
Stack(
fit: StackFit.expand,
children: [
if (widget.calltype == 'videocall') ...[
child: _viewRows(),
]
...
Is there any better way to attain this UI Draggable effect?
You can use this widget to make it draggable
https://pub.dev/packages/draggable_widget
I am trying to make a animation show bookmark. Just like the example on this website.The orignial example is too complicated. So I put part of code from the example of flutter doc. To learn the easiest animation. I have put same tag in both hero,but still error.
Please help me out.Thanks!
Sorry my english is poor.
Center(
child: FutureBuilder(
future: fetchData('querySdiList'),
builder: (context, qS) {
if (qS.hasData) {
return CarouselSlider.builder(
itemCount: qS.data.length,
itemBuilder: (BuildContext context, int itemIndex, int i) {
final list = qS.data[itemIndex];
sdiId = list['sdiId'];
print('carousel:' + sdiId.toString());
return Center(
child: SizedBox(
width: 300,
child: Hero(
tag: sdiId.toString(),
child: Material(
child: InkWell(
onTap: () {
// Navigator.pushNamed(context, '/BookMarkPage');
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
print('Hero:' + sdiId.toString());
return Container(
// Set background to blue to emphasize that it's a new route.
color: Colors.lightBlueAccent,
padding: const EdgeInsets.all(16.0),
alignment: Alignment.topLeft,
child: SizedBox(
width: 100,
child: Hero(
tag: sdiId.toString(),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {},
child: Image.network(
_image[0],
fit: BoxFit.contain,
),
),
),
),
));
}));
},
child: Container(
height:
MediaQuery.of(context).size.height / 2,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
offset: Offset(0, 10),
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 10,
)
],
),
margin: EdgeInsets.all(5.0),
child: Stack(
alignment: Alignment.bottomLeft,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(15)),
child: Container(
height: MediaQuery.of(context)
.size
.height /
2,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(_image[
Random().nextInt(
_image.length)])),
),
),
),
Container(
height: MediaQuery.of(context)
.size
.height,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(15)),
color: Colors.white,
gradient: LinearGradient(
begin: FractionalOffset.topCenter,
end: FractionalOffset.bottomLeft,
colors: [
Colors.transparent,
Colors.black,
],
stops: [0.0, .85],
),
),
),
Container(
padding: EdgeInsets.all(10),
child: RichText(
text: TextSpan(
text: '${list['sdiName']}',
style: TextStyle(
fontSize: 50,
color: Colors.white),
),
),
height: MediaQuery.of(context)
.size
.height /
8,
),
],
),
),
),
))));
},
options: CarouselOptions(
aspectRatio: 2,
autoPlay: true,
enlargeCenterPage: true,
height: MediaQuery.of(context).size.height,
),
);
} else if (qS.hasError) {
return qS.error;
}
return CircularProgressIndicator();
},
),
),
error
There are multiple heroes that share the same tag within a subtree.
You are creating multiple widgets with the carouselBuilder and each one of them is getting the same tag, you cant do that, the tag is what tells the Hero widget where it should animate to.
The problem seem to be here
final list = qS.data[itemIndex];
sdiId = list['sdiId'];
try setting the hero tag as something like this
tag: qS.data[itemIndex]['sdiId']
this should give each of the heros the sdiId of the itemIndex preventing them from having the same one
I'm having trouble making a card that has a transparent white color (opacity 0.4). But, with shadow from the elevation effect.
If I remove the elevation, there's no shadow effect and the card look transparent. But, if I add some elevation, the transparent effect ruined. Here's what I've tried:
Widget cardMenu(String title) {
return Container(
padding: EdgeInsets.symmetric(horizontal: UIComponent.componentPadding),
child: Stack(
alignment: Alignment.topCenter,
children: [
Positioned(
top: -100,
child: Container(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: Center(
child: Text(
title,
style: TextStyle(color: Colors.transparent),
),
),
),
)
),
Align(
alignment: Alignment.bottomCenter,
child: Card(
elevation: 0,
color: Colors.white.withOpacity(0.4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(UIComponent.cardButtonRadius),
),
),
child: Container(
height: 350,
width: 180,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
padding: EdgeInsets.all(UIComponent.widgetPadding),
child: Text(
title,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: UIComponent.h1,
color: UIComponent.neutralDark,
),
),
)
],
),
),
),
)
],
),
);
}
The output of my code:
What I'm expecting to be:
Hii Christophorus Anindityo N
Make a class for BoxShadow property of container.
class CustomBoxShadow extends BoxShadow {
final BlurStyle blurStyle;
const CustomBoxShadow({
Color color = const Color(0xFF000000),
Offset offset = Offset.zero,
double blurRadius = 0.0,
this.blurStyle = BlurStyle.normal,
}) : super(color: color, offset: offset, blurRadius: blurRadius);
#override
Paint toPaint() {
final Paint result = Paint()
..color = color
..maskFilter = MaskFilter.blur(this.blurStyle, blurSigma);
assert(() {
if (debugDisableShadows)
result.maskFilter = null;
return true;
}());
return result;
}
}
And use this class in a Container
Container(
child: Center(
child: Container(
height: 200.0,
width: 300.0
decoration: BoxDecoration(
boxShadow: [
CustomBoxShadow(
color: Colors.black,
offset: Offset(5.0, 5.0),
blurRadius: 5.0,
blurStyle: BlurStyle.outer
)
],
),
child: Text("Transparent Card with Shadow", style:TextStyle(fontSize:15))),
)
)
Now you are good to code :)
I want to build a reusable card widget, it will have an image and text with some custom design layout. I tried everything I could, but wasn't able to achieve the desired result. Any help would be much appreciated.
This is what I want to do
I'm stuck here
This is my code
class ReusabelCard extends StatelessWidget {
ReusabelCard(
{this.cardChild, #required this.assetImagePath, #required this.cardText});
final Widget cardChild;
final String assetImagePath;
final String cardText;
#override
Widget build(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height * 0.35,
width: MediaQuery.of(context).size.width * 0.5,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(MediaQuery.of(context).size.width * 0.5 * 0.28),
),
child: Stack(
children: [
LayoutBuilder(
builder: (context, contraint) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Icon(
Icons.trip_origin,
size: contraint.biggest.width,
color: Colors.grey[300],
),
Container(
height: MediaQuery.of(context).size.height*0.05,
width: MediaQuery.of(context).size.width,
color: Colors.green,
),
],
);
},
),
],
)
);
}
}
Use ClipRRect to do it:
ClipRRect(
borderRadius: BorderRadius.circular(50.0), //clipping the whole widget
child: Container(
height: MediaQuery.of(context).size.height * 0.4, //I adjusted here for responsiveness problems on my device
width: MediaQuery.of(context).size.width * 0.5,
color: Colors.white,
child: LayoutBuilder(
builder: (context, constraint) {
return Stack(
children: [
Center(
child: Icon(
Icons.trip_origin,
size: constraint.biggest.width,
color: Colors.grey[300],
),
),
Positioned(
right: 0,
left: 0,
top: 20.0,
child: Icon(
Icons.sports_volleyball_rounded, //just to represent the ball
size: constraint.biggest.width * 0.5,
),
),
Positioned(
bottom: 0.0,
child: Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height * 0.1,
width: constraint.biggest.width,
color: Colors.yellow[700],
child: Text(
'Sports',
style: Theme.of(context)
.textTheme
.headline3
.copyWith(color: Colors.white),
),
),
),
],
);
},
),
),
);
I want to have more(in this example 4) items in Row. I tried use Expanded or Flexible or mainAxisAlignment: MainAxisAlignment.spaceEvenly to fill up all width of screen. But I want to heve items lets say specific width and height 50 pixels, and GestureDetector which is around item to be 1/4 of screen(4 items = full width). So everywhere I tap in the row something will be selected. My problem is that every my solution deforms items(circles) or circle must be very huge to width = height to not be deformed.
I also tried wrapping whole _ratingEmoji in Expanded and giving ratingItem.ratingIndicator constraints to max width but with same result.
Row of items:
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (var ratingItem in editGroceryRatingProvider.foodRatings)
_ratingEmoji(editGroceryRatingProvider, ratingItem, context),
],
),
Item:
Widget _ratingEmoji(EditGroceryRatingProvider editGroceryRatingProvider,
SelectedFoodRating ratingItem, BuildContext context) {
return GestureDetector(
child: ratingItem.selected
? Container(
width: MediaQuery.of(context).size.width / 8,
height: MediaQuery.of(context).size.width / 8,
padding: const EdgeInsets.all(2.0),
decoration: BoxDecoration(
border: Border.all(
color: Color(0xFF312ADB),
width: 3.0,
),
borderRadius: BorderRadius.circular(32.0)),
child: Center(
child: ratingItem.ratingIndicator,
),
)
: ratingItem.ratingIndicator,
onTap: () => editGroceryRatingProvider.updateSelectedRating(ratingItem),
);
}
RatingIndicator which is "circle" item to be on the screen:
Container(
decoration: BoxDecoration(
border: Border.all(
color: color,
width: 1.5,
),
borderRadius: BorderRadius.circular(64.0),
),
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 3.0,
),
borderRadius: BorderRadius.circular(64.0),
),
child: ClipOval(
child: Container(
width: width ?? MediaQuery.of(context).size.width / 7,
height: height ?? MediaQuery.of(context).size.width / 7,
color: color,
),
),
),
);
Thanks a lot.
Update:
Items should stay as they are on screenshot, but "whole" row should be clickable(means even if you click between 2 items, one closer to click should be selected)
Check, please solution.
The whole area is clickable. You just need to add your item instead of mine.
#override
Widget build(BuildContext context) {
final colors = [Colors.red, Colors.blue, Colors.brown, Colors.cyan];
return Scaffold(
body: Container(
alignment: Alignment.center,
color: const Color(0xffFAFAFA),
child: Row(
children: List.generate(
colors.length,
(index) => Expanded(
child: GestureDetector(
onTap: () => print('Tapped:$index'),
child: Container(
height: 50,
color: Colors.transparent,
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: colors[index],
),
),
)),
)),
),
),
);