Commit b136deda authored by Adam Barth's avatar Adam Barth

Move Getting Started and Tutorial to GitHub pages

Along with some other docs.
parent 0f4d3765
Getting Started with Sky
========================
Sky
===
Sky apps are written in Dart. To get started, we need to set up Dart SDK:
Sky is a new way to build high-performance, cross-platform mobile apps.
Sky is optimized for today's, and tomorrow's, mobile devices. We are
focused on low-latency input and high frame rates on Android and iOS.
- Install the [Dart SDK](https://www.dartlang.org/downloads/):
- Mac: `brew tap dart-lang/dart && brew install dart --devel`
- Linux: See [https://www.dartlang.org/downloads/linux.html](https://www.dartlang.org/downloads/linux.html)
- Ensure that `$DART_SDK` is set to the path of your Dart SDK and that the
`dart` and `pub` executables are on your `$PATH`.
Once you have installed Dart SDK, create a new directory and add a
[pubspec.yaml](https://www.dartlang.org/tools/pub/pubspec.html):
```yaml
name: your_app_name
dependencies:
sky: any
sky_tools: any
```
Next, create a `lib` directory (which is where your Dart code will go) and use
the `pub` tool to fetch the Sky package and its dependencies:
- `mkdir lib`
- `pub upgrade`
Sky assumes the entry point for your application is a `main` function in
`lib/main.dart`:
```dart
import 'package:sky/widgets.dart';
class HelloWorldApp extends App {
Widget build() {
return new Center(child: new Text('Hello, world!'));
}
}
void main() {
runApp(new HelloWorldApp());
}
```
Execution starts in `main`, which in this example runs a new instance of the `HelloWorldApp`.
The `HelloWorldApp` builds a `Text` widget containing the traditional `Hello, world!`
string and centers it on the screen using a `Center` widget. To learn more about
the widget system, please see the
[widgets tutorial](https://github.com/domokit/sky_engine/blob/master/sky/packages/sky/lib/src/widgets/README.md).
Setting up your Android device
-------------------------
Currently Sky requires an Android device running the Lollipop (or newer) version
of the Android operating system.
- Install the `adb` tool from the [Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools):
- Mac: `brew install android-platform-tools`
- Linux: `sudo apt-get install android-tools-adb`
- If the version of `adb` provided by your Linux distribution is too old,
you might need to [install the Android SDK manually](https://developer.android.com/sdk/installing/index.html?pkg=tools]).
- Enable developer mode on your device by visiting `Settings > About phone`
and tapping the `Build number` field five times.
- Enable `Android debugging` in `Settings > Developer options`.
- Using a USB cable, plug your phone into your computer. If prompted on your
device, authorize your computer to access your device.
Running a Sky application
-------------------------
The `sky` pub package includes a `sky_tool` script to assist in running
Sky applications inside the `SkyShell.apk` harness. The `sky_tool` script
expects to be run from the root directory of your application's package (i.e.,
the same directory that contains the `pubspec.yaml` file).
To run your app with logging, run this command:
- `./packages/sky/sky_tool start --checked && ./packages/sky/sky_tool logs`
The `sky_tool start` command starts the dev server and uploads your app to the device, installing `SkyShell.apk` if needed.
The `--checked` flag triggers checked mode, in which types are checked, asserts are run, and
various [debugging features](https://github.com/domokit/sky_engine/blob/master/sky/packages/sky/lib/base/debug.dart) are enabled.
The `sky_tool logs` command logs errors and Dart `print()` output from the app, automatically limiting the output to just output from Sky Dart code and the Sky Engine C++ code (which
for historical reasons currently uses the tag `chromium`.)
To avoid confusion from old log messages, you may wish to call `sky_tool logs --clear` before calling
`sky_tool start`, to clear the log between runs.
Rapid Iteration
---------------
As an alternative to running `./packages/sky/sky_tool start` every time you make a change,
you might prefer to have the SkyShell reload your app automatically for you as you edit. To
do this, run the following command:
- `./packages/sky/sky_tool listen`
This is a long-running command -- just press `ctrl-c` when you want to stop listening for
changes to the file system and automatically reloading your app.
Currently `sky_tool listen` only works for Android, but iOS device and iOS simulator support
are coming soon.
Debugging
---------
Sky uses [Observatory](https://www.dartlang.org/tools/observatory/) for
debugging and profiling. While running your Sky app using `sky_tool`, you can
access Observatory by navigating your web browser to
[http://localhost:8181/](http://localhost:8181/).
Building a standalone APK
-------------------------
Although it is possible to build a standalone APK containing your application,
doing so right now is difficult. If you're feeling brave, you can see how we
build the `Stocks.apk` in
[examples/stocks](https://github.com/domokit/sky_engine/tree/master/examples/stocks).
Eventually we plan to make this much easier and support platforms other than
Android, but that work still in progress.
See the [getting started guide](https://flutter.github.io/getting-started/) for
information about using Sky.
This diff is collapsed.
......@@ -360,7 +360,7 @@ abstract class RenderBox extends RenderObject {
assert(constraints != null);
assert(_size != null);
assert(() {
'See https://github.com/domokit/sky_engine/blob/master/sky/packages/sky/lib/src/widgets/sizing.md#user-content-unbounded-constraints';
'See https://flutter.github.io/layout/#unbounded-constraints';
return !_size.isInfinite;
});
bool result = constraints.isSatisfiedBy(_size);
......
......@@ -351,7 +351,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
// Flexible children can only be used when the RenderFlex box's container has a finite size.
// When the container is infinite, for example if you are in a scrollable viewport, then
// it wouldn't make any sense to have a flexible child.
assert(canFlex && 'See https://github.com/domokit/sky_engine/blob/master/sky/packages/sky/lib/src/widgets/sizing.md#user-content-flex' is String);
assert(canFlex && 'See https://flutter.github.io/layout/#flex' is String);
totalFlex += child.parentData.flex;
} else {
BoxConstraints innerConstraints;
......
This diff is collapsed.
Sizing in Sky
=============
Background
----------
In Sky, widgets are rendered by render boxes. Render boxes are given
constraints by their parent, and size themselves within those
constraints. Constraints consist of minimum and maximum widths and
heights; sizes consist of a specific width and height.
Generally, there are three kinds of boxes, in terms of how they handle
their constraints:
- Those that try to be as big as possible.
For example, the boxes used by `Center` and `Block`.
- Those that try to be the same size as their children.
For example, the boxes used by `Transform` and `Opacity`.
- Those that try to be a particular size.
For example, the boxes used by `Image` and `Text`.
Some widgets, for example `Container`, vary from type to type based on
their constructor arguments. In the case of `Container`, it defaults
to trying to be as big as possible, but if you give it a `width`, for
instance, it tries to honor that and be that particular size.
Others, for example `Row` and `Column` (flex boxes) vary based on the
constraints they are given, as described below in the "Flex" section.
The constraints are sometimes "tight", meaning that they leave no room
for the render box to decide on a size (e.g. if the minimum and
maximum width are the same, it is said to have a tight width). The
main example of this is the `App` widget, which is contained by the
`RenderView` class: the box used by the child returned by the
application's `build` function is given a constraint that forces it to
exactly fill the application's content area (typically, the entire
screen). Many of the boxes in Sky, especially those that just take a
single child, will pass their constraint on to their children. This
means that if you nest a bunch of boxes inside each other at the root
of your application's render tree, they'll all exactly fit in each
other, forced by these tight constraints.
Some boxes _loosen_ the constraints, meaning the maximum is maintained
but the minimum is removed. For example, `Center`.
Unbounded constraints
---------------------
In certain situations, the constraint that is given to a box will be
_unbounded_, or infinite. This means that either the maximum width or
the maximum height is set to `double.INFINITY`.
A box that tries to be as big as possible won't function usefully when
given an unbounded constraint, and in checked mode, will assert with a
message saying `!_size.isInfinite` and a string that points to this
file.
The most common cases where a render box finds itself with unbounded
constraints are within flex boxes (`Row` and `Column`), and **within
scrollable regions** (mainly `Block`, `ScollableList<T>`, and
`ScrollableMixedWidgetList`).
In particular, `Block` tries to expand to fit the space available in
its cross-direction (i.e. if it's a vertically-scrolling block, it
will try to be as wide as its parent). If you nest a vertically
scrolling `Block` inside a horizontally scrolling `Block`, the inner
one will try to be as wide as possible, which is infinitely wide,
since the outer one is scrollable in that direction.
Flex
----
Flex boxes themselves (`Row` and `Column`) behave differently based on
whether they are in a bounded constraints or unbounded constraints in
their given direction.
In bounded constraints, they try to be as big as possible in that
direction.
In unbounded constraints, they try to fit their children in that
direction. In this case, you cannot set `flex` on the children to
anything other than 0 (the default). In the widget hierarchy, this
means that you cannot use `Flexible` when the flex box is inside
another flex box or inside a scrollable. If you do, you'll get an
assert that `canFlex` is not true, pointing you at this section.
In the _cross_ direction, i.e. in their width for `Column` (vertical
flex) and in their height for `Row` (horizontal flex), they must never
be unbounded, otherwise they would not be able to reasonably align
their children.
Sky Widgets: Basic
==================
This document describes the basic widgets available in Sky. These widgets are
general-purpose and don't offer an opinion about the visual style of your app.
Container
---------
`Container` is a general-purpose widget that combines several basic widgets in
order to make them easier to use.
- `BoxDecoration decoration` Draw the given decoration around this container.
- `double width` Forces the container to have the given width.
- `double height` Force the container to have the given height.
- `EdgeDims margin` Surrounds the container (i.e., outside the container's
decoration) on the top, right, bottom, and left with the given amount of
space.
- `EdgeDims padding` Surrounds the container's child (i.e., inside the
container's decoration) on the top, right, bottom, and left with the given
amount of space.
- `Matrix4 transform` Apply the given matrix before painting the container.
- `BoxConstraints constraints` Force the width and height of the container to
respect the given constraints.
Layout models
-------------
There are two _flex_ layout models:
- `Row`: Layout a list of child widgets in the horizontal direction.
- `Column': Layout a list of child widgets in the vertical direction.
The direction along which the widgets are laid out is called the
*main* direction and the other axis is called the *cross* direction.
These flex widgets size themselves to the maximum size permitted by
its parent, unless that would be infinite size, in which case they
shrink-wrap their children. For details, see [flex.md](flex.md).
Each child of a flex widget is either *flexible* or *inflexible*.
The flex first lays out its inflexible children and subtracts their
total length along the main direction to determine how much free space
is available. The flex then divides this free space among the flexible
children in a ratio determined by their `flex` properties.
The `alignItems` property determines how children are positioned in
the cross direction. The `justifyContent` property determines how the
remaining free space (if any) in the main direction is allocated.
- `Flexible`: Mark this child as being flexible with the given `flex` ratio.
There is also a stacking layout model:
- `Stack`: Layout a list of child widgets on top of each other from back to
front. Each child of a `Stack` widget is either *positioned* or
*non-positioned*. The stack sizes itself to the contain all the
non-positioned children, which are located at the top-left corner of the
stack. The *positioned* children are then located relative to the stack
according to their `top`, `right`, `bottom`, and `left` properties.
- `Positioned`: Mark this child as *positioned*. If the `top` property is
non-null, the top edge of this child will be positioned `top` layout units
from the top of the stack widget. The `right`, `bottom`, and `right`
properties work analogously. Note that if the both the `top` and `bottom`
properties are non-null, then the child will be forced to have exactly the
height required to satisfy both constraints. Similarly, setting the
`right` and `left` properties to non-null values will force the child to
have a particular width.
Positioning and sizing
----------------------
- `Padding` Surround the child with empty space on the top, right, bottom, and
left according to the given `EdgeDims`.
- `Center` Center the child widget within the space occupied by this widget.
- `SizedBox` Force the child widget to have a particular `width` or `height`
(or both).
- `ConstrainedBox` Apply the given `BoxConstraints` to the child widget as
additional constraints during layout. This widget is a generalization of
`SizedBox`.
- `AspectRatio` Force the child widget's width and height to have the given
`aspectRatio`, expressed as a ratio of width to height.
- `Transform` Apply the given matrix to the child before painting the child.
This widget is useful for adjusting the visual size and position of a widget
without affecting layout.
- `Viewport` Layout the child widget at a larger size than fits in this widget
and render only the portion of the child that is visually contained by this
widget. When rendering, add `offset` to the child's vertical position to
control which part of the child is visible through the viewport.
TODO(abarth): Add support for horizontal viewporting.
- `SizeObserver` Whenever the child widget changes size, this widget calls the
`callback`. Warning: If the callback changes state that affects the size of
the child widget, it is possible to create an infinite loop.
- `ShrinkWrapWidth` Force the child widget to have a width equal to its max
intrinsic width. TODO(abarth): Add a link to the definition of max intrinsic
width. Optionally, round up the child widget's width or height (or both) to
a multiple of `stepWidth` or `stepHeight`, respectively. Note: The layout
performed by `ShrinkWrapWidth` is relatively expensive and should be used
sparingly.
- `Baseline` If the child widget has a `TextBaseline` of the given
`baselineType`, position the child such that its baseline is at `baseline`
layout units from the top of this widget.
Painting effects
----------------
- `Opacity` Adjusts the opacity of the child widget, making the child partially
transparent. The amount of transparency is controlled by `opacity`, with 0.0
0.0 is fully transparent and 1.0 is fully opaque.
- `ClipRect` Apply a rectangular clip to the child widget. The dimensions of
the clip match the dimensions of the child.
- `ClipRRect` Apply a rounded-rect clip the child widget. The bounds of the
clip match the bounds of the child widget with `xRadius` and `yRadius`
controlling the x and y radius of the rounded corner, respectively.
- `ClipOval` Apply an oval clip to the child widget. The oval will be
axis-aligned, with its horizontal and vertical bounds matching the bounds of
the child widget.
- `DecoratedBox` Draw the given `BoxDecoration` surrounding the child widget.
- `ColorFilter` Applies a color filter to the child widget, for example to
tint the child a given color.
- `CustomPaint` Calls `callback` during the paint phase with the current
`Canvas` and `Size`. The widget occupies the region of the canvas starting at
the origin (i.e., `x = 0.0` and `y = 0.0`) and of the given size (i.e.,
`x = size.width` and `y = size.height`).
Use the `token` to invalidate the painting. As long as the any new `token`
is `operator==` the current `token`, the `CustomPaint` widget is permitted
to retain a recording of the painting produced by the previous `callback`
call.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment