Created
January 6, 2023 11:35
-
-
Save folaoluwafemi/ddbd7fc9b9ca2b63b144ae96da2a3554 to your computer and use it in GitHub Desktop.
custom outline input border that allows floating input label to be inside it.
This file contains hidden or 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
import 'dart:math' as math; | |
import 'package:flutter/material.dart'; | |
class CustomOutlineInputBorder extends InputBorder { | |
/// Creates an underline border for an [InputDecorator]. | |
/// | |
/// The [borderSide] parameter defaults to [BorderSide.none] (it must not be | |
/// null). Applications typically do not specify a [borderSide] parameter | |
/// because the input decorator substitutes its own, using [copyWith], based | |
/// on the current theme and [InputDecorator.isFocused]. | |
/// | |
/// The [borderRadius] parameter defaults to a value where the top left | |
/// and right corners have a circular radius of 4.0. The [borderRadius] | |
/// parameter must not be null. | |
const CustomOutlineInputBorder({ | |
BorderSide borderSide = const BorderSide(), | |
this.outlineRadius = const BorderRadius.only( | |
topLeft: Radius.circular(16.0), | |
topRight: Radius.circular(16.0), | |
bottomLeft: Radius.circular(16.0), | |
bottomRight: Radius.circular(16.0), | |
), | |
this.borderRadius = const BorderRadius.only( | |
topLeft: Radius.circular(20.0), | |
topRight: Radius.circular(20.0), | |
bottomLeft: Radius.circular(20.0), | |
bottomRight: Radius.circular(20.0), | |
), | |
}) : assert(borderRadius != null), | |
super(borderSide: borderSide); | |
/// The radii of the border's rounded rectangle corners. | |
/// | |
/// When this border is used with a filled input decorator, see | |
/// [InputDecoration.filled], the border radius defines the shape | |
/// of the background fill as well as the bottom left and right | |
/// edges of the underline itself. | |
/// | |
/// By default the top right and top left corners have a circular radius | |
/// of 4.0. | |
final BorderRadius borderRadius; | |
@override | |
bool get isOutline => false; | |
final BorderRadius outlineRadius; | |
@override | |
CustomOutlineInputBorder copyWith({ | |
BorderSide? borderSide, | |
BorderRadius? borderRadius, | |
}) { | |
return CustomOutlineInputBorder( | |
borderSide: borderSide ?? this.borderSide, | |
borderRadius: borderRadius ?? this.borderRadius, | |
); | |
} | |
@override | |
EdgeInsetsGeometry get dimensions { | |
return EdgeInsets.only(bottom: borderSide.width); | |
} | |
@override | |
CustomOutlineInputBorder scale(double t) { | |
return CustomOutlineInputBorder(borderSide: borderSide.scale(t)); | |
} | |
@override | |
Path getInnerPath(Rect rect, {TextDirection? textDirection}) { | |
return Path() | |
..addRect(Rect.fromLTWH(rect.left, rect.top, rect.width, | |
math.max(0.0, rect.height - borderSide.width))); | |
} | |
@override | |
Path getOuterPath(Rect rect, {TextDirection? textDirection}) { | |
return Path()..addRRect(borderRadius.toRRect(rect)); | |
} | |
@override | |
ShapeBorder? lerpFrom(ShapeBorder? a, double t) { | |
if (a is CustomOutlineInputBorder) { | |
return CustomOutlineInputBorder( | |
borderSide: BorderSide.lerp(a.borderSide, borderSide, t), | |
borderRadius: BorderRadius.lerp(a.borderRadius, borderRadius, t)!, | |
); | |
} | |
return super.lerpFrom(a, t); | |
} | |
@override | |
ShapeBorder? lerpTo(ShapeBorder? b, double t) { | |
if (b is CustomOutlineInputBorder) { | |
return CustomOutlineInputBorder( | |
borderSide: BorderSide.lerp(borderSide, b.borderSide, t), | |
borderRadius: BorderRadius.lerp(borderRadius, b.borderRadius, t)!, | |
); | |
} | |
return super.lerpTo(b, t); | |
} | |
/// Draw a horizontal line at the bottom of [rect]. | |
/// | |
/// The [borderSide] defines the line's color and weight. The `textDirection` | |
/// `gap` and `textDirection` parameters are ignored. | |
@override | |
void paint( | |
Canvas canvas, | |
Rect rect, { | |
double? gapStart, | |
double gapExtent = 0.0, | |
double gapPercentage = 0.0, | |
TextDirection? textDirection, | |
}) { | |
final Paint paint = borderSide.toPaint(); | |
final Path outlinePath = Path()..addRRect(outlineRadius.toRRect(rect)); | |
canvas.drawPath(outlinePath, paint); | |
} | |
@override | |
bool operator ==(Object other) { | |
if (identical(this, other)) return true; | |
if (other.runtimeType != runtimeType) return false; | |
return other is InputBorder && other.borderSide == borderSide; | |
} | |
@override | |
int get hashCode => borderSide.hashCode; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment