Flutter: how to override the private state implementation of a Cupertino widget? - ios

I will first give a bit of background of my problem and then ask the actual question which I am trying to achieve:
BACKGROUND:
I posted this earlier question about preventing rows from disappearing as soon as they entered the padding area of the CupertinoScrollbar's parent Padding widget:
Flutter Padding on CupertinoScrollbar - how to prevent row from disappearing as soon as they enter the padding area?
I have figured out a workaround solution which involves removing the parent Padding widget entirely and instead wrapping the SliverList only in SliverPadding which achieves the padding on the list. However, this makes the scrollbar start at the top as it's the parent of the SliverPadding and thus doesn't know the padding for the inner SliverList.
I have figured out a solution for this problem. I can edit the source code of the CupertinoScrollbar and modify the following line in the updateScrollbarPainter method:
..padding = MediaQuery.of(context).padding
to what I need.
QUESTION:
This updateScrollbarPainter is part of the private state implementation _CupertinoScrollbarState, so I can't access it outside from my app.
Is there a workaround for this?
If not, is the only possible solution to modify the padding there is to copy the entire source code from this file into my app and then modify it there? It seems a bit complicated for modifying a single line of code no?
Here's the line I can modify:

You can try wrapping widget with MediaQuery and provide the padding while it depends on context.
body: MediaQuery(
data: MediaQuery.of(context).copyWith(
padding: EdgeInsets.all(52), //here modify the one you want
),
child: Scrollbar(

Related

Unable to set GridLayout height programatically

I am trying to implement swipe actions on ListView for each element. Whole view is AbsoluteLayout, with two GridLayouts: one acting as "foreground"(list element) and other as "background" (swipe actions). I want them both to have equal height of "foreground" (which is dynamic and differs for every list element).
I succesfully implemented this on Android - I call a method on layoutChanged event
onLayoutChanged(args: EventData) {
const foregroundNotificationTemplate = (<AbsoluteLayout>(args.object)).getChildAt(1);
const backgroundButtons = (<AbsoluteLayout>args.object).getChildAt(0);
backgroundButtons.height = foregroundNotificationTemplate.getActualSize().height;
}
This unfortunatelly is not working on iOS. I tried to access Frame and UiView, but with no success - it has height of background content.
Demo presenting the problem on Nativescript Playground:
https://play.nativescript.org/?template=play-ng&id=4LRwDC
You don't necessarily have to use AbsoluteLayout as you are animating the position with translate which is possible with any layout. So using GridLayout instead of AbsoluteLayout should solve your problem on both platforms and you may also get rid layoutChanged event for measuring height.
Also note that your ListView item template can not be dynamic, you should not use ngIf or anything that would alter the structure of the list item, use multiple templates instead.
For anyone looking for working solution, thats what Manoj proposed: https://play.nativescript.org/?template=play-ng&id=yXggcv

ListView loses scroll position when using InheritedWidget in Flutter

After adding InheritedWidget to app I recognize that ListView loses scroll position (selected item index) when I come back to list from details screen using Pop().
I know that widget can be rebuild any time but maybe someone can suggest solution without handling cache manually.
P.S.
Scroll position was fine before implementing InheritedWidget
no any code so a shot in the dark
try to add 'key'
like this
ListView(
key: const PageStorageKey<String>('some unique text'),
//other parameters
);

Flutter UI - How can I add more IconButtons to the trailing CupertinoSliverNavigationBar?

Tried to research around but couldn't find a solution. I would like to use the CupertinoSliverNavigationBar which is the large title version of the top navigation bar I could achieve this in Xcode Storyboard but simply adding buttons to the top bar but the trailing option only allows a single widget.
I tried using a Row() but that messes up the location and the title aloooot.
Composing your comment coversation into an answer:
CupertinoSliverNavigationBar(
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: ...
))
You also asked how one would go about removing the shadow below the navigation bar. That is impossible with the CupertinoSliverNavitionBar Widget. Taking a look at the constructor, you will notice that there is nothing like an elevation value. You would have to create a custom widget for this.
This also makes sense because it should look like "iOS-11-style" and removing the shadow would remove that feature.

Update Scaffold contents (appBar title and body) without pushing a new view?

Say I have a main, top-level Scaffold with an appBar and and body.
I have a button in the appBar and in its onTap I do:
Navigator.push(
context,
new MaterialPageRoute(builder: (_) => new DogeWidget())
);
Now DogeWidget is also aScaffold, because I like the appBar's default rendering.
What's happening:
I see the DogeWidget slide from the bottom of the screen. It's a whole scaffold sliding, not just the body.
What I'd like to see:
The main appBar's contents change, its hamburger changes into a "back arrow". There is no slide from the bottom, just an ordinary fade.
I don't know if I should write this myself or is there something that Flutter can provide?
AFAICT, the Gallery does what I want (e.g. tap on the "typography" item) - behavior is different despite my code being an almost literate copy and paste. Why?
For a while we had a hack that made this happen by making the AppBar a Hero, but it was not a good implementation and caused more trouble than it was worth so we backed it out. That's probably what you're seeing.
There's no easy way to do this using Navigator with today's material framework, though you can certainly implement widgets on top of the widgets layer that do it if you want to. What you might be able to do though is implement it by having a Navigator inside the body of your MaterialApp, and then manually replacing the AppBar (maybe via a crossfade widget like AnimatedCrossFade).
Solving this properly is something we intend to do in due course but we are prioritising bugs and API stability at the moment so it is not something we plan to do in the near term (next few months).

Forcing Vaadin Component to occupy it's space in invisible state

I have a Label and a Progess Indicator in my Vaadin indicator. It is dynamically made visible in the UI. There is a Tree below this Progress Indicator.
When the program dynamically sets the visibility of the Progress Indicator to true, the tree shifts down and the UI shakes due to the shifting.
Is there any way to make a Vaadin component occupy it's space, even if it is invisible and hence, when made visible it must not try to borrow space from other UI components?
What I am looking for is a feature similar to setRendered(true) in flex and actionscript programming.
Thanks for your help.
Finally I got an answer to my question. I just replaced the invisible components with a dummy visible label with no text.
And used it alternatively to switch between visible and invisible.
I asked the question in the Vaadin forum, and here's the response I got, from Kim Leppanen:
With Vaadin 7, if you set a component's visibility to false, then the component's information is not sent to the browser at all - it is just as if the component wouldn't exist in the layout at all.
I can quickly come up with two solutions. If you know the size of the component whose visibility you want to toggle, then you can use placeholder components - such as a Label. Put a label with the correct size in the place where you want the component. When you want to set a component as visible, then replace the label with the actual component.
The second option is to use css. Apply the css attribute "visibility: hidden" for the component you want to hide. Note that the component is not "truly" hidden. Let's say that it is a button. A user could still inspect the DOM tree and see the button in the code, change the visibility of the component on the client side (eg using developer tools or firebug) and then see and use the button as if it would be visible in the layout.
I am putting it here because people might add some more useful answers there. For a detailed explanation please see this.
Use this following example to the component you want set invisible but keeping its occupied space:
Image home = new Image();
home.setSource(HOME);
home.addStyleName("visibility: hidden");
OR
home.addStyleName("visibility: collapse");

Resources