Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 23 additions & 94 deletions lib/flutter_highlight.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

@immutable
part 'src/flutter_highlight_filter.dart';
part 'src/flutter_highlight_render.dart';

class FlutterHighlight extends StatefulWidget {
/// Duration of the animation.
final Duration duration;

/// Number of times the animation goes forward and reverse.
final int blinkNumber;

/// Color of the highlight.
final Color? color;

/// Minimum highlight opacity.
final double minOpacity;

/// Maximum highlight opacity.
final double maxOpacity;

final Widget child;

const FlutterHighlight({
super.key,
required this.duration,
this.blinkNumber = 3,
this.minOpacity = 0.0,
this.maxOpacity = 0.6,
this.color,
required this.child,
});
}) : assert(blinkNumber >= 1),
assert(minOpacity >= 0.0),
assert(maxOpacity <= 1.0);

@override
State<FlutterHighlight> createState() => _FlutterHighlightState();
Expand All @@ -27,9 +45,9 @@ class _FlutterHighlightState extends State<FlutterHighlight>
Future<void> _runAnimation() async {
int count = 0;
while (count < widget.blinkNumber) {
count++;
await _animationController.forward();
await _animationController.reverse();
count++;
}
}

Expand All @@ -39,7 +57,8 @@ class _FlutterHighlightState extends State<FlutterHighlight>
_animationController = AnimationController(
vsync: this,
duration: widget.duration,
upperBound: 0.6,
lowerBound: widget.minOpacity,
upperBound: widget.maxOpacity,
);
_runAnimation();
}
Expand All @@ -65,93 +84,3 @@ class _FlutterHighlightState extends State<FlutterHighlight>
);
}
}

/// ----------------------------------------------------------------------------

@immutable
class _FlutterHighlightRender extends SingleChildRenderObjectWidget {
final double percent;
final Color color;

const _FlutterHighlightRender({
required this.percent,
required this.color,
required super.child,
});

@override
_FlutterHighlightFilter createRenderObject(BuildContext context) {
return _FlutterHighlightFilter(percent, color);
}

@override
void updateRenderObject(
BuildContext context,
_FlutterHighlightFilter filter,
) {
filter.percent = percent;
filter.color = color;
}
}

/// ----------------------------------------------------------------------------

class _FlutterHighlightFilter extends RenderProxyBox {
double _percent;
Color _color;

_FlutterHighlightFilter(this._percent, this._color);

@override
ShaderMaskLayer? get layer => super.layer as ShaderMaskLayer?;

@override
bool get alwaysNeedsCompositing => child != null;

set percent(double newValue) {
if (newValue == _percent) return;
_percent = newValue;
markNeedsPaint();
}

set color(Color newValue) {
if (newValue == _color) return;
_color = newValue;
markNeedsPaint();
}

double _offset(double start, double end, double percent) {
return start + (end - start) * percent;
}

@override
void paint(PaintingContext context, Offset offset) {
if (child != null) {
final double width = child!.size.width;
final double height = child!.size.height;

Rect rect;
double dx, dy;

dx = _offset(-width, width, 1);
dy = 0.0;
rect = Rect.fromLTWH(dx - width, dy, 3 * width, height);

layer ??= ShaderMaskLayer();
layer!
..shader = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
_color.withValues(alpha: _percent),
_color.withValues(alpha: _percent),
],
).createShader(rect)
..maskRect = offset & size
..blendMode = BlendMode.srcATop;
context.pushLayer(layer!, super.paint, offset);
} else {
layer = null;
}
}
}
61 changes: 61 additions & 0 deletions lib/src/flutter_highlight_filter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
part of '../flutter_highlight.dart';

class _FlutterHighlightFilter extends RenderProxyBox {
double _percent;
Color _color;

_FlutterHighlightFilter(this._percent, this._color);

@override
ShaderMaskLayer? get layer => super.layer as ShaderMaskLayer?;

@override
bool get alwaysNeedsCompositing => child != null;

set percent(double newValue) {
if (newValue == _percent) return;
_percent = newValue;
markNeedsPaint();
}

set color(Color newValue) {
if (newValue == _color) return;
_color = newValue;
markNeedsPaint();
}

double _offset(double start, double end, double percent) {
return start + (end - start) * percent;
}

@override
void paint(PaintingContext context, Offset offset) {
if (child != null) {
final double width = child!.size.width;
final double height = child!.size.height;

Rect rect;
double dx, dy;

dx = _offset(-width, width, 1);
dy = 0.0;
rect = Rect.fromLTWH(dx - width, dy, 3 * width, height);

layer ??= ShaderMaskLayer();
layer!
..shader = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
_color.withValues(alpha: _percent),
_color.withValues(alpha: _percent),
],
).createShader(rect)
..maskRect = offset & size
..blendMode = BlendMode.srcATop;
context.pushLayer(layer!, super.paint, offset);
} else {
layer = null;
}
}
}
26 changes: 26 additions & 0 deletions lib/src/flutter_highlight_render.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
part of '../flutter_highlight.dart';

class _FlutterHighlightRender extends SingleChildRenderObjectWidget {
final double percent;
final Color color;

const _FlutterHighlightRender({
required this.percent,
required this.color,
required super.child,
});

@override
_FlutterHighlightFilter createRenderObject(BuildContext context) {
return _FlutterHighlightFilter(percent, color);
}

@override
void updateRenderObject(
BuildContext context,
_FlutterHighlightFilter filter,
) {
filter.percent = percent;
filter.color = color;
}
}
3 changes: 1 addition & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
name: flutter_highlight
description: "A new Flutter project."
version: 0.0.1
homepage:

environment:
sdk: ^3.7.2
sdk: ">=3.7.0"
flutter: ">=1.17.0"

dependencies:
Expand Down