I'm trying to have a responsive drawer that when the screen size is higher than X itemExtent is set to default, how could I add a if statement inside a ListView?
Widget drawer(context){
double _containerHeight = MediaQuery. of(context). size. height;
int _numberOfListTiles = 16;
return new Drawer(
child: Container(
height: _containerHeight,
color: const Color(0xff68778d),
child: ListView(
padding: EdgeInsets.zero,
itemExtent: _containerHeight/_numberOfListTiles,
children: [
],
),
)
);
}
I would like to do:
if(_containerHeight < 700){
itemExtent: _containerHeight/_numberOfListTiles,
}
The cleanest way (in my opinion) would be to instantiate your variable at the top of your drawer method as you did for the _containerHieght and _numberOfListTiles variables.
Your code would then look like that
Widget drawer(context) {
final double _containerHeight = MediaQuery.of(context).size.height;
final int _numberOfListTiles = 16;
double itemExtent;
if(_containerHeight < 700){
itemExtent = _containerHeight/_numberOfListTiles;
} else {
itemExtent = 100; // Default ?
}
return new Drawer(
child: Container(
height: _containerHeight,
color: const Color(0xff68778d),
child: ListView(
padding: EdgeInsets.zero,
itemExtent: _containerHeight / _numberOfListTiles,
children: [],
),
));
}
Related
I'm working on the application and I need to build this widget which you can then click on the plus icon join to the team the problem is I can't do it like picture exactly
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(30),
child: Stack(
children: List.generate(
listOfEvents[i].attendeesList.length, (index) {
return Positioned(
left: index * 30,
child: const CircleAvatar(
backgroundImage: NetworkImage("https://avatars.githubusercontent.com/u/61495501?v=4"),
radius: 30,
)
);
}
)
)
);
}
you have to use the package called "dotted_border" and follow the given code
DottedBorder( child: // put your image here //borderType: BorderType.Circle,dashPattern: [10,5,10,5,10,5]),
Here i have a simple class that i show images from network with Image.network. as i used this class into a Listview, during scrolling that cause of a bit lag and i think i can fix it with Isolate.
after reading some documentation about this feature in Dart i'm not sure how can i put this this class or part of that such as a simple widget into that.
class InistaLikers extends HookWidget {
final List<String> imageUrls;
const InistaLikers({required this.imageUrls});
#override
Widget build(BuildContext context) {
late double _width = 0;
late int count = 4;
final _orientation = MediaQuery.of(context).orientation;
final _screenWidth = MediaQuery.of(context).size.width;
useEffect((){
if(_orientation == Orientation.portrait){
_width = _screenWidth* 0.39;
count = 4;
}else if(_orientation == Orientation.landscape){
_width = (_screenWidth / 2) * 0.39;
count = 3;
}
});
return Container(
width: _width,
height: 35.0,
child: Row(
children: [
Expanded(
child: Stack(
children: List.generate(
count,
(i) {
return Positioned(
right: imageUrls.length + (20.0 * i),
child: ClipOval(
child: Container(
width: 35,
height: 35,
child: Image.network(
imageUrls[i],
),
),
),
);
},
).toList(),
),
),
ClipOval(
child: Container(
width: 35,
height: 35,
child: Image.network(
imageUrls.last,
),
),
),
],
),
);
}
}
You cannot build a widget through an isolate as dart:ui which is used to render your widgets is only available on the main isolate. Moreover, Image.network already uses an ImageStream to manage the recuperation of an online image.
If you have some performance issues you should try to optimize the way you are building your widgets, for example if it was not the case already you should use ListView.builder if you have a lot of widgets to render.
You can find some "Performance best practices" documentation on the flutter website or the article Flutter Performance Tips written by Hasan Basri Bayat.
Here's some of the tips described in this article which you can apply to improve the performances of your app:
Use Widgets Over Functions
// Don't do this
[
_buildHeaderWidget(),
_buildMainWidget(context),
_buildFooterWidget(),
]
// Do this
[
HeaderWidget(),
MainWidget(),
FooterWidget(),
]
Use const where possible
const _myFixedHeight = 48.0;
Use const constructors whenever possible
class CustomWidget extends StatelessWidget {
const CustomWidget();
#override
Widget build(BuildContext context) {
// ...
}
}
Use nil instead of Container()
// Don't do this
Column(
children: [
text != null ? Text(text) : Container(),
],
)
// Do this
Column(
children: [
if (text != null)
Text(text),
],
)
And you'll find some more tips in the article.
I'm trying to stack some playing cards like the image shows. BUT I want the cards to wrap into a new line when there is no more space on the device.
This is what I have so far
class CollectionOfCards extends StatelessWidget {
List<PlayingCard> cards;
CollectionOfCards(this.cards);
#override
Widget build(BuildContext context) {
return Stack(
children: [
...cards
.asMap()
.map(
(key, value) => MapEntry(
key,
Positioned(
child: PlayingCardWidget(value),
left: 35.0 * key,
),
),
)
.values
.toList(),
],
overflow: Overflow.visible,
);
}
}
Any ideas how to do this? I imagine it is somewhat a common task.
Another idea would be to make a fan of cards that can always fit but I imagine thats harder to achieve!
Assume we want to have 2 rows of cards, each containing 10 cards. We need to use Positioned in a way that every card is positioned according to its index in the row(from 0 to 9) and its column(column 0 or column 1). So we need to set top and left in the Positioned widget. The 0.7 * cardHeight in top is for the vertical stacking, you can change that to cardHeight if you don't want to have vertical stacking.
Note: Set width and height of the cards using MediaQuery size. I didn't have the cards so I just made empty containers instead.
class _MyHomePageState extends State<MyHomePage> {
List<Widget> _cards = [];
void _initCards() {
double cardHeight = 400 / 2;
double cardWidth = 2500 / 20;
for (int i = 0; i < 20; i++) {
_cards.add(Positioned(
left: ((i >= 10) ? i - 10 : i) * cardWidth / 2,
top: (i >= 10) ? 0.7 * cardHeight : 0,
child: Card(
elevation: 10,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
child: Container(width: cardWidth, height: cardHeight),
),
));
}
}
#override
void initState() {
super.initState();
_initCards();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.symmetric(horizontal: 15.0),
child: Stack(
children: _cards
),
decoration: BoxDecoration(
color: Colors.yellow,
),
),
);
}
}
Result:
Just for reference. I ended up with solution like this inspired by #Mobina's answer
class CollectionOfCards extends StatelessWidget {
final List<PlayingCard> cards;
final double stackSkew = 0.4;
CollectionOfCards(this.cards);
#override
Widget build(BuildContext context) {
final double widgetWidth = MediaQuery.of(context).size.width - 16;
final double cardWith = PlayingCardWidget.defaultWidth(context);
final int cardsPerRow =
(widgetWidth / cardWith / stackSkew - 1 / stackSkew).floor();
return Stack(
children: [
...cards
.asMap()
.map(
(index, card) {
return MapEntry(
index,
Positioned(
child: Draggable(
childWhenDragging: Container(),
feedback: PlayingCardWidget(card: card),
child: PlayingCardWidget(
card: card,
),
),
left: stackSkew *
cardWith *
(index - (cardsPerRow) * (index / cardsPerRow).floor()),
top: (card.heightFromWidth(cardWith) + 2) *
(index / cardsPerRow).floor(),
),
);
},
)
.values
.toList(),
],
overflow: Overflow.visible,
);
}
}
It seems to work flawless.
One way you can do this is by passing left as well as top parameter to Positioned calculated based on -
Screen width
Card index ("key" in your code)
Card width
Card height
See the demo on dartpad - https://dartpad.dev/d36e018c1f1c7a6cd4b91d5b09e69a7c
Try using Wrap() widget inside a Column()
Column(
children: <Widget>[
Wrap(
children: <Widget>[
//your card widget
]
)
]
)
I am using the Cupertino design library for Android developing in Flutter. I want to change the width of the CupertinoSlidingSegmentedControl. This is what I have
final Map<int, Widget> myTabs = const <int, Widget>{
0: Text("Doctor"),
1: Text("Pacient")
};
CupertinoSlidingSegmentedControl(
groupValue: segmentedControlGroupValue,
children: myTabs,
onValueChanged: (i){
setState(() {
segmentedControlGroupValue = i;
});
},
),
Wrap it in SizedBox:
SizedBox(
width: double.infinity,
child: CupertinoSlidingSegmentedControl(...),
)
I achieved it by wrapping every Text widget with a Container of width double.maxFinite:
final Map<int, Widget> myTabs = const <int, Widget>{
0: Container(width: double.maxFinite, child: Text("Doctor"),),
1: Container(width: double.maxFinite, child: Text("Pacient"),),
};
Extra tip: if you want to change the height of CupertinoSlidingSegmentedControl's children (option buttons), you can set the height of the Container, or you can use padding property, like this:
Container(
padding: EdgeInsets.symmetric(vertical: 10.0),
width: double.maxFinite,
child: Text("Doctor"),
);
Is there a way to align Wrap widget items in all lines except the last with spaceAround and the last one with start? Is there another way to do it? Number of rows and columns should not be fixed - it depends on device width and height.
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SingleChildScrollView(
child: new Wrap(
direction: Axis.horizontal,
spacing: 10.0,
alignment: WrapAlignment.spaceAround,
children: <Widget>[
//items
],
),
);
});
See screenshot how it actually looks like. I need the last row to have the same spacing as the others and start from the left.
AFAIK there's no way to achieve this with Wrap widget, but similar effect produce GridView with extent constructor:
GridView.extent(
children: List.generate(10, (index) {
return Center(
child: Icon(
Icons.star_border,
size: 100.0,
),
);
}),
maxCrossAxisExtent: 150.0,
)
If the size of the item is known, it can be achieved in this way:
const itemCount = 10;
const itemSize = 100.0;
LayoutBuilder(
builder: (context, c) {
const spacing = 0.0;
final columnCount =
((c.maxWidth + spacing) / (itemSize + spacing)).floor();
final rowCount = (itemCount / columnCount).ceil();
final maxLength = columnCount * rowCount;
return Wrap(
spacing: spacing,
children: List.generate(
math.max(itemCount, maxLength),
(index) => index < itemCount
? _buildItem(context, index)
: const SizedBox(width: itemSize, height: itemSize),
),
);
},
);