Skip to content

Instantly share code, notes, and snippets.

@rydmike

rydmike/main.dart

Last active Aug 6, 2020
Embed
What would you like to do?
Demo code for Flutter Elevation Issue, the issue is only visible on SKIA builds, not on Web DomCanvas.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
const double kEdgePadding = 35.0;
const double kMaxContentWidth = 800.0;
const double kMaxExtraSpace = 1500.0;
const double kMaxElevation = 20.0;
const int kMaxCards = 20;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
systemNavigationBarColor: Colors.grey[100],
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light,
systemNavigationBarIconBrightness: Brightness.dark,
),
);
return MaterialApp(
title: 'Flutter Elevation Issue',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.indigo,
scaffoldBackgroundColor: Colors.grey[100],
buttonTheme: ButtonThemeData(
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.indigo),
textTheme: ButtonTextTheme.primary,
),
),
// home: SliverGridExtPage(title: 'Flutter Elevation Issue'),
home: const ElevationIssueDemoPage(title: 'Flutter Elevation Issue'),
);
}
}
class ElevationIssueDemoPage extends StatefulWidget {
const ElevationIssueDemoPage({Key key, this.title}) : super(key: key);
final String title;
@override
_ElevationIssueDemoPageState createState() => _ElevationIssueDemoPageState();
}
class _ElevationIssueDemoPageState extends State<ElevationIssueDemoPage> {
double elevation;
double spaceBefore;
bool wrapInColumn;
@override
void initState() {
elevation = 6;
spaceBefore = 0;
wrapInColumn = false;
super.initState();
}
@override
Widget build(BuildContext context) {
final double topPadding = MediaQuery.of(context).padding.top;
final double bottomPadding = MediaQuery.of(context).padding.bottom;
final TextStyle headline6 = Theme.of(context).textTheme.headline6;
final Size size = MediaQuery.of(context).size;
return Scaffold(
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
title: Row(
children: <Widget>[
Text(widget.title),
// Show canvas size in tha app bar
Expanded(
child: Text(
" W:${size.width.round()} H:${size.height.round()}",
style: const TextStyle(fontSize: 11, color: Colors.white),
textAlign: TextAlign.right,
),
),
],
),
centerTitle: true,
elevation: 0,
backgroundColor: Colors.transparent,
// Gradient partially transparent AppBar
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.topRight,
colors: <Color>[
Colors.indigo,
Colors.indigo.withOpacity(0.7),
],
),
),
child: null,
),
),
body: Scrollbar(
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: kMaxContentWidth),
child: ListView(
padding: EdgeInsets.fromLTRB(
kEdgePadding,
topPadding + kToolbarHeight,
kEdgePadding,
kEdgePadding + bottomPadding,
),
children: <Widget>[
Text(
'Strange elevations',
style: Theme.of(context).textTheme.headline4,
),
Text('Issue 1', style: headline6),
const Text(
'The Material SKIA elevation shadow gets too substantial on '
'objects far down or to the far right on a large canvas.\n'
'Already a small elevation of 6 on a 2000px tall screen '
'looks very bad.'),
Text('Issue 2', style: headline6),
const Text(
'The elevation shadows gets really strange when the cards '
'are added in Column to a ListView. \n '
'A bit sub-optimal usage, but it may happen in a widget tree '
'where user does not have access to parent implementation.'),
const SizedBox(height: 16),
const SelectableText(
'Source: https://gist.github.com/rydmike/145828269bd8d24ee9c44a9df26ec7fb'),
const SizedBox(height: 20),
//
// Adjust card elevation
//
const Divider(),
ListTile(
title: const Text('Change card elevation'),
subtitle: Slider.adaptive(
min: 0.0,
max: kMaxElevation,
divisions: (kMaxElevation * 2).floor(),
label: elevation.toStringAsFixed(1),
value: elevation,
onChanged: (double value) {
setState(() {
elevation = value;
});
},
),
trailing: Padding(
padding: const EdgeInsets.only(right: 12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
const Text(
'Elevation',
style: TextStyle(fontSize: 11),
),
Text(
elevation.toStringAsFixed(1),
style: const TextStyle(fontSize: 15),
),
],
),
),
),
//
// Wrap the card inside a column
//
const Divider(),
SwitchListTile.adaptive(
title: const Text(
'Wrap the cards in a Column for issue 2',
),
subtitle: const Text(
'The shadows change and get less pronounced, BUT '
'they behave really strangely. Like the light '
'source would move from an above position higher up than '
'the elevated cards, to a position below them, as you scroll '
'further down. VERY PECULIAR!',
),
value: wrapInColumn,
onChanged: (bool value) {
setState(() {
wrapInColumn = value;
});
},
),
//
// Adjust space before cards
//
const Divider(),
ListTile(
title: const Text(
'Space before the cards. See how shadow changes as cards move down'),
subtitle: Slider.adaptive(
min: 0.0,
max: kMaxExtraSpace,
divisions: kMaxExtraSpace.floor(),
label: spaceBefore.floor().toString(),
value: spaceBefore,
onChanged: (double value) {
setState(() {
spaceBefore = value;
});
},
),
trailing: Padding(
padding: const EdgeInsets.only(right: 12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
const Text(
'Space',
style: TextStyle(fontSize: 11),
),
Text(
spaceBefore.floor().toString(),
style: const TextStyle(fontSize: 15),
),
],
),
),
),
//
// Extra spacing before cards
SizedBox(height: spaceBefore),
const Divider(),
if (!wrapInColumn)
Text('Cards in a list',
style: Theme.of(context).textTheme.headline5),
//
// Plain cards with elevation, added to this list inside a column
if (wrapInColumn)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Cards in a list, wrapped in a column',
style: Theme.of(context).textTheme.headline5),
for (int i = 0; i < kMaxCards; i++)
Padding(
padding: const EdgeInsets.only(bottom: kEdgePadding),
child: Card(
elevation: elevation,
child: Container(
height: 90,
child: Center(child: Text('Card ${i + 1}')),
),
),
),
const Text(
'Anything elevated inside the column is affected, '
'also this raised button.'),
RaisedButton(
onPressed: () {},
child: const Text('RAISED BUTTON'),
),
],
)
// Plain cards with elevation, added directly to the list view
else
for (int i = 0; i < kMaxCards; i++)
Padding(
padding: const EdgeInsets.only(bottom: kEdgePadding),
child: Card(
elevation: elevation,
child: Container(
height: 90,
child: Center(
child: Text('Card ${i + 1}'),
),
),
),
),
//
// Let's add a grid with card below the Card in a list
// to see how they look.
const SizedBox(height: kEdgePadding),
Text('Colorful cards in a GridView',
style: Theme.of(context).textTheme.headline5),
if (wrapInColumn)
const Text(
'Items outside the column are unaffected when they appear '
'below the items in the column. They do however always '
'get too pronounced shadows far down and right on the '
'canvas, as everything always do. Notice '
'how strange it looks with these cards illuminated from '
'above and the cards and button above them from below!'),
GridView.builder(
padding: const EdgeInsets.all(kEdgePadding),
shrinkWrap: true,
primary: false,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: kEdgePadding,
crossAxisSpacing: kEdgePadding,
childAspectRatio: 2,
),
itemCount: kMaxCards,
itemBuilder: (_, int index) => Card(
elevation: elevation,
child: GridItem(
title: 'Card ${index + 1}',
color: Colors.primaries[index % Colors.primaries.length]
[800]),
),
)
],
),
),
),
),
);
}
}
class GridItem extends StatelessWidget {
const GridItem({Key key, this.title, this.color}) : super(key: key);
final String title;
final Color color;
@override
Widget build(BuildContext context) {
return Container(
color: color,
padding: const EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
title,
style: const TextStyle(
color: Colors.white,
fontSize: 18,
),
),
const Icon(Icons.apps, color: Colors.white),
],
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment