Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
576b3aa2
Commit
576b3aa2
authored
Feb 14, 2016
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1864 from abarth/examples_comments
Adds documentation to the layering examples
parents
981a7f37
025c43de
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
254 additions
and
73 deletions
+254
-73
canvas.dart
examples/layers/raw/canvas.dart
+24
-2
hello_world.dart
examples/layers/raw/hello_world.dart
+69
-12
spinning_square.dart
examples/layers/raw/spinning_square.dart
+48
-37
text.dart
examples/layers/raw/text.dart
+29
-6
autolayout.dart
examples/layers/rendering/autolayout.dart
+2
-1
custom_coordinate_systems.dart
examples/layers/rendering/custom_coordinate_systems.dart
+3
-0
flex_layout.dart
examples/layers/rendering/flex_layout.dart
+3
-0
hello_world.dart
examples/layers/rendering/hello_world.dart
+8
-0
spinning_square.dart
examples/layers/rendering/spinning_square.dart
+24
-8
touch_input.dart
examples/layers/rendering/touch_input.dart
+44
-7
No files found.
examples/layers/raw/canvas.dart
View file @
576b3aa2
...
...
@@ -2,19 +2,32 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This example shows how to use the ui.Canvas interface to draw various shapes
// with gradients and transforms.
import
'dart:ui'
as
ui
;
import
'dart:math'
as
math
;
import
'dart:typed_data'
;
ui
.
Picture
paint
(
ui
.
Rect
paintBounds
)
{
// First we create a PictureRecorder to record the commands we're going to
// feed in the canvas. The PictureRecorder will eventually produce a Picture,
// which is an immutable record of those commands.
ui
.
PictureRecorder
recorder
=
new
ui
.
PictureRecorder
();
// Next, we create a canvas from the recorder. The canvas is an interface
// which can receive drawing commands. The canvas interface is modeled after
// the SkCanvas interface from Skia. The paintBounds establishes a "cull rect"
// for the canvas, which lets the implementation discard any commands that
// are entirely outside this rectangle.
ui
.
Canvas
canvas
=
new
ui
.
Canvas
(
recorder
,
paintBounds
);
ui
.
Size
size
=
paintBounds
.
size
;
ui
.
Paint
paint
=
new
ui
.
Paint
();
canvas
.
drawPaint
(
new
ui
.
Paint
()..
color
=
const
ui
.
Color
(
0xFFFFFFFF
));
ui
.
Size
size
=
paintBounds
.
size
;
ui
.
Point
mid
=
size
.
center
(
ui
.
Point
.
origin
);
double
radius
=
size
.
shortestSide
/
2.0
;
canvas
.
drawPaint
(
new
ui
.
Paint
()..
color
=
const
ui
.
Color
(
0xFFFFFFFF
));
canvas
.
save
();
canvas
.
translate
(-
mid
.
x
/
2.0
,
ui
.
window
.
size
.
height
*
2.0
);
...
...
@@ -46,6 +59,11 @@ ui.Picture paint(ui.Rect paintBounds) {
canvas
.
restore
();
canvas
.
translate
(
0.0
,
50.0
);
// A DrawLooper is a powerful painting primitive that lets you apply several
// blending and filtering passes over a sequence of commands "in a loop". For
// example, the looper below draws the circle tree times, once with a blur,
// then with a gradient blend, and finally with just an offset.
ui
.
LayerDrawLooperBuilder
builder
=
new
ui
.
LayerDrawLooperBuilder
()
..
addLayerOnTop
(
new
ui
.
DrawLooperLayerInfo
()
...
...
@@ -90,6 +108,10 @@ ui.Picture paint(ui.Rect paintBounds) {
paint
.
drawLooper
=
builder
.
build
();
canvas
.
drawCircle
(
ui
.
Point
.
origin
,
radius
,
paint
);
// When we're done issuing painting commands, we end the recording an receive
// a Picture, which is an immutable record of the commands we've issued. You
// can draw a Picture into another canvas or include it as part of a
// composited scene.
return
recorder
.
endRecording
();
}
...
...
examples/layers/raw/hello_world.dart
View file @
576b3aa2
...
...
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This example shows how to put some pixels on the screen using the raw
// interface to the engine.
import
'dart:ui'
as
ui
;
import
'dart:typed_data'
;
...
...
@@ -12,18 +15,38 @@ import 'package:sky_services/pointer/pointer.mojom.dart';
ui
.
Color
color
;
ui
.
Picture
paint
(
ui
.
Rect
paintBounds
)
{
// First we create a PictureRecorder to record the commands we're going to
// feed in the canvas. The PictureRecorder will eventually produce a Picture,
// which is an immutable record of those commands.
ui
.
PictureRecorder
recorder
=
new
ui
.
PictureRecorder
();
// Next, we create a canvas from the recorder. The canvas is an interface
// which can receive drawing commands. The canvas interface is modeled after
// the SkCanvas interface from Skia. The paintBounds establishes a "cull rect"
// for the canvas, which lets the implementation discard any commands that
// are entirely outside this rectangle.
ui
.
Canvas
canvas
=
new
ui
.
Canvas
(
recorder
,
paintBounds
);
ui
.
Size
size
=
paintBounds
.
size
;
double
radius
=
size
.
shortestSide
*
0.45
;
ui
.
Paint
paint
=
new
ui
.
Paint
()..
color
=
color
;
canvas
.
drawCircle
(
size
.
center
(
ui
.
Point
.
origin
),
radius
,
paint
);
// The commands draw a circle in the center of the screen.
ui
.
Size
size
=
paintBounds
.
size
;
canvas
.
drawCircle
(
size
.
center
(
ui
.
Point
.
origin
),
size
.
shortestSide
*
0.45
,
new
ui
.
Paint
()..
color
=
color
);
// When we're done issuing painting commands, we end the recording an receive
// a Picture, which is an immutable record of the commands we've issued. You
// can draw a Picture into another canvas or include it as part of a
// composited scene.
return
recorder
.
endRecording
();
}
ui
.
Scene
composite
(
ui
.
Picture
picture
,
ui
.
Rect
paintBounds
)
{
// The device pixel ratio gives an approximate ratio of the size of pixels on
// the device's screen to "normal" sized pixels. We commonly work in logical
// pixels, which are then scalled by the device pixel ratio before being drawn
// on the screen.
final
double
devicePixelRatio
=
ui
.
window
.
devicePixelRatio
;
ui
.
Rect
sceneBounds
=
new
ui
.
Rect
.
fromLTWH
(
0.0
,
...
...
@@ -31,49 +54,83 @@ ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) {
ui
.
window
.
size
.
width
*
devicePixelRatio
,
ui
.
window
.
size
.
height
*
devicePixelRatio
);
// This transform scales the x and y coordinates by the devicePixelRatio.
Float64List
deviceTransform
=
new
Float64List
(
16
)
..[
0
]
=
devicePixelRatio
..[
5
]
=
devicePixelRatio
..[
10
]
=
1.0
..[
15
]
=
1.0
;
// We build a very simple scene graph with two nodes. The root node is a
// transform that scale its children by the device pixel ratio. This transform
// lets us paint in "logical" pixels which are converted to device pixels by
// this scaling operation.
ui
.
SceneBuilder
sceneBuilder
=
new
ui
.
SceneBuilder
(
sceneBounds
)
..
pushTransform
(
deviceTransform
)
..
addPicture
(
ui
.
Offset
.
zero
,
picture
)
..
pop
();
// When we're done recording the scene, we call build() to obtain an immutable
// record of the scene we've recorded.
return
sceneBuilder
.
build
();
}
void
beginFrame
(
Duration
timeStamp
)
{
ui
.
Rect
paintBounds
=
ui
.
Point
.
origin
&
ui
.
window
.
size
;
// First, record a picture with our painting commands.
ui
.
Picture
picture
=
paint
(
paintBounds
);
// Second, include that picture in a scene graph.
ui
.
Scene
scene
=
composite
(
picture
,
paintBounds
);
// Third, instruct the engine to render that scene graph.
ui
.
window
.
render
(
scene
);
}
void
handlePopRoute
(
)
{
print
(
'Pressed back button.'
);
}
// Pointer input arrives as an array of bytes. The format for the data is
// defined by pointer.mojom, which generates serializes and parsers for a
// number of languages, including Dart, C++, Java, and Go.
void
handlePointerPacket
(
ByteData
serializedPacket
)
{
// We wrap the byte data up into a Mojo Message object, which we then
// deserialize according to the mojom definition.
bindings
.
Message
message
=
new
bindings
.
Message
(
serializedPacket
,
<
core
.
MojoHandle
>[],
serializedPacket
.
lengthInBytes
,
0
);
PointerPacket
packet
=
PointerPacket
.
deserialize
(
message
);
// The deserialized pointer packet contains a number of pointer movements,
// which we iterate through and process.
for
(
Pointer
pointer
in
packet
.
pointers
)
{
if
(
pointer
.
type
==
PointerType
.
down
)
{
color
=
new
ui
.
Color
.
fromARGB
(
255
,
0
,
0
,
255
);
// If the pointer went down, we change the color of the circle to blue.
color
=
const
ui
.
Color
(
0xFF0000FF
);
// Rather than calling paint() synchronously, we ask the engine to
// schedule a frame. The engine will call onBeginFrame when it is actually
// time to produce the frame.
ui
.
window
.
scheduleFrame
();
}
else
if
(
pointer
.
type
==
PointerType
.
up
)
{
color
=
new
ui
.
Color
.
fromARGB
(
255
,
0
,
255
,
0
);
// Similarly, if the pointer went up, we change the color of the circle to
// green and schedule a frame. It's harmless to call scheduleFrame many
// times because the engine will ignore redundant requests up until the
// point where the engine calls onBeginFrame, which signals the boundary
// between one frame and another.
color
=
const
ui
.
Color
(
0xFF00FF00
);
ui
.
window
.
scheduleFrame
();
}
}
}
// This function is the primary entry point to your application. The engine
// calls main() as soon as it has loaded your code.
void
main
(
)
{
// Print statements go either go to stdout or to the system log, as
// appropriate for the operating system.
print
(
'Hello, world'
);
color
=
new
ui
.
Color
.
fromARGB
(
255
,
0
,
255
,
0
);
color
=
const
ui
.
Color
(
0xFF00FF00
);
// The engine calls onBeginFrame whenever it wants us to produce a frame.
ui
.
window
.
onBeginFrame
=
beginFrame
;
ui
.
window
.
onPopRoute
=
handlePopRoute
;
// The engine calls onPointerPacket whenever it had updated information about
// the pointers directed at our app.
ui
.
window
.
onPointerPacket
=
handlePointerPacket
;
// Here we kick off the whole process by asking the engine to schedule a new
// frame. The engine will eventually call onBeginFrame when it is time for us
// to actually produce the frame.
ui
.
window
.
scheduleFrame
();
}
examples/layers/raw/spinning_square.dart
View file @
576b3aa2
...
...
@@ -2,30 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:developer'
;
// This example shows how to perform a simple animation using the raw interface
// to the engine.
import
'dart:math'
as
math
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
Duration
timeBase
=
null
;
void
beginFrame
(
Duration
timeStamp
)
{
Timeline
.
timeSync
(
'beginFrame'
,
()
{
if
(
timeBase
==
null
)
timeBase
=
timeStamp
;
double
delta
=
(
timeStamp
-
timeBase
).
inMicroseconds
/
Duration
.
MICROSECONDS_PER_MILLISECOND
;
// The timeStamp argument to beginFrame indicates the timing information we
// should use to clock our animations. It's important to use timeStamp rather
// than reading the system time because we want all the parts of the system to
// coordinate the timings of their animations. If each component read the
// system clock independently, the animations that we processed later would be
// slightly ahead of the animations we processed earlier.
// PAINT
// paint
ui
.
Rect
paintBounds
=
ui
.
Point
.
origin
&
ui
.
window
.
size
;
ui
.
PictureRecorder
recorder
=
new
ui
.
PictureRecorder
();
ui
.
Canvas
canvas
=
new
ui
.
Canvas
(
recorder
,
paintBounds
);
canvas
.
translate
(
paintBounds
.
width
/
2.0
,
paintBounds
.
height
/
2.0
);
canvas
.
rotate
(
math
.
PI
*
delta
/
1800
);
// Here we determine the rotation according to the timeStamp given to us by
// the engine.
double
t
=
timeStamp
.
inMicroseconds
/
Duration
.
MICROSECONDS_PER_MILLISECOND
/
1800.0
;
canvas
.
rotate
(
math
.
PI
*
(
t
%
1.0
));
canvas
.
drawRect
(
new
ui
.
Rect
.
fromLTRB
(-
100.0
,
-
100.0
,
100.0
,
100.0
),
new
ui
.
Paint
()..
color
=
const
ui
.
Color
.
fromARGB
(
255
,
0
,
255
,
0
));
ui
.
Picture
picture
=
recorder
.
endRecording
();
// composite
// COMPOSITE
final
double
devicePixelRatio
=
ui
.
window
.
devicePixelRatio
;
ui
.
Rect
sceneBounds
=
new
ui
.
Rect
.
fromLTWH
(
0.0
,
...
...
@@ -43,8 +52,10 @@ void beginFrame(Duration timeStamp) {
..
addPicture
(
ui
.
Offset
.
zero
,
picture
)
..
pop
();
ui
.
window
.
render
(
sceneBuilder
.
build
());
});
// After rendering the current frame of the animation, we ask the engine to
// schedule another frame. The engine will call beginFrame again when its time
// to produce the next frame.
ui
.
window
.
scheduleFrame
();
}
...
...
examples/layers/raw/text.dart
View file @
576b3aa2
...
...
@@ -2,9 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This example shows how to draw some bi-directional text using the raw
// interface to the engine.
import
'dart:ui'
as
ui
;
import
'dart:typed_data'
;
// A paragraph represents a rectangular region that contains some text.
ui
.
Paragraph
paragraph
;
ui
.
Picture
paint
(
ui
.
Rect
paintBounds
)
{
...
...
@@ -15,8 +19,9 @@ ui.Picture paint(ui.Rect paintBounds) {
canvas
.
drawRect
(
new
ui
.
Rect
.
fromLTRB
(-
100.0
,
-
100.0
,
100.0
,
100.0
),
new
ui
.
Paint
()..
color
=
const
ui
.
Color
.
fromARGB
(
255
,
0
,
255
,
0
));
canvas
.
translate
(
paragraph
.
maxWidth
/
-
2.0
,
(
paragraph
.
maxWidth
/
2.0
)
-
125
);
paragraph
.
paint
(
canvas
,
ui
.
Offset
.
zero
);
// The paint method of Pargraph draws the contents of the paragraph unto the
// given canvas.
paragraph
.
paint
(
canvas
,
new
ui
.
Offset
(
paragraph
.
maxWidth
/
-
2.0
,
(
paragraph
.
maxWidth
/
2.0
)
-
125
));
return
recorder
.
endRecording
();
}
...
...
@@ -49,19 +54,37 @@ void beginFrame(Duration timeStamp) {
}
void
main
(
)
{
// To create a paragraph of text, we use ParagraphBuilder.
ui
.
ParagraphBuilder
builder
=
new
ui
.
ParagraphBuilder
()
// We first push a style that turns the text blue.
..
pushStyle
(
new
ui
.
TextStyle
(
color:
const
ui
.
Color
(
0xFF0000FF
)))
..
addText
(
"Hello, "
)
..
addText
(
'Hello, '
)
// The next run of text will be bold.
..
pushStyle
(
new
ui
.
TextStyle
(
fontWeight:
ui
.
FontWeight
.
bold
))
..
addText
(
"world. "
)
..
addText
(
'world. '
)
// The pop() command signals the end of the bold styling.
..
pop
()
..
addText
(
"هذا هو قليلا طويلة من النص الذي يجب التفاف ."
)
// We add text to the paragraph in logical order. The paragraph object
// understands bi-directional text and will compute the visual ordering
// during layout.
..
addText
(
'هذا هو قليلا طويلة من النص الذي يجب التفاف .'
)
// The second pop() removes the blue color.
..
pop
()
..
addText
(
" و أكثر قليلا لجعله أطول. "
);
// We can add more text with the default styling.
..
addText
(
' و أكثر قليلا لجعله أطول. '
)
..
addText
(
'สวัสดี'
);
// When we're done adding styles and text, we build the Paragraph object, at
// which time we can apply styling that affects the entire paragraph, such as
// left, right, or center alignment. Once built, the contents of the paragraph
// cannot be altered, but sizing and positioning information can be updated.
paragraph
=
builder
.
build
(
new
ui
.
ParagraphStyle
())
// Next, we supply a maximum width that the text is permitted to occupy.
..
maxWidth
=
180.0
// ... and we ask the paragraph to the visual position of each its glyphs as
// well as its overall size, subject to its sizing constraints.
..
layout
();
// Finally, we register our beginFrame callback and kick off the first frame.
ui
.
window
.
onBeginFrame
=
beginFrame
;
ui
.
window
.
scheduleFrame
();
}
examples/layers/rendering/autolayout.dart
View file @
576b3aa2
...
...
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:ui'
;
// This example shows how to use the Cassowary autolayout system directly in the
// underlying render tree.
import
'package:cassowary/cassowary.dart'
as
al
;
import
'package:flutter/rendering.dart'
;
...
...
examples/layers/rendering/custom_coordinate_systems.dart
View file @
576b3aa2
...
...
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This example shows how to build a render tree with a non-cartesian coordinate
// system. Most of the guts of this examples are in src/sector_layout.dart.
import
'package:flutter/rendering.dart'
;
import
'src/sector_layout.dart'
;
...
...
examples/layers/rendering/flex_layout.dart
View file @
576b3aa2
...
...
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This example shows how to use flex layout directly in the underlying render
// tree.
import
'package:flutter/rendering.dart'
;
import
'src/solid_color_box.dart'
;
...
...
examples/layers/rendering/hello_world.dart
View file @
576b3aa2
...
...
@@ -2,12 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This example shows how to show the text 'Hello, world.' using the underlying
// render tree.
import
'package:flutter/rendering.dart'
;
void
main
(
)
{
// We use RenderingFlutterBinding to attach the render tree to the window.
new
RenderingFlutterBinding
(
// The root of our render tree is a RenderPositionedBox, which centers its
// child both vertically and horizontally.
root:
new
RenderPositionedBox
(
alignment:
const
FractionalOffset
(
0.5
,
0.5
),
// We use a RenderParagraph to display the text "Hello, world." without
// any explicit styling.
child:
new
RenderParagraph
(
new
PlainTextSpan
(
'Hello, world.'
))
)
);
...
...
examples/layers/rendering/spinning_square.dart
View file @
576b3aa2
...
...
@@ -2,43 +2,59 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This example shows how to perform a simple animation using the underlying
// render tree.
import
'dart:math'
as
math
;
import
'package:flutter/animation.dart'
;
import
'package:flutter/rendering.dart'
;
void
main
(
)
{
//
A green box..
.
//
We first create a render object that represents a green box
.
RenderBox
green
=
new
RenderDecoratedBox
(
decoration:
const
BoxDecoration
(
backgroundColor:
const
Color
(
0xFF00FF00
))
);
// of a certain size...
// Second, we wrap that green box in a render object that forces the green box
// to have a specific size.
RenderBox
square
=
new
RenderConstrainedBox
(
additionalConstraints:
const
BoxConstraints
.
tightFor
(
width:
200.0
,
height:
200.0
),
child:
green
);
// With a given rotation (starts off as the identity transform)...
// Third, we wrap the sized green square in a render object that applies rotation
// transform before painting its child. Each frame of the animation, we'll
// update the transform of this render object to cause the green square to
// spin.
RenderTransform
spin
=
new
RenderTransform
(
transform:
new
Matrix4
.
identity
(),
alignment:
const
FractionalOffset
(
0.5
,
0.5
),
child:
square
);
//
centered
...
//
Finally, we center the spinning green square
...
RenderBox
root
=
new
RenderPositionedBox
(
alignment:
const
FractionalOffset
(
0.5
,
0.5
),
child:
spin
);
//
on the screen
.
//
and attach it to the window
.
new
RenderingFlutterBinding
(
root:
root
);
// A repeating animation every 1800 milliseconds...
// To make the square spin, we use an animation that repeats every 1800
// milliseconds.
AnimationController
animation
=
new
AnimationController
(
duration:
const
Duration
(
milliseconds:
1800
)
)..
repeat
();
// From 0.0 to math.PI.
// The animation will produce a value between 0.0 and 1.0 each frame, but we
// want to rotate the square using a value between 0.0 and math.PI. To change
// the range of the animation, we use a Tween.
Tween
<
double
>
tween
=
new
Tween
<
double
>(
begin:
0.0
,
end:
math
.
PI
);
// We add a listener to the animation, which will be called every time the
// animation ticks.
animation
.
addListener
(()
{
// Each frame of the animation, set the rotation of the square.
// This code runs every tick of the animation and sets a new transform on
// the "spin" render object by evaluating the tween on the current value
// of the animation. Setting this value will mark a number of dirty bits
// inside the render tree, which cause the render tree to repaint with the
// new transform value this frame.
spin
.
transform
=
new
Matrix4
.
rotationZ
(
tween
.
evaluate
(
animation
));
});
}
examples/layers/rendering/touch_input.dart
View file @
576b3aa2
...
...
@@ -2,7 +2,10 @@
// 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'
;
// This example shows how to use process input events in the underlying render
// tree.
import
'package:flutter/material.dart'
;
// Imported just for its color palette.
import
'package:flutter/rendering.dart'
;
// Material design colors. :p
...
...
@@ -34,12 +37,23 @@ class Dot {
}
/// A render object that draws dots under each pointer.
class
RenderDots
extends
Render
Constrained
Box
{
RenderDots
()
:
super
(
additionalConstraints:
const
BoxConstraints
.
expand
())
;
class
RenderDots
extends
RenderBox
{
RenderDots
();
/// State to remember which dots to paint.
final
Map
<
int
,
Dot
>
_dots
=
<
int
,
Dot
>{};
/// Indicates that the size of this render object depends only on the
/// layout constraints provided by the parent.
bool
get
sizedByParent
=>
true
;
/// By selecting the biggest value permitted by the incomming constraints
/// during layout, this function makes this render object as large as
/// possible (i.e., fills the entire screen).
void
performResize
()
{
size
=
constraints
.
biggest
;
}
/// Makes this render object hittable so that it receives pointer events.
bool
hitTestSelf
(
Point
position
)
=>
true
;
...
...
@@ -49,6 +63,10 @@ class RenderDots extends RenderConstrainedBox {
if
(
event
is
PointerDownEvent
)
{
Color
color
=
_kColors
[
event
.
pointer
.
remainder
(
_kColors
.
length
)];
_dots
[
event
.
pointer
]
=
new
Dot
(
color:
color
)..
update
(
event
);
// We call markNeedsPaint to indicate that our painting commands have
// changed and that paint needs to be called before displaying a new frame
// to the user. It's harmless to call markNeedsPaint multiple times
// because the render tree will ignore redundant calls.
markNeedsPaint
();
}
else
if
(
event
is
PointerUpEvent
||
event
is
PointerCancelEvent
)
{
_dots
.
remove
(
event
.
pointer
);
...
...
@@ -62,31 +80,50 @@ class RenderDots extends RenderConstrainedBox {
/// Issues new painting commands.
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
final
Canvas
canvas
=
context
.
canvas
;
// The "size" property indicates the size of that this render box was
// alotted during layout. Here we paint our bounds white. Notice that we're
// located at "offset" from the origin of the canvas' coordinate system.
// Passing offset during the render tree's paint walk is an optimization to
// avoid having to change the origin of the canvas's coordinate system too
// often.
canvas
.
drawRect
(
offset
&
size
,
new
Paint
()..
color
=
const
Color
(
0xFFFFFFFF
));
// We iterate through our model and paint each dot.
for
(
Dot
dot
in
_dots
.
values
)
dot
.
paint
(
canvas
,
offset
);
super
.
paint
(
context
,
offset
);
}
}
void
main
(
)
{
// Create some styled text to tell the user to interact with the app.
RenderParagraph
paragraph
=
new
RenderParagraph
(
new
StyledTextSpan
(
new
TextStyle
(
color:
Colors
.
black87
),
[
new
PlainTextSpan
(
"Touch me!"
)
]
<
TextSpan
>
[
new
PlainTextSpan
(
"Touch me!"
)
]
)
);
// A stack is a render object that layers its children on top of each other.
// The bottom later is our RenderDots object, and on top of that we show the
// text.
RenderStack
stack
=
new
RenderStack
(
children:
<
RenderBox
>[
new
RenderDots
(),
paragraph
,
]
);
// Prevent the RenderParagraph from filling the whole screen so
// that it doesn't eat events.
// The "parentData" field of a render object is controlled by the render
// object's parent render object. Now that we've added the paragraph as a
// child of the RenderStack, the paragraph's parentData field has been
// populated with a StackParentData, which we can use to provide input to the
// stack's layout algorithm.
//
// We use the StackParentData of the paragraph to position the text in the top
// left corner of the screen.
final
StackParentData
paragraphParentData
=
paragraph
.
parentData
;
paragraphParentData
..
top
=
40.0
..
left
=
20.0
;
// Finally, we attach the render tree we've built to the screen.
new
RenderingFlutterBinding
(
root:
stack
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment