-
Notifications
You must be signed in to change notification settings - Fork 28.4k
Design a dynamic platform theming mechanism between Material and Cupertino #8410
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
One concrete example for a semi-complex case where we probably want the experience to be magical-ish without too much user selection is with page routes. Currently the dependency is:
So the graph is We'd need to clear up the dependency graph a bit. Starting from the graph down, we probably want: So one unpolished idea might be to do something like:
which implies a user API change from pushing MaterialPageRoute to PlatformPageRoute. or we can do something like:
which implies we're saying the users don't have to manually think about page transitions and the Material spec is automatically platform dynamic. We'd also have to do the dependency injection of widget.PageTransition -> platform_widget.PlatformPageTransition in the MaterialApp. |
https://material.io/guidelines/patterns/navigational-transitions.html Which makes me lean more towards option 1 where the user specifies that he wants a platform dynamic page route (and perhaps will be overriden with a hero navigation observer most of the time). cc @HansMuller |
Material Design has a notion of adapting to the target platform. That means it's conceptually fine for material.dart to take a dependency on cupertino.dart and for MaterialPageRoute to know about both _MountainViewPageTransition and _CupertinoPageTransition. Another way to approach this thought experiment is to build a pure CupertinoPageRoute and then see what parts of its machinery MaterialPageRoute wants to use in order to adapt to iOS. |
Developers may want to control the mapping from generic components to potentially platform-specific ones. In other words rather than providing generic components that just map from the platform to some platform-specific component (or transition or whatever), developers might prefer for control to flow through a look-and-feel theme that they can customize. Maybe I'd like generic buttons to map to MyButton and route transition durations to be 500ms. If the l&f theme was an inherited widget I could configure for the app or a subtree. |
@HansMuller that's always going to be true in any of the options. Users can always pick a specific route or transition. If there were dynamic wrappers, they're just a thin convenience layer. |
Chatted offline. So conceptually, instead of making Cupertino and Material siblings with each meaning a full spec'ed design opinion and components for iOS and Android and having a common parent, we'll extract MountainView out of Material and make MountainView and Cupertino siblings. Those will be the basic OS components that have less value add if the developers remade them. Material will be the opinionated design usage of MountainView and Cupertino base components. And the user that wants to create non-Material apps can reuse MountainView and not have to recreate non-value-add basic components. (cc @sethladd https://docs.google.com/presentation/d/1cw7A4HbvM_Abv320rVgPVGiUP2msVs7tfGbkgdrTy0I/edit?ts=58d9dd75#slide=id.gbb3c3233b_0_162) |
Is there any documentation about rendering the correct widgets for each platform? I thought there was but I'm not sure anymore. |
Is this behaviour set in the |
We're discussing about a solution for this now. For those that are interested on the thread, can you guys provide some specific examples (even better with usage code) of what behaviors you'd like to see from Flutter? Especially if you would like additional functionalities than Flutter providing a widget that simply does: class PlatformBuilder extends StatelessWidget {
const PlatformBuilder({
this.materialWidgetBuilder,
this.cupertinoWidgetBuilder,
});
final WidgetBuilder materialWidgetBuilder;
final WidgetBuilder cupertinoWidgetBuilder;
@override
Widget build(BuildContext context) {
switch (Theme.of(context).platform) {
case TargetPlatform.android:
return materialWidgetBuilder(context);
case TargetPlatform.iOS:
return cupertinoWidgetBuilder(context);
}
}
} |
Either that or providing people a way to think about cross platform well. Right now, I feel like I would either write many Builders similar to what you wrote or leave switch statements scattered across the code. |
I recently struggled with this, and kinda ditched it because it got a little too tedious for me. All I really want is a way to get Platform Specific AppBar's (ios Navbars), BottonNavigtionBar (ios TabBar), spinners, and dialogs without extra effort. Those are the main pieces that really stand out to me that I feel like MUST be in the native design language. |
👏 |
cc @willlarche - you may be interested in seeing above what some of our developers are saying they would like from Flutter in terms of automatic cross-platformness (beyond what Material is defined as doing today). |
Where are we with this? Basically what "Adam Barth" was saying is that changing design language, can change the functionalities of the single widgets and it's right but not for most of them. At the expense of clarity, I see two roads:
I'd go for the second But not having this functionality built-in, I know for sure is not good for a project's codebase. I've seen many flutter apps doing this switch manually over the flutter widgets. Tell me yours :) |
second pleases. https://ionicframework.com display platform styled widget, but expose the same interface. |
I would also prefer the second option. If there are platform specific settings these widgets could have a property like |
I'd prefer the second option as well. |
Second option for me as well. If I am not wrong, it should be something like what this library is doing: https://pub.dartlang.org/packages/flutter_platform_widgets |
I'm curious about what people would actually like here. For something like the back button, we do this automatically already. For something a little more elaborate, like a regular text button, one could imagine a control that automatically switches between Cupertino and Material variants. But what about more complicated things? For example, the Switch control is a different size on iOS and Material, what should happen when you use that? Should it change size? Be the biggest size? What about something like a checkbox, which exists on Material but not iOS? Or Navigator, which works entirely differently in Material and iOS paradigms? |
To somewhat second Hixie, as we try to make this more concrete, it's becoming clearer that these are questions that need to be answered at design time rather than implementation time (and even less so doing it implicitly). Even for relatively simple things like sliders and dialogs, in Material, sliders can have manually editable numeric fields, iOS does not. With dialogs, Material specs against having more than 2 responses while UIAlertController supports a vertical scrollable list of actions when there are more than 2 (though discouraged). The interchangeability of dialog/alerts and action sheets is also greater on iOS and requires more design level subjectivity. What should the API be in a common widget? At mid-level complexity: the Material app bar supports toggling into contextual actions mode and having stateful actions (such as the pin button in Google Inbox). iOS's navigation bar commonly has segmented controls in lieu of a title. Material bottom sheets are highly flexible, can be dismissible without choosing any action, can be scrollable/expandable, can even expand into full screens themselves. iOS action sheets are always modal, can't contain arbitrary widgets and aren't even necessarily anchored at the bottom of the screen on iPads. What to do in each case are answers your apps' designers need to answer. At your application's information architecture level, the 2 designs can diverge on the general pattern. In iOS, tab bars with parallel navigation stacks are common. Page navigations occur inside of tabs generally but you can also summon full screen modals that presents pages over the tabs. With Material, what the HIG calls "Flat Navigation" isn't common practice and lateral navigation happens in one page at the hierarchy root level via commonly the drawer. This can create entirely different app experiences. You can navigate to the same sub-item from a feed in tab 1 and from search in tab 2 on iOS. You can go into a profile tab in tab 3, change some app-wide setting and go back to tab 1. These interactions aren't possible if lateral navigation only happen at the root. These are all product/design level questions that are likely too late to try to answer at implementation time. Given the need to make design choices, there are 2 choices we can take (and get community feedback on). 1- Present an opinionated and (arbitrarily) shrunk down set of widgets that takes the minimally supported API options from both while making compromises clearly documented. e.g. there's always 2 choices on dialogs, common app/nav bars can't have iOS 11 style large titles or be translucent etc. Since these design choices aren't inherently related to Material or Cupertino themselves, they can't be in either packages and should be separate Flutter package in pub. Orthogonally to all of this, some UI are always going to be 'wrong' if not done, such as back swipe navigations on iOS or iOS scroll physics on Android. For those, we always auto-adapt to the platform. |
In order to move this issue forward and to take concrete action based on user feedback, I've created a doc http://bit.ly/flutter-adaptive-widget-problem to clarify terminology around this nebulous concept and hopefully break it down into smaller bits. Please give us your feedback in terms of what specifically is desired with respect to 'dynamic adaptations'. Once we have some feedback, we can close this issue and break it down into smaller specific actionable issues. |
@xster The document you provided is very helpful. I think automatic switching on types 3 and 4 is very helpful. In addition, just to add to the conversation, something like https://pub.dartlang.org/packages/flutter_platform_widgets |
Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now. Please don't hesitate to comment on the bug if you have any more information for us; we will reopen it right away! |
We haven't received any actionable feedback from http://bit.ly/flutter-adaptive-widget-problem so we're closing this issue and branching off the subset (type 4) of the problem that's solvable in #33830. @ShadyBoukhary, for type 3, specifically based on http://bit.ly/flutter-adaptive-widget-problem, which compromises would you like us to make (such as in the dialog/dropdown/action sheet/picker/pop-up many-to-many scenario)? |
This feels a lot like the discussions when Swing was first introduced. Basically, what people WANT is the ability to say something like ( child: Text( “some text” ) ) and have the platform draw an OEM or OEM-ish textbox without thinking any more about it. When you build a material app you’re essentially agreeing to have the whole thing look like Android unless you take other actions. The DESIRE in the community is for it to look like the device’s native design language without taking extra steps. That’s hard. But that’s what people want. Adding class decoration or different types just makes for clunkier code, and IMO, should only be necessary when you really, really want to decorate something in a very particular way. For me and my company, we just say screw it... you get an Android-looking app while we continue to evaluate what Flutter really does for us that we can’t get with Native, beyond just the kitsch of saying we can work in Flutter. Which not one single customer has ever heard of (yet). :) The hope of “write once, run everywhere” is still very much in its youth because every time you blink, another new company, another new platform, another new “better idea” pops up, and now you’ve got to decide between Ionic, React Native (bleh), Trigger, Flutter, and... let’s see what’s next. Great goal. Competing platforms may drive platform enhancements and updates and innovations, but also further fragments the landscape. At least Flutter came from one of the big campuses, and it’s pretty much the only cross-platform tool that has. That’s power. I don’t see Apple ever building XCode for Android, and native Android development is akin to eating a live rattlesnake, so at the very least, Flutter brings WAY more approachability to “native”-enough development for Android. If nothing else ever comes of it in terms of cross-platform adoption, THAT ALONE is well, well worth the price of admission. $.02 |
Updated: this sign-up form has been closed. Thank you for your interests! Hello from the Flutter team! If you’re following this discussion, we are looking for a few Flutter developers to share their experience on developing Flutter apps that have a platform-specific look & feel for both iOS and Android. If you’re interested, please fill out this short questionnaire: [closed] Thank you very much for your help! |
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of |
Provide an easy way for developers to insert a simple widget whose UI conforms to Material or Cupertino depending on runtime platform.
The text was updated successfully, but these errors were encountered: