Merge pull request #3052 from vlidholt/linedrawing
Initial version of complex layout performance test
9
dev/benchmarks/complex_layout/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.idea
|
||||||
|
.packages
|
||||||
|
.pub/
|
||||||
|
build/
|
||||||
|
ios/.generated/
|
||||||
|
packages
|
||||||
|
pubspec.lock
|
22
dev/benchmarks/complex_layout/android/AndroidManifest.xml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.yourcompany.complexLayout"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="0.0.1">
|
||||||
|
|
||||||
|
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
|
||||||
|
<application android:name="org.domokit.sky.shell.SkyApplication" android:label="complex_layout" android:icon="@mipmap/ic_launcher">
|
||||||
|
<activity android:name="org.domokit.sky.shell.SkyActivity"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 8.7 KiB |
6
dev/benchmarks/complex_layout/flutter.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
name: complex_layout
|
||||||
|
uses-material-design: true
|
||||||
|
assets:
|
||||||
|
- packages/flutter_gallery_assets/ali_connors.png
|
||||||
|
- packages/flutter_gallery_assets/ali_connors_sml.png
|
||||||
|
- packages/flutter_gallery_assets/top_10_australian_beaches.png
|
@ -0,0 +1,142 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-Small@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-Small@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-Small-40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-Small-40@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-60@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-60@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-Small.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-Small@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-Small-40.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-Small-40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-76.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-76@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "83.5x83.5",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-83.5@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "16x16",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_16x16.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "16x16",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_16x16@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "32x32",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_32x32.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "32x32",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_32x32@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "128x128",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_128x128.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "128x128",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_128x128@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "256x256",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_256x256.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "256x256",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_256x256@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "512x512",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_512x512.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "512x512",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_512x512@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 869 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 425 B |
After Width: | Height: | Size: 952 B |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 952 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 56 KiB |
47
dev/benchmarks/complex_layout/ios/Info.plist
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>Runner</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.yourcompany.complexLayout</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>complex_layout</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
27
dev/benchmarks/complex_layout/ios/LaunchScreen.storyboard
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
636
dev/benchmarks/complex_layout/lib/main.dart
Normal file
@ -0,0 +1,636 @@
|
|||||||
|
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart' show timeDilation;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(
|
||||||
|
new ComplexLayoutApp()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ComplexLayoutApp extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
ComplexLayoutAppState createState() => new ComplexLayoutAppState();
|
||||||
|
|
||||||
|
static ComplexLayoutAppState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<ComplexLayoutAppState>());
|
||||||
|
}
|
||||||
|
|
||||||
|
class ComplexLayoutAppState extends State<ComplexLayoutApp> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new MaterialApp(
|
||||||
|
theme: lightTheme ? new ThemeData.light() : new ThemeData.dark(),
|
||||||
|
title: 'Advanced Layout',
|
||||||
|
routes: <String, WidgetBuilder>{
|
||||||
|
'/': (BuildContext context) => new ComplexLayout(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _lightTheme = true;
|
||||||
|
bool get lightTheme => _lightTheme;
|
||||||
|
void set lightTheme(bool value) {
|
||||||
|
setState(() {
|
||||||
|
_lightTheme = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ComplexLayout extends StatefulWidget {
|
||||||
|
ComplexLayout({ Key key }) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ComplexLayoutState createState() => new ComplexLayoutState();
|
||||||
|
|
||||||
|
static ComplexLayoutState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<ComplexLayoutState>());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ComplexLayoutState extends State<ComplexLayout> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
return new Scaffold(
|
||||||
|
appBar: new AppBar(
|
||||||
|
title: new Text('Advanced Layout'),
|
||||||
|
actions: <Widget>[
|
||||||
|
new IconButton(
|
||||||
|
icon: Icons.create,
|
||||||
|
tooltip: 'Search',
|
||||||
|
onPressed: () {
|
||||||
|
print("Pressed search");
|
||||||
|
}
|
||||||
|
),
|
||||||
|
new TopBarMenu()
|
||||||
|
]
|
||||||
|
),
|
||||||
|
body: new Column(
|
||||||
|
children: <Widget>[
|
||||||
|
new Flexible(
|
||||||
|
child: new ScrollableMixedWidgetList(
|
||||||
|
key: new Key("main-scroll"),
|
||||||
|
builder: (BuildContext context, int index) {
|
||||||
|
if (index % 2 == 0)
|
||||||
|
return new FancyImageItem(index, key: new Key("Item $index"));
|
||||||
|
else
|
||||||
|
return new FancyGalleryItem(index, key: new Key("Item $index"));
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new BottomBar()
|
||||||
|
]
|
||||||
|
),
|
||||||
|
drawer: new GalleryDrawer()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TopBarMenu extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new PopupMenuButton<String>(
|
||||||
|
onSelected: (String value) { print("Selected: $value"); },
|
||||||
|
items: <PopupMenuItem<String>>[
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Friends",
|
||||||
|
child: new MenuItemWithIcon(Icons.people, "Friends", "5 new")
|
||||||
|
),
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Events",
|
||||||
|
child: new MenuItemWithIcon(Icons.event, "Events", "12 upcoming")
|
||||||
|
),
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Events",
|
||||||
|
child: new MenuItemWithIcon(Icons.group, "Groups", "14")
|
||||||
|
),
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Events",
|
||||||
|
child: new MenuItemWithIcon(Icons.image, "Pictures", "12")
|
||||||
|
),
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Events",
|
||||||
|
child: new MenuItemWithIcon(Icons.near_me, "Nearby", "33")
|
||||||
|
),
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Friends",
|
||||||
|
child: new MenuItemWithIcon(Icons.people, "Friends", "5")
|
||||||
|
),
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Events",
|
||||||
|
child: new MenuItemWithIcon(Icons.event, "Events", "12")
|
||||||
|
),
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Events",
|
||||||
|
child: new MenuItemWithIcon(Icons.group, "Groups", "14")
|
||||||
|
),
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Events",
|
||||||
|
child: new MenuItemWithIcon(Icons.image, "Pictures", "12")
|
||||||
|
),
|
||||||
|
new PopupMenuItem<String>(
|
||||||
|
value: "Events",
|
||||||
|
child: new MenuItemWithIcon(Icons.near_me, "Nearby", "33")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuItemWithIcon extends StatelessWidget {
|
||||||
|
MenuItemWithIcon(this.icon, this.title, this.subtitle);
|
||||||
|
|
||||||
|
final IconData icon;
|
||||||
|
final String title;
|
||||||
|
final String subtitle;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Row(
|
||||||
|
children: <Widget>[
|
||||||
|
new Icon(icon: icon),
|
||||||
|
new Padding(
|
||||||
|
padding: new EdgeInsets.only(left: 8.0, right: 8.0),
|
||||||
|
child: new Text(title)
|
||||||
|
),
|
||||||
|
new Text(subtitle, style: Theme.of(context).textTheme.caption)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FancyImageItem extends StatelessWidget {
|
||||||
|
FancyImageItem(this.index, {Key key}) : super(key: key);
|
||||||
|
|
||||||
|
final int index;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new BlockBody(
|
||||||
|
children: <Widget>[
|
||||||
|
new UserHeader("Ali Connors $index"),
|
||||||
|
new ItemDescription(),
|
||||||
|
new ItemImageBox(),
|
||||||
|
new InfoBar(),
|
||||||
|
new Padding(
|
||||||
|
padding: new EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: new Divider()
|
||||||
|
),
|
||||||
|
new IconBar(),
|
||||||
|
new FatDivider()
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FancyGalleryItem extends StatelessWidget {
|
||||||
|
FancyGalleryItem(this.index, {Key key}) : super(key: key);
|
||||||
|
|
||||||
|
final int index;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new BlockBody(
|
||||||
|
children: <Widget>[
|
||||||
|
new UserHeader("Ali Connors"),
|
||||||
|
new ItemGalleryBox(index),
|
||||||
|
new InfoBar(),
|
||||||
|
new Padding(
|
||||||
|
padding: new EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: new Divider()
|
||||||
|
),
|
||||||
|
new IconBar(),
|
||||||
|
new FatDivider()
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InfoBar extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Padding(
|
||||||
|
padding: new EdgeInsets.all(8.0),
|
||||||
|
child: new Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
new MiniIconWithText(Icons.thumb_up, "42"),
|
||||||
|
new Text("3 Comments", style: Theme.of(context).textTheme.caption)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IconBar extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Padding(
|
||||||
|
padding: new EdgeInsets.only(left: 16.0, right: 16.0),
|
||||||
|
child: new Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
new IconWithText(Icons.thumb_up, "Like"),
|
||||||
|
new IconWithText(Icons.comment, "Comment"),
|
||||||
|
new IconWithText(Icons.share, "Share"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IconWithText extends StatelessWidget {
|
||||||
|
IconWithText(this.icon, this.title);
|
||||||
|
|
||||||
|
final IconData icon;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.collapse,
|
||||||
|
children: <Widget>[
|
||||||
|
new IconButton(icon: icon, onPressed: () { print("Pressed $title button"); } ),
|
||||||
|
new Text(title)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MiniIconWithText extends StatelessWidget {
|
||||||
|
MiniIconWithText(this.icon, this.title);
|
||||||
|
|
||||||
|
final IconData icon;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.collapse,
|
||||||
|
children: <Widget>[
|
||||||
|
new Padding(
|
||||||
|
padding: new EdgeInsets.only(right: 8.0),
|
||||||
|
child: new Container(
|
||||||
|
width: 16.0,
|
||||||
|
height: 16.0,
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
|
shape: BoxShape.circle
|
||||||
|
),
|
||||||
|
child: new Icon(icon: icon, color: Colors.white, size: 12.0)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new Text(title, style: Theme.of(context).textTheme.caption)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FatDivider extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Container(
|
||||||
|
height: 8.0,
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
backgroundColor: Theme.of(context).dividerColor
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserHeader extends StatelessWidget {
|
||||||
|
UserHeader(this.userName);
|
||||||
|
|
||||||
|
final String userName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Padding(
|
||||||
|
padding: new EdgeInsets.all(8.0),
|
||||||
|
child: new Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
new Padding(
|
||||||
|
padding: new EdgeInsets.only(right: 8.0),
|
||||||
|
child: new AssetImage(
|
||||||
|
name: "packages/flutter_gallery_assets/ali_connors_sml.png",
|
||||||
|
width: 32.0,
|
||||||
|
height: 32.0
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new Flexible(
|
||||||
|
child: new Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: <Widget>[
|
||||||
|
new RichText(text: new TextSpan(
|
||||||
|
style: Theme.of(context).textTheme.body1,
|
||||||
|
children: <TextSpan>[
|
||||||
|
new TextSpan(text: userName, style: new TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
new TextSpan(text: " shared a new "),
|
||||||
|
new TextSpan(text: "photo", style: new TextStyle(fontWeight: FontWeight.bold))
|
||||||
|
]
|
||||||
|
)),
|
||||||
|
new Row(
|
||||||
|
children: <Widget>[
|
||||||
|
new Text("Yesterday at 11:55 • ", style: Theme.of(context).textTheme.caption),
|
||||||
|
new Icon(icon: Icons.people, size: 16.0, color: Theme.of(context).textTheme.caption.color)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new TopBarMenu()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemDescription extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Padding(
|
||||||
|
padding: new EdgeInsets.all(8.0),
|
||||||
|
child: new Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemImageBox extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Padding(
|
||||||
|
padding: new EdgeInsets.all(8.0),
|
||||||
|
child: new Card(
|
||||||
|
child: new Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: <Widget>[
|
||||||
|
new Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
new SizedBox(
|
||||||
|
height: 230.0,
|
||||||
|
child: new AssetImage(
|
||||||
|
name: "packages/flutter_gallery_assets/top_10_australian_beaches.png"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new Theme(
|
||||||
|
data: new ThemeData.dark(),
|
||||||
|
child: new Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
new IconButton(icon: Icons.edit, onPressed: () { print("Pressed edit button"); }),
|
||||||
|
new IconButton(icon: Icons.zoom_in, onPressed: () { print("Pressed zoom button"); })
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new Positioned(
|
||||||
|
bottom: 4.0,
|
||||||
|
left: 4.0,
|
||||||
|
child: new Container(
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
backgroundColor: Colors.black54,
|
||||||
|
borderRadius: 2.0
|
||||||
|
),
|
||||||
|
padding: new EdgeInsets.all(4.0),
|
||||||
|
child: new RichText(
|
||||||
|
text: new TextSpan(
|
||||||
|
style: new TextStyle(color: Colors.white),
|
||||||
|
children: <TextSpan>[
|
||||||
|
new TextSpan(
|
||||||
|
text: "Photo by "
|
||||||
|
),
|
||||||
|
new TextSpan(
|
||||||
|
style: new TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
text: "Magic Mike"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
,
|
||||||
|
new Padding(
|
||||||
|
padding: new EdgeInsets.all(8.0),
|
||||||
|
child: new Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: <Widget>[
|
||||||
|
new Text("Where can you find that amazing sunset?", style: Theme.of(context).textTheme.body2),
|
||||||
|
new Text("The sun sets over stinson beach", style: Theme.of(context).textTheme.body1),
|
||||||
|
new Text("flutter.io/amazingsunsets", style: Theme.of(context).textTheme.caption)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemGalleryBox extends StatelessWidget {
|
||||||
|
ItemGalleryBox(this.index);
|
||||||
|
|
||||||
|
final int index;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<String> tabNames = <String>[
|
||||||
|
"A", "B", "C", "D"
|
||||||
|
];
|
||||||
|
|
||||||
|
return new SizedBox(
|
||||||
|
height: 200.0,
|
||||||
|
child: new TabBarSelection<String>(
|
||||||
|
values: tabNames,
|
||||||
|
child: new Column(
|
||||||
|
children: <Widget>[
|
||||||
|
new Flexible(
|
||||||
|
child: new TabBarView(
|
||||||
|
children: tabNames.map((String tabName) {
|
||||||
|
return new Container(
|
||||||
|
key: new Key("Tab $index - $tabName"),
|
||||||
|
child: new Padding(
|
||||||
|
padding: new EdgeInsets.all(8.0),
|
||||||
|
child: new Card(
|
||||||
|
child: new Column(
|
||||||
|
children: <Widget>[
|
||||||
|
new Flexible(
|
||||||
|
child: new Container(
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
backgroundColor: Theme.of(context).primaryColor
|
||||||
|
),
|
||||||
|
child: new Center(
|
||||||
|
child: new Text(tabName, style: Theme.of(context).textTheme.headline.copyWith(color: Colors.white))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new Row(
|
||||||
|
children: <Widget>[
|
||||||
|
new IconButton(
|
||||||
|
icon: Icons.share,
|
||||||
|
onPressed: () { print("Pressed share"); }
|
||||||
|
),
|
||||||
|
new IconButton(
|
||||||
|
icon: Icons.event,
|
||||||
|
onPressed: () { print("Pressed event"); }
|
||||||
|
),
|
||||||
|
new Flexible(
|
||||||
|
child: new Padding(
|
||||||
|
padding: new EdgeInsets.only(left: 8.0),
|
||||||
|
child: new Text("This is item $tabName")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}).toList()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new Container(
|
||||||
|
child: new TabPageSelector<String>()
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BottomBar extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Container(
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
border: new Border(
|
||||||
|
top: new BorderSide(
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
width: 1.0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
child: new Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
new BottomBarButton(Icons.new_releases, "News"),
|
||||||
|
new BottomBarButton(Icons.people, "Requests"),
|
||||||
|
new BottomBarButton(Icons.chat, "Messenger"),
|
||||||
|
new BottomBarButton(Icons.bookmark, "Bookmark"),
|
||||||
|
new BottomBarButton(Icons.alarm, "Alarm")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BottomBarButton extends StatelessWidget {
|
||||||
|
BottomBarButton(this.icon, this.title);
|
||||||
|
|
||||||
|
final IconData icon;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Padding(
|
||||||
|
padding: new EdgeInsets.all(8.0),
|
||||||
|
child: new Column(
|
||||||
|
children: <Widget>[
|
||||||
|
new IconButton(
|
||||||
|
icon: icon,
|
||||||
|
onPressed: () { print("Pressed: $title"); }
|
||||||
|
),
|
||||||
|
new Text(title, style: Theme.of(context).textTheme.caption)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GalleryDrawer extends StatelessWidget {
|
||||||
|
GalleryDrawer({ Key key }) : super(key: key);
|
||||||
|
|
||||||
|
void _changeTheme(BuildContext context, bool value) {
|
||||||
|
ComplexLayoutApp.of(context).lightTheme = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggleAnimationSpeed(BuildContext context) {
|
||||||
|
ComplexLayoutApp.of(context).setState(() {
|
||||||
|
timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Drawer(
|
||||||
|
child: new Block(
|
||||||
|
children: <Widget>[
|
||||||
|
new FancyDrawerHeader(),
|
||||||
|
new DrawerItem(
|
||||||
|
icon: Icons.brightness_5,
|
||||||
|
onPressed: () { _changeTheme(context, true); },
|
||||||
|
selected: ComplexLayoutApp.of(context).lightTheme,
|
||||||
|
child: new Row(
|
||||||
|
children: <Widget>[
|
||||||
|
new Flexible(child: new Text('Light')),
|
||||||
|
new Radio<bool>(
|
||||||
|
value: true,
|
||||||
|
groupValue: ComplexLayoutApp.of(context).lightTheme,
|
||||||
|
onChanged: (bool value) { _changeTheme(context, value); }
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new DrawerItem(
|
||||||
|
icon: Icons.brightness_7,
|
||||||
|
onPressed: () { _changeTheme(context, false); },
|
||||||
|
selected: !ComplexLayoutApp.of(context).lightTheme,
|
||||||
|
child: new Row(
|
||||||
|
children: <Widget>[
|
||||||
|
new Flexible(child: new Text('Dark')),
|
||||||
|
new Radio<bool>(
|
||||||
|
value: false,
|
||||||
|
groupValue: ComplexLayoutApp.of(context).lightTheme,
|
||||||
|
onChanged: (bool value) { _changeTheme(context, value); }
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new Divider(),
|
||||||
|
new DrawerItem(
|
||||||
|
icon: Icons.hourglass_empty,
|
||||||
|
selected: timeDilation != 1.0,
|
||||||
|
onPressed: () { _toggleAnimationSpeed(context); },
|
||||||
|
child: new Row(
|
||||||
|
children: <Widget>[
|
||||||
|
new Flexible(child: new Text('Animate Slowly')),
|
||||||
|
new Checkbox(
|
||||||
|
value: timeDilation != 1.0,
|
||||||
|
onChanged: (bool value) { _toggleAnimationSpeed(context); }
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FancyDrawerHeader extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Container(
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
backgroundColor: Colors.purple[500]
|
||||||
|
),
|
||||||
|
height: 200.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
8
dev/benchmarks/complex_layout/pubspec.yaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
name: complex_layout
|
||||||
|
description: A new flutter project.
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
path: ../../../packages/flutter
|
||||||
|
flutter_driver:
|
||||||
|
path: ../../../packages/flutter_driver
|
||||||
|
flutter_gallery_assets: '0.0.14'
|
11
dev/benchmarks/complex_layout/test_driver/scroll_perf.dart
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter_driver/driver_extension.dart';
|
||||||
|
import 'package:complex_layout/main.dart' as app;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
enableFlutterDriverExtension();
|
||||||
|
app.main();
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:flutter_driver/flutter_driver.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('scrolling performance test', () {
|
||||||
|
FlutterDriver driver;
|
||||||
|
|
||||||
|
setUpAll(() async {
|
||||||
|
driver = await FlutterDriver.connect();
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDownAll(() async {
|
||||||
|
if (driver != null)
|
||||||
|
driver.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('measure', () async {
|
||||||
|
Map<String, dynamic> profileJson = await driver.traceAction(() async {
|
||||||
|
// Find the scrollable stock list
|
||||||
|
ObjectRef stockList = await driver.findByValueKey('main-scroll');
|
||||||
|
expect(stockList, isNotNull);
|
||||||
|
|
||||||
|
// Scroll down
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
await driver.scroll(stockList, 0.0, -300.0, new Duration(milliseconds: 300));
|
||||||
|
await new Future<Null>.delayed(new Duration(milliseconds: 500));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll up
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
await driver.scroll(stockList, 0.0, 300.0, new Duration(milliseconds: 300));
|
||||||
|
await new Future<Null>.delayed(new Duration(milliseconds: 500));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(profileJson, isNotNull);
|
||||||
|
await new File("build/profile.json").writeAsString(JSON.encode(profileJson));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|