Kate Lovett 9d96df2364
Modernize framework lints (#179089)
WIP

Commits separated as follows:
- Update lints in analysis_options files
- Run `dart fix --apply`
- Clean up leftover analysis issues 
- Run `dart format .` in the right places.

Local analysis and testing passes. Checking CI now.

Part of https://github.com/flutter/flutter/issues/178827
- Adoption of flutter_lints in examples/api coming in a separate change
(cc @loic-sharma)

## Pre-launch Checklist

- [ ] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [ ] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [ ] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [ ] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
2025-11-26 01:10:39 +00:00

137 lines
4.7 KiB
Dart

// Copyright 2014 The Flutter Authors. All rights reserved.
// 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 process input events in the underlying render
// tree.
import 'package:flutter/material.dart'; // Imported just for its color palette.
import 'package:flutter/rendering.dart';
import 'src/binding.dart';
// Material design colors. :p
List<Color> _kColors = <Color>[
Colors.teal,
Colors.amber,
Colors.purple,
Colors.lightBlue,
Colors.deepPurple,
Colors.lime,
];
/// A simple model object for a dot that reacts to pointer pressure.
class Dot {
Dot({required Color color}) : _paint = Paint()..color = color;
final Paint _paint;
Offset position = Offset.zero;
double radius = 0.0;
void update(PointerEvent event) {
position = event.position;
radius = 5 + (95 * event.pressure);
}
void paint(Canvas canvas, Offset offset) {
canvas.drawCircle(position + offset, radius, _paint);
}
}
/// A render object that draws dots under each pointer.
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.
@override
bool get sizedByParent => true;
/// By selecting the biggest value permitted by the incoming constraints
/// during layout, this function makes this render object as large as
/// possible (i.e., fills the entire screen).
@override
void performResize() {
size = constraints.biggest;
}
/// Makes this render object hittable so that it receives pointer events.
@override
bool hitTestSelf(Offset position) => true;
/// Processes pointer events by mutating state and invalidating its previous
/// painting commands.
@override
void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (event is PointerDownEvent) {
final Color color = _kColors[event.pointer.remainder(_kColors.length)];
_dots[event.pointer] = 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);
markNeedsPaint();
} else if (event is PointerMoveEvent) {
_dots[event.pointer]!.update(event);
markNeedsPaint();
}
}
/// Issues new painting commands.
@override
void paint(PaintingContext context, Offset offset) {
final Canvas canvas = context.canvas;
// The "size" property indicates the size of that this render box was
// allotted 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, Paint()..color = const Color(0xFFFFFFFF));
// We iterate through our model and paint each dot.
for (final Dot dot in _dots.values) {
dot.paint(canvas, offset);
}
}
}
void main() {
// Create some styled text to tell the user to interact with the app.
final paragraph = RenderParagraph(
const TextSpan(
style: TextStyle(color: Colors.black87),
text: 'Touch me!',
),
textDirection: TextDirection.ltr,
);
// 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.
final stack = RenderStack(
textDirection: TextDirection.ltr,
children: <RenderBox>[RenderDots(), paragraph],
);
// 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 paragraphParentData = paragraph.parentData! as StackParentData;
paragraphParentData
..top = 40.0
..left = 20.0;
// Finally, we attach the render tree we've built to the screen.
ViewRenderingFlutterBinding(root: stack).scheduleFrame();
}