-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d8e480e
commit 42dffbc
Showing
9 changed files
with
209 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
## 0.2.0 | ||
|
||
* Added input border | ||
|
||
## 0.1.0 | ||
|
||
* Initial release containing gradient box border |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
library gradient_borders; | ||
|
||
export 'box_borders/gradient_box_border.dart'; | ||
export 'input_borders/gradient_outline_input_border.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
import 'dart:ui'; | ||
import 'dart:math' as math; | ||
|
||
import 'package:flutter/material.dart'; | ||
|
||
class GradientOutlineInputBorder extends InputBorder { | ||
final double width; | ||
final BorderRadius borderRadius; | ||
final Gradient gradient; | ||
final double gapPadding; | ||
|
||
const GradientOutlineInputBorder({ | ||
required this.gradient, | ||
this.width = 1.0, | ||
this.gapPadding = 4.0, | ||
this.borderRadius = const BorderRadius.all(Radius.circular(4.0)), | ||
}); | ||
|
||
@override | ||
InputBorder copyWith({BorderSide? borderSide}) { | ||
return this; | ||
} | ||
|
||
@override | ||
bool get isOutline => true; | ||
|
||
@override | ||
EdgeInsetsGeometry get dimensions => EdgeInsets.all(width); | ||
|
||
@override | ||
Path getInnerPath(Rect rect, {TextDirection? textDirection}) { | ||
return Path() | ||
..addRRect(borderRadius | ||
.resolve(textDirection) | ||
.toRRect(rect) | ||
.deflate(borderSide.width)); | ||
} | ||
|
||
@override | ||
Path getOuterPath(Rect rect, {TextDirection? textDirection}) { | ||
return Path()..addRRect(borderRadius.resolve(textDirection).toRRect(rect)); | ||
} | ||
|
||
@override | ||
void paint(Canvas canvas, Rect rect, | ||
{double? gapStart, | ||
double gapExtent = 0.0, | ||
double gapPercentage = 0.0, | ||
TextDirection? textDirection}) { | ||
final Paint paint = _getPaint(rect); | ||
final RRect outer = borderRadius.toRRect(rect); | ||
final RRect center = outer.deflate(borderSide.width / 2.0); | ||
if (gapStart == null || gapExtent <= 0.0 || gapPercentage == 0.0) { | ||
canvas.drawRRect(center, paint); | ||
} else { | ||
final double extent = | ||
lerpDouble(0.0, gapExtent + gapPadding * 2.0, gapPercentage)!; | ||
switch (textDirection!) { | ||
case TextDirection.rtl: | ||
final Path path = _gapBorderPath(canvas, center, | ||
math.max(0.0, gapStart + gapPadding - extent), extent); | ||
canvas.drawPath(path, paint); | ||
break; | ||
|
||
case TextDirection.ltr: | ||
final Path path = _gapBorderPath( | ||
canvas, center, math.max(0.0, gapStart - gapPadding), extent); | ||
canvas.drawPath(path, paint); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
@override | ||
ShapeBorder scale(double t) { | ||
return GradientOutlineInputBorder( | ||
width: width * t, | ||
borderRadius: borderRadius * t, | ||
gradient: gradient, | ||
); | ||
} | ||
|
||
Paint _getPaint(Rect rect) { | ||
return Paint() | ||
..strokeWidth = width | ||
..shader = gradient.createShader(rect) | ||
..style = PaintingStyle.stroke; | ||
} | ||
|
||
Path _gapBorderPath( | ||
Canvas canvas, RRect center, double start, double extent) { | ||
// When the corner radii on any side add up to be greater than the | ||
// given height, each radius has to be scaled to not exceed the | ||
// size of the width/height of the RRect. | ||
final RRect scaledRRect = center.scaleRadii(); | ||
|
||
final Rect tlCorner = Rect.fromLTWH( | ||
scaledRRect.left, | ||
scaledRRect.top, | ||
scaledRRect.tlRadiusX * 2.0, | ||
scaledRRect.tlRadiusY * 2.0, | ||
); | ||
final Rect trCorner = Rect.fromLTWH( | ||
scaledRRect.right - scaledRRect.trRadiusX * 2.0, | ||
scaledRRect.top, | ||
scaledRRect.trRadiusX * 2.0, | ||
scaledRRect.trRadiusY * 2.0, | ||
); | ||
final Rect brCorner = Rect.fromLTWH( | ||
scaledRRect.right - scaledRRect.brRadiusX * 2.0, | ||
scaledRRect.bottom - scaledRRect.brRadiusY * 2.0, | ||
scaledRRect.brRadiusX * 2.0, | ||
scaledRRect.brRadiusY * 2.0, | ||
); | ||
final Rect blCorner = Rect.fromLTWH( | ||
scaledRRect.left, | ||
scaledRRect.bottom - scaledRRect.blRadiusY * 2.0, | ||
scaledRRect.blRadiusX * 2.0, | ||
scaledRRect.blRadiusX * 2.0, | ||
); | ||
|
||
const double cornerArcSweep = math.pi / 2.0; | ||
final double tlCornerArcSweep = start < scaledRRect.tlRadiusX | ||
? math.asin((start / scaledRRect.tlRadiusX).clamp(-1.0, 1.0)) | ||
: math.pi / 2.0; | ||
|
||
final Path path = Path() | ||
..addArc(tlCorner, math.pi, tlCornerArcSweep) | ||
..moveTo(scaledRRect.left + scaledRRect.tlRadiusX, scaledRRect.top); | ||
|
||
if (start > scaledRRect.tlRadiusX) | ||
path.lineTo(scaledRRect.left + start, scaledRRect.top); | ||
|
||
const double trCornerArcStart = (3 * math.pi) / 2.0; | ||
const double trCornerArcSweep = cornerArcSweep; | ||
if (start + extent < scaledRRect.width - scaledRRect.trRadiusX) { | ||
path | ||
..relativeMoveTo(extent, 0.0) | ||
..lineTo(scaledRRect.right - scaledRRect.trRadiusX, scaledRRect.top) | ||
..addArc(trCorner, trCornerArcStart, trCornerArcSweep); | ||
} else if (start + extent < scaledRRect.width) { | ||
final double dx = scaledRRect.width - (start + extent); | ||
final double sweep = math.acos(dx / scaledRRect.trRadiusX); | ||
path.addArc(trCorner, trCornerArcStart + sweep, trCornerArcSweep - sweep); | ||
} | ||
|
||
return path | ||
..moveTo(scaledRRect.right, scaledRRect.top + scaledRRect.trRadiusY) | ||
..lineTo(scaledRRect.right, scaledRRect.bottom - scaledRRect.brRadiusY) | ||
..addArc(brCorner, 0.0, cornerArcSweep) | ||
..lineTo(scaledRRect.left + scaledRRect.blRadiusX, scaledRRect.bottom) | ||
..addArc(blCorner, math.pi / 2.0, cornerArcSweep) | ||
..lineTo(scaledRRect.left, scaledRRect.top + scaledRRect.tlRadiusY); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.