I'm creating a simple card that contains a long description.
I want to set the normal height of the card to 50px and when the user clicks on it I want to expand the card to be able to fit all the content inside.
So far, to obtain my needs I wrote this:
String aLotOfText = "When Gradle resolves the compile classpath, it first resolves the runtime classpath and uses the result to determine what versions of dependencies should be added to the compile classpath. In other words, the runtime classpath determines the required version numbers for identical dependencies on downstream classpaths. Your app's runtime classpath also determines the version numbers that Gradle requires for matching dependencies in the runtime classpath for the app's test APK. The hierarchy of classpaths is described in figure 1.";
bool cardExpanded = false;
InkWell(
onTap: () {
expandCard();
},
child: AnimatedContainer(
height: cardExpanded ? null : 50,
duration: Duration(milliseconds: 200),
child: Card(
child: Text(aLotOfText),
),
)
)
expandCard() {
setState(() {
cardExpanded = !cardExpanded;
});
}
As you can see on the line height: cardExpanded ? null : 50, when cardExpanded is true I didn't specify the height, so in this way I'm able to expand the card to the right height to contain the text.
But with this little hack I've completely lost the animation and as long as this card would go in a listview with 20 or more other cards, the opening and closing makes the list to jump up and down.
I'm sure that there is a way to expand the card to the right height keeping also the animation.
I would also like to specify that the one above is just an example, in my card, there will be images and buttons as well.
In addition, when the card is opened with a button, I could add some text, so the card has to expand as well when it is opened.
That's why I cannot specify a height.
EDIT
With height: cardExpanded ? null : 50 I get what I want, so, the card grows big enough to fit the content, but as you can see there is no animation there
Instead if I provide a value like height: cardExpanded ? 100 : 50, I get the animation, but obviously the card grows until it gets to 100 pixels and it dosen't show all the content.
The result that I would like to obtain is what there is in the first example plus the animation.
Thankyou
You could set two variables:
height = MediaQuery.of(context).size.height * 0.8; //the percentage you want the card to grow
width = MediaQuery.of(context).size.width * 0.8;
So when expanded is true, the container grows.
height: cardExpanded ? height : 50,
width: cardExpanded ? width : 50,
Also, to specify how the animation will perform, you have a property that can make the animation look smoother.
curve: Curves.bounceInOut,
or you could try using a widget like expanded to adjust.
Related
Currently I am calling an API to populate data in the bar chart made using echarts, I used the following code.
var mychart = echarts.init(document.getElementById("test"));
mychart.showLoading();
Once the data comes then I hide the loading, but in echarts I am getting only the circular shape loading option, can I use vertical bars for showing loading animation in echarts.
Echarts has no another loading spinner but you can make own or take any spinner lib (for example) and place above. Of course you can use the custom series or graphic and draw something but is not quite right spent time because it's loader and its role just to show that chart is not dead and will continue action soon to prevent user leaving.
Try the DOC
https://echarts.apache.org/en/api.html#echartsInstance.showLoading
default: {
text: 'loading',color: '#c23531',
textColor: '#000',
maskColor: 'rgba(255, 255, 255, 0.8)',
zlevel: 0,
// Font size. Available since `v4.8.0`.
fontSize: 12,
// Show an animated "spinner" or not. Available since v4.8.0`.
showSpinner: true,
// Radius of the "spinner". Available since `v4.8.0`.
spinnerRadius: 10,
// Line width of the "spinner". Available since `v4.8.0`.
lineWidth: 5
}
The design of an application I developed with Flutter is broken on devices with different screen sizes (tablet vs. phone). Cards and containers overlap and vary in size. What is your suggestion?
I really suggest you to give a look at the LayoutBuilder class that's been created exactly to solve your problem. Give a look at the doc for every info; here's a simple usage:
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < YOUR_SIZE)
return Column();
else
return GridView();
},
),
Very intuitively: if the width of the device is lower than YOUR_SIZE, the screen is not so "wide" and a column fits well. Otherwise you could place your widgets in a grid with N columns probably.
Official video about LayoutBuilder on YouTube.
Use widgets composition instead of functions that return Widget. Functions are NOT optimized, you can't const-construct the widget and they get rebuilt every time!
To make the size of any widget proportional with any device, you need to get the device width and height before setting widget size.
For instance, to create a container of size that is responsive to any device height and width and also scale when rotated, you need to use the MediaQuery to get the device height and width to scale you widget size as follows:
....
#override
Widget build(BuildContext context){
double _height = MediaQuery.of(context).size.height;
double _width = MediaQuery.of(context).size.width;
return Container(
height: _width > _height ? _width / 10 : _height / 10,
width: _width > _height? ? _height / 10 : _widht / 10,
child: AnyWidget(),
);
}
...
I have been wondering why one should use [Expanded] / [Flexible] flex over [Align] alignment? You can precisely align your widget with [Align] and even potentially avoid [Padding].
Let's see it from another view, is using the flex of [Expanded] / [Flexible] more efficient and faster than [Align]?
There is no comparison between Expanded/Flex and Align. Take a look at the following snippet.
Column(
children: [
Container(color: Colors.blue, height: 200),
Align(child: Container(color: Colors.green)), // doesn't show anything
Expanded(child: Container(color: Colors.orange)), // shows up in the remaining space
],
);
Having Align as the parent of Container won't show anything on screen but if you use Expanded/Flex it will take up the left space.
Not sure what you a referring to. Expanded is for (more or less) "selecting" which widget inside a Row/Column should fill the remaining space. While Align just positions the child inside itself at the given alignment.
I am developing an application on react-native. I have made a UI which works fine on iPhone 6 but not working fine on iPhone 5 or lower versions.
How should I fix this ?
You need to think about proportion when building your UI.
1, Use percentage(%) for width and aspectRatio for height, or vice versa.
container: {
width: "100%",
aspectRatio: 10 / 3, //height will be "30%" of your width
}
2, Use flex for the jobs percentage can't do. For example, if you have arbitrary size of items in a list and you want them to share equal sizes. Assign each of them with flex: 1
3, Use rem from EStyleSheet instead of pixels. rem is a scale fator. For example, if your rem is 2 and your “11rem” will become “11*2” = “22”. If we make rem proportion to the screen sizes, your UI will scale with any screen sizes.
//we define rem equals to the entireScreenWidth / 380
const entireScreenWidth = Dimensions.get('window').width;
EStyleSheet.build({$rem: entireScreenWidth / 380});
//how to use rem
container: {
width: "100%",
aspectRatio: 10 / 3, //height will be "30%"
padding: "8rem", //it'll scale depend on the screen sizes.
}
4, Use scrollView for contents that could potentially scale out of the boxes. For example, a TextView
5, Every time you think about using pixels, consider use rem in method 3.
For a detailed explanation, you can read the article here. 7 Tips to Develop React Native UIs For All Screen Sizes
Have you designed the app using fixed widths and heights? You should definitely use the capabilities of flexbox and try to avoid settings fixed sizes as much as possible. The flex property can be used to define how much space a <View /> should use releative to others, and the other properties on that page can be used to lay out elements in a flexible way that should give the desired results on a range of different screen sizes.
Sometimes, you may also need a <ScrollView />.
When you do need fixed sizes, you could use Dimensions.get('window').
You need to calculate sizes dynamically, relying on screen size.
import { Dimensions, StyleSheet } from 'react-native'
[...]
const { width, height } = Dimensions.get('window')
[...]
const styles = StyleSheet.create({
container: {
flex: 1.
flexDirection: 'column',
},
myView: {
width: width * 0.8, // 80% of screen's width
height: height * 0.2 // 20% of screen's height
}
})
If you are using TabbarIOS, remember that Dimensions.get('window') gives you the whole screen's height, this means that you'll have to take in account that the tabbar has fixed-height of 56.
So for example, when using TabbarIOS:
const WIDTH = Dimensions.get('window').width,
HEIGHT = Dimensions.get('window').height - 56
Then use WIDTH and HEIGHT as above.
I have a Xamarin forms page that contains an absolute layout that wraps everything. Inside that, I have content that fills the whole space and has left padding of 80, and then I have a left nav sidebar that is 80 wide and sits on top of the main content:
I want a sort of modified "push" animation, which means doing two things:
Increase the width of left nav by 100 (to 180)
TranslateX the main content by 100
(Note that using TranslateTo() would be super easy, but the left nav needs to increase in width, not shift to the right, and there's no WidthTo() method).
I can do #1 by itself just fine.
I can do #2 by itself just fine.
But I can't get them to both animate. If I run the left nav animation first (via .Commit()), only the main content animates. If I run the main content animation first, neither animates. Strange! What is going on here?
Here's the basic code I'm using:
var leftNavAnimation = new Animation(
callback: x => leftNav.WidthRequest = x,
start: 80,
end: 180,
easing: Easing.Linear
);
var mainContentAnimation = new Animation(
callback: x => mainContent.TranslationX = x,
start: 0,
end: 100,
easing: Easing.Linear
);
leftNavAnimation.Commit(this, "leftNavAnimationName", length: animationLength);
pageContentAnimation.Commit(this, "mainContentAnimationName", length: animationLength);
I figured out that the first parameter of .Commit() needs to refer to the element you're animating. So changing from:
mainContentAnimation.Commit(this, "mainContentAnimationName", length: animationLength);
To:
mainContentAnimation.Commit(mainContent, "mainContentAnimationName", length: animationLength);
Fixed it.