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
2e194d5b
Commit
2e194d5b
authored
Apr 26, 2017
by
Ian Hickson
Committed by
GitHub
Apr 26, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow ChangeNotifiers to be CustomPainters (#9584)
Fixes
https://github.com/flutter/flutter/issues/7648
parent
4e7a38b1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
50 additions
and
38 deletions
+50
-38
scrollbar.dart
packages/flutter/lib/src/material/scrollbar.dart
+11
-20
proxy_box.dart
packages/flutter/lib/src/rendering/proxy_box.dart
+39
-18
No files found.
packages/flutter/lib/src/material/scrollbar.dart
View file @
2e194d5b
...
...
@@ -43,25 +43,25 @@ class Scrollbar extends StatefulWidget {
}
class
_ScrollbarState
extends
State
<
Scrollbar
>
with
TickerProviderStateMixin
{
_Scrollbar
Controller
_controll
er
;
_Scrollbar
Painter
_paint
er
;
@override
void
didChangeDependencies
()
{
super
.
didChangeDependencies
();
_
controller
??=
new
_ScrollbarControll
er
(
this
);
_
controll
er
.
color
=
Theme
.
of
(
context
).
highlightColor
;
_
painter
??=
new
_ScrollbarPaint
er
(
this
);
_
paint
er
.
color
=
Theme
.
of
(
context
).
highlightColor
;
}
bool
_handleScrollNotification
(
ScrollNotification
notification
)
{
if
(
notification
is
ScrollUpdateNotification
||
notification
is
OverscrollNotification
)
_
controll
er
.
update
(
notification
.
metrics
,
notification
.
metrics
.
axisDirection
);
_
paint
er
.
update
(
notification
.
metrics
,
notification
.
metrics
.
axisDirection
);
return
false
;
}
@override
void
dispose
()
{
_
controll
er
.
dispose
();
_
paint
er
.
dispose
();
super
.
dispose
();
}
...
...
@@ -73,7 +73,7 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin {
// boundaries when the scroll bars are invisible.
child:
new
RepaintBoundary
(
child:
new
CustomPaint
(
foregroundPainter:
new
_ScrollbarPainter
(
_controller
)
,
foregroundPainter:
_painter
,
child:
new
RepaintBoundary
(
child:
widget
.
child
,
),
...
...
@@ -83,8 +83,8 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin {
}
}
class
_Scrollbar
Controller
extends
ChangeNotifi
er
{
_Scrollbar
Controll
er
(
TickerProvider
vsync
)
{
class
_Scrollbar
Painter
extends
ChangeNotifier
implements
CustomPaint
er
{
_Scrollbar
Paint
er
(
TickerProvider
vsync
)
{
assert
(
vsync
!=
null
);
_fadeController
=
new
AnimationController
(
duration:
_kThumbFadeDuration
,
vsync:
vsync
);
_opacity
=
new
CurvedAnimation
(
parent:
_fadeController
,
curve:
Curves
.
fastOutSlowIn
)
...
...
@@ -161,6 +161,7 @@ class _ScrollbarController extends ChangeNotifier {
painter
(
canvas
,
size
,
thumbOffset
,
thumbExtent
);
}
@override
void
paint
(
Canvas
canvas
,
Size
size
)
{
if
(
_lastAxisDirection
==
null
||
_lastMetrics
==
null
||
_opacity
.
value
==
0.0
)
return
;
...
...
@@ -179,20 +180,10 @@ class _ScrollbarController extends ChangeNotifier {
break
;
}
}
}
class
_ScrollbarPainter
extends
CustomPainter
{
_ScrollbarPainter
(
this
.
controller
)
:
super
(
repaint:
controller
);
final
_ScrollbarController
controller
;
@override
void
paint
(
Canvas
canvas
,
Size
size
)
{
controller
.
paint
(
canvas
,
size
);
}
bool
hitTest
(
Offset
position
)
=>
null
;
@override
bool
shouldRepaint
(
_ScrollbarPainter
oldDelegate
)
{
return
oldDelegate
.
controller
!=
controller
;
}
bool
shouldRepaint
(
_ScrollbarPainter
oldDelegate
)
=>
false
;
}
packages/flutter/lib/src/rendering/proxy_box.dart
View file @
2e194d5b
...
...
@@ -1788,10 +1788,10 @@ class RenderFractionalTranslation extends RenderProxyBox {
/// The interface used by [CustomPaint] (in the widgets library) and
/// [RenderCustomPaint] (in the rendering library).
///
/// To implement a custom painter,
subclass this interface to define your custom
///
paint delegate. [CustomPaint] subclasses must implement the [paint] and
///
[shouldRepaint] methods, and may optionally also implement the [hitTest]
/// method.
/// To implement a custom painter,
either subclass or implement this interface
///
to define your custom paint delegate. [CustomPaint] subclasses must
///
implement the [paint] and [shouldRepaint] methods, and may optionally also
///
implement the [hitTest]
method.
///
/// The [paint] method is called whenever the custom object needs to be repainted.
///
...
...
@@ -1799,21 +1799,42 @@ class RenderFractionalTranslation extends RenderProxyBox {
/// is provided, to check if the new instance actually represents different
/// information.
///
/// The most efficient way to trigger a repaint is to supply a repaint argument
/// to the constructor of the [CustomPainter]. The custom object will listen to
/// this animation and repaint whenever the animation ticks, avoiding both the
/// build and layout phases of the pipeline.
/// The most efficient way to trigger a repaint is to either extend this class
/// and supply a `repaint` argument to the constructor of the [CustomPainter],
/// where that object notifies its listeners when it is time to repaint, or to
/// extend [Listenable] (e.g. via [ChangeNotifier]) and implement
/// [CustomPainter], so that the object itself provides the notifications
/// directly. In either case, the [CustomPaint] widget or [RenderCustomPaint]
/// render object will listen to the [Listenable] and repaint whenever the
/// animation ticks, avoiding both the build and layout phases of the pipeline.
///
/// The [hitTest] method is called when the user interacts with the underlying
/// render object, to determine if the user hit the object or missed it.
abstract
class
CustomPainter
{
abstract
class
CustomPainter
extends
Listenable
{
/// Creates a custom painter.
///
/// The painter will repaint whenever
[repaint]
notifies its listeners.
/// The painter will repaint whenever
`repaint`
notifies its listeners.
const
CustomPainter
({
Listenable
repaint
})
:
_repaint
=
repaint
;
final
Listenable
_repaint
;
/// Register a closure to be notified when it is time to repaint.
///
/// The [CustomPainter] implementation merely forwards to the same method on
/// the [Listenable] provided to the constructor in the `repaint` argument, if
/// it was not null.
@override
void
addListener
(
VoidCallback
listener
)
=>
_repaint
?.
addListener
(
listener
);
/// Remove a previously registered closure from the list of closures that the
/// object notifies when it is time to repaint.
///
/// The [CustomPainter] implementation merely forwards to the same method on
/// the [Listenable] provided to the constructor in the `repaint` argument, if
/// it was not null.
@override
void
removeListener
(
VoidCallback
listener
)
=>
_repaint
?.
removeListener
(
listener
);
/// Called whenever the object needs to paint. The given [Canvas] has its
/// coordinate space configured such that the origin is at the top left of the
/// box. The area of the box is the size of the [size] argument.
...
...
@@ -1884,7 +1905,7 @@ abstract class CustomPainter {
bool
hitTest
(
Offset
position
)
=>
null
;
@override
String
toString
()
=>
'
$runtimeType
#
$hashCode
'
;
String
toString
()
=>
'
$runtimeType
#
$hashCode
(
${ _repaint?.toString() ?? "" }
)
'
;
}
/// Provides a canvas on which to draw during the paint phase.
...
...
@@ -1898,7 +1919,7 @@ abstract class CustomPainter {
/// those bounds, there might be insufficient memory allocated to rasterize the
/// painting commands and the resulting behavior is undefined.)
///
/// Painters are implemented by subclassing [CustomPainter].
/// Painters are implemented by subclassing
or implementing
[CustomPainter].
///
/// Because custom paint calls its painters during paint, you cannot mark the
/// tree as needing a new layout during the callback (the layout for this frame
...
...
@@ -1986,8 +2007,8 @@ class RenderCustomPaint extends RenderProxyBox {
markNeedsPaint
();
}
if
(
attached
)
{
oldPainter
?.
_repaint
?.
removeListener
(
markNeedsPaint
);
newPainter
?.
_repaint
?.
addListener
(
markNeedsPaint
);
oldPainter
?.
removeListener
(
markNeedsPaint
);
newPainter
?.
addListener
(
markNeedsPaint
);
}
}
...
...
@@ -2011,14 +2032,14 @@ class RenderCustomPaint extends RenderProxyBox {
@override
void
attach
(
PipelineOwner
owner
)
{
super
.
attach
(
owner
);
_painter
?.
_repaint
?.
addListener
(
markNeedsPaint
);
_foregroundPainter
?.
_repaint
?.
addListener
(
markNeedsPaint
);
_painter
?.
addListener
(
markNeedsPaint
);
_foregroundPainter
?.
addListener
(
markNeedsPaint
);
}
@override
void
detach
()
{
_painter
?.
_repaint
?.
removeListener
(
markNeedsPaint
);
_foregroundPainter
?.
_repaint
?.
removeListener
(
markNeedsPaint
);
_painter
?.
removeListener
(
markNeedsPaint
);
_foregroundPainter
?.
removeListener
(
markNeedsPaint
);
super
.
detach
();
}
...
...
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