Flutter Markdown "Show more" button - flutter

I use MarkdownBody from flutter_markdown inside a LimitedBox. When pressing a "Show more" button the maxHeight is set to double.infinity and the full text is shown:
LimitedBox(
maxHeight:
showMoreCommentsIds
.contains(
commentId)
? double.infinity
: 100,
child: Wrap(
direction:
Axis.horizontal,
children: <Widget>[
MarkdownBody(
data: showList[index]
.comment
.comment,
)
],
),
),
But how can I find out the height of the text and only display the "Show more" button, if it is necessary?

You can find the length of the text using text.length and based on that information determine if the "Show more" button is needed. For example:
if(text.length > 60) {
_showButton();
}
You may need to do a little testing with the length of text in order to find out which length you want as the threshold. I just chose 60 as an arbitrary number.

I struggled a little bit with a similar problem because I had to know the size of a widget to apply some logic.
I learned that you can prerender the widget in an Offstage widget, determine it's size with the widget key once it is mounted.
You should wait for the rebuild, so you can force it and then you get the size with a function like this:
Future.delayed(Duration(milliseconds:100)).then(
final widgetSize = getWidgetSize(widgetKey);
// You can make logic here to remove the Offstage, variables, and free its space.
// Todo: apply the size in your code after this
)
...
Size getWidgetSize(GlobalKey key) {
final RenderBox renderBox = key.currentContext.findRenderObject();
return renderBox.size;
}
In my case, I needed it after tapping somewhere, so I used it inside a function, but maybe you will apply it directly on the initState(), inside a post frame callback.
initState(){
super.initState();
ServicesBinding.instance.addPostFrameCallback((_) async {
// here
});
}

Related

How to get size of a child Widget

I have a special requirement to allow for a header widget, usually containing static content to appear at the top of a scroll view. The scroll view should overlap the header widget so that a clip shape can be used for effect. I've achieved this effect by using a stack view with the header widget as the first item in the stack, the scroll view as the top element. The scroll view contains a column with the first child being an empty container of the desired height (the height of the header widget minus the amount of overlap). This achieves the desired effect when passing in a known height as a hard-coded parameter. (NOTE: I tried to accomplish this using a Sliver List, but wasn't able to achieve the desired overlap to meet product requirements.)
The header widget contains an image which is loaded via an API response. The height of the images can vary so I need to determine this at runtime and adjust the UI accordingly. I didn't think this would be a difficult task but so far, I've not found a way to do this. The following two images show the desired effect, the image on the right shows the correct behavior on scrolling up. Note that the scroll view must overlap the header image by the same amount as the radius of the clip.
This generates the list. _getComponents provides child widgets for a column contained in the SingleChildScrollView:
List<Widget> _getComponents(List<Section> sections, BuildContext context, double? height) {
List<Widget> widgetList = [
Container(height: 225) // need to obtain correct height here
];
for (int i = 1; i < sections.length; i++) {
Section section = sections[i];
if (section.model != null) {
switch (section.code) {
case mediaTypeCode:
if (section.model.runtimeType == MediaModel) {
widgetList.add(HeaderComponent(section: section));
}
break;
case articleTypeCode:
if (section.model.runtimeType == ArticleSectionModel) {
widgetList.add(TitleContentHeader(
model: section.model as ArticleSectionModel));
}
break;
}
}
}
return widgetList;
}
Then in my view widget, the stack is built as follows:
return Container(
color: Colors.white,
child: Stack(
children: [
_getHeader(sections),
SingleChildScrollView(
child: Column(
children: _getComponents(sections!, context, null),
),
),
],
),
);
I need to be able to get the height of the header returned in _getHeader(sections) and pass it to the _getComponents function so that I can determine the correct starting position for the scroll view.
Can anyone offer any insight into this?
Or, can you suggest a plugin that would allow the behavior show in the images above? As mentioned above, Sliver List did not produce the desired effect.
Thanks!
You can get size of a widget using RenderBox :
import 'package:flutter/material.dart';
class WidgetPosition {
getSizes(GlobalKey key) {
final RenderBox renderBoxRed = key.currentContext.findRenderObject();
final sizeRed = renderBoxRed.size;
// print("SIZE: $sizeRed");
return [sizeRed.width, sizeRed.height];
}
getPositions(GlobalKey key) {
final RenderBox renderBoxRed = key.currentContext.findRenderObject();
final positionRed = renderBoxRed.localToGlobal(Offset.zero);
// print("POSITION: $positionRed ");
return [positionRed.dx, positionRed.dy];
}
}

Flutter Bottom Container Swipe Up

I'm making an app which shows place detail when clicking a place on Google Maps. I can open a container at bottom of the page but I want to do that when the user swipe this container to up with animation, the container will cover the whole page and I will get extra information about that place and show the user.
How can I do that with Flutter?
You can try to use the package here:
https://pub.dev/packages/sliding_up_panel
However, if this does not fullfill you wish, try this instead: Wrap you Widget with a GestureDetector and an AnimatedController:
double containerHeight = 0;
GestureDetector(
onVerticalDragEnd: (dragUpdateDetails) {
setState(){
containerHeight = //device height or use MediaQuery.of(context).size.height//
}
},
child: AnimatedContainer(
duration: Duration(milliseconds: //how long should it take//),
height: containerHeight,
child: //whatever you want//
)
),
AnimatedController automatically animates between changes of properties. However, you might want to try changing onVertivalDragEnd to something else like onVerticalDragUpdate to fullfill your wish completely. If you want to have that behaviour for the full screen, wrap your first return Widget with the GestureDetector.
I guess DragableScrollableSheet fits your need. There is a good explanation here in the documentation.
You can use DraggableScrollableSheet
Document and Video tutorial available here:
https://api.flutter.dev/flutter/widgets/DraggableScrollableSheet-class.html

Flutter: How to make such Edit text and remove the unexpected layout padding

I'm trying to implement this design:
i'm very beginner to flutter, and what i'm getting is this:
I don't want you guys to get me wrong, i'm not asking for someone to implement this for me.
i need guidance on how to:
remove the layout padding.
make a textview and edit text side by side look like one widget.
remove the space between the edit texts.
implement the CheckBox (i tried a row with check box and text, didn't work)
show a proper arrow in "Sign In" (instead of ->).
just some explanations, guidance and any documentation or tutorial that could be good for my case.
Here is my code
remove the layout padding.
make a textview and edit text side by side look like one widget.
Im not sure of this if your talking about inside TextFormField you can use contentPadding inside InputDecoration. But based on your layout design, you can separate the Label in TextFormField and create your own label text
Row(
children:[
Text("LABEL"),
Expanded(
child: TextFormField(),
)
]
)
4.implement the CheckBox (i tried a row with check box and text, didn't work)
Row(
children: [
Checkbox(
value: isValue,
onChanged: (bool value) {
setState(() {
isValue = value;
});
}),
Text("SOME TEXT"), //Read RichText widget for your design
],
),
For you arrow -> sign in
Try using Icon() widget

Flutter: How to make a ListView transparent to pointer events (but not its non-transparent contents)?

I have a Scrollable (ListView or any other) and it contains a transparent widget, say Container(height:200). I can see through both the widget and the scrollable (in other words I can see the widgets behind the scrollable).
How can I be able to click through the transparent widget and the scrollable, so that I reach the widgets behind the scrollable?
ListView(
children: [
Container(height: 200), // Transparent.
Container(color: Colors.red, height: 200),
],
);
Note, I cannot wrap the scrollable with IgnorePointer, because I still want to click the non-transparent widgets in the scrollable.
The only reasonable solution I can think of is to have a GestureDetector on the transparent container, which will give you the global position of the taps:
GestureDetector(
onTapUp: (TapUpDetails tapUpDetails) {
print("onTapUp global: " + tapUpDetails.globalPosition.toString());
},
And then add a Key to the widget behind the list, and use it to get the global position of the top left corner of the widget's rectangle, as well as the size of the widget, and use those to get the rectangle of the widget:
RenderBox renderBox = _key.currentContext.findRenderObject();
Offset topLeftCorner = renderBox.localToGlobal(Offset.zero);
Size size = renderBox.size;
Rect rectangle = topLeftCorner & size;
If the background widget does not move, you can do it within initState on the very next frame using WidgetsBinding.instance.addPostFrameCallback (the render object will be null if do it synchronously within initState) and save the Rect - otherwise you will have to recalculate it on every tap.
And then finally on each tap on the transparent container you can calculate whether the tap's position is within the boundaries of the background widget, and invoke the corresponding code:
// if tap is within boundaries of the background widget
if (rectangle.contains(tapUpDetails.globalPosition)) {
// your code here
}

Flutter - only show image if enough space available

I have an Expanded Widget with an Image.asset(...) as it's child.
On small phones there is not enough space and the image is scaled down massively. Since it is only for eye-candy anyways, I'd like to hide / not show the Image if there isn't at least a height >= 100.0 available.
How do I accomplish this in Flutter? Is there a way to get the parent widgets size?
You can use LayoutBuilder to obtain the input constraints of a widget.
Then based on these constraints decide to display or not an image
LayoutBuilder(
builder: (context, constraint) {
if (constraint.maxHeight < 100.0) {
// too small
return Container();
} else {
// ok
return Column(
children: <Widget>[
Image.asset("foo"),
Container()
],
);
}
},
)
Awesome Remi's solution, and You can use the MediaQuery and MediaQueryData too, has some properties and methods that can help your in situations like that.
Some properties are orientation, size, padding, devicePixelRatio, etc.
Example:
MediaQuery.of(context).orientation
https://docs.flutter.io/flutter/widgets/MediaQuery-class.html
https://docs.flutter.io/flutter/widgets/MediaQueryData-class.html