-
-
Save Vanchel/d473ef4204ab54b6203020bc4f43c994 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart'; | |
class OutlinedInputBorder extends InputBorder { | |
/// Creates a rounded rectangle outline border for an [InputDecorator]. | |
/// | |
/// If the [borderSide] parameter is [BorderSide.none], it will not draw a | |
/// border. However, it will still define a shape (which you can see if | |
/// [InputDecoration.filled] is true). | |
/// | |
/// If an application does not specify a [borderSide] parameter of | |
/// value [BorderSide.none], the input decorator substitutes its own, using | |
/// [copyWith], based on the current theme and [InputDecorator.isFocused]. | |
/// | |
/// The [borderRadius] parameter defaults to a value where all four | |
/// corners have a circular radius of 4.0. The [borderRadius] parameter | |
/// must not be null and the corner radii must be circular, i.e. their | |
/// [Radius.x] and [Radius.y] values must be the same. | |
/// | |
/// See also: | |
/// | |
/// * [InputDecoration.floatingLabelBehavior], which should be set to | |
/// [FloatingLabelBehavior.never] when the [borderSide] is | |
/// [BorderSide.none]. If let as [FloatingLabelBehavior.auto], the label | |
/// will extend beyond the container as if the border were still being | |
/// drawn. | |
const OutlinedInputBorder({ | |
super.borderSide = const BorderSide(), | |
this.borderRadius = const BorderRadius.all(Radius.circular(4.0)), | |
}); | |
/// The radii of the border's rounded rectangle corners. | |
/// | |
/// The corner radii must be circular, i.e. their [Radius.x] and [Radius.y] | |
/// values must be the same. | |
final BorderRadius borderRadius; | |
@override | |
bool get isOutline => false; | |
@override | |
OutlinedInputBorder copyWith({ | |
BorderSide? borderSide, | |
BorderRadius? borderRadius, | |
}) { | |
return OutlinedInputBorder( | |
borderSide: borderSide ?? this.borderSide, | |
borderRadius: borderRadius ?? this.borderRadius, | |
); | |
} | |
@override | |
EdgeInsetsGeometry get dimensions { | |
return EdgeInsets.all(borderSide.width); | |
} | |
@override | |
OutlinedInputBorder scale(double t) { | |
return OutlinedInputBorder( | |
borderSide: borderSide.scale(t), | |
borderRadius: borderRadius * t, | |
); | |
} | |
@override | |
ShapeBorder? lerpFrom(ShapeBorder? a, double t) { | |
if (a is OutlinedInputBorder) { | |
final OutlinedInputBorder outline = a; | |
return OutlinedInputBorder( | |
borderRadius: BorderRadius.lerp(outline.borderRadius, borderRadius, t)!, | |
borderSide: BorderSide.lerp(outline.borderSide, borderSide, t), | |
); | |
} | |
return super.lerpFrom(a, t); | |
} | |
@override | |
ShapeBorder? lerpTo(ShapeBorder? b, double t) { | |
if (b is OutlinedInputBorder) { | |
final OutlinedInputBorder outline = b; | |
return OutlinedInputBorder( | |
borderRadius: BorderRadius.lerp(borderRadius, outline.borderRadius, t)!, | |
borderSide: BorderSide.lerp(borderSide, outline.borderSide, t), | |
); | |
} | |
return super.lerpTo(b, t); | |
} | |
@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 paintInterior(Canvas canvas, Rect rect, Paint paint, | |
{TextDirection? textDirection}) { | |
canvas.drawRRect(borderRadius.resolve(textDirection).toRRect(rect), paint); | |
} | |
@override | |
bool get preferPaintInterior => true; | |
/// Draw a rounded rectangle around [rect] using [borderRadius]. | |
/// | |
/// The [borderSide] defines the line's color and weight. | |
@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 RRect outer = borderRadius.toRRect(rect); | |
final RRect center = outer.deflate(borderSide.width / 2.0); | |
canvas.drawRRect(center, paint); | |
} | |
@override | |
bool operator ==(Object other) { | |
if (identical(this, other)) { | |
return true; | |
} | |
if (other.runtimeType != runtimeType) { | |
return false; | |
} | |
return other is OutlinedInputBorder && | |
other.borderSide == borderSide && | |
other.borderRadius == borderRadius; | |
} | |
@override | |
int get hashCode => Object.hash(borderSide, borderRadius); | |
} | |
abstract class MaterialStateOutlinedInputBorder extends OutlinedInputBorder | |
implements WidgetStateProperty<InputBorder> { | |
/// Abstract const constructor. This constructor enables subclasses to provide | |
/// const constructors so that they can be used in const expressions. | |
const MaterialStateOutlinedInputBorder(); | |
/// Creates a [MaterialStateOutlinedInputBorder] from a [WidgetPropertyResolver<InputBorder>] | |
/// callback function. | |
/// | |
/// If used as a regular input border, the border resolved in the default state (the | |
/// empty set of states) will be used. | |
/// | |
/// The given callback parameter must return a non-null text style in the default | |
/// state. | |
static MaterialStateOutlinedInputBorder resolveWith( | |
WidgetPropertyResolver<InputBorder> callback) => | |
_MaterialStateOutlinedInputBorder(callback); | |
/// Returns a [InputBorder] that's to be used when a Material component is in the | |
/// specified state. | |
@override | |
InputBorder resolve(Set<WidgetState> states); | |
} | |
/// A [MaterialStateOutlinedInputBorder] created from a [WidgetPropertyResolver<OutlinedInputBorder>] | |
/// callback alone. | |
/// | |
/// If used as a regular input border, the border resolved in the default state will | |
/// be used. | |
/// | |
/// Used by [WidgetStateTextStyle.resolveWith]. | |
class _MaterialStateOutlinedInputBorder | |
extends MaterialStateOutlinedInputBorder { | |
const _MaterialStateOutlinedInputBorder(this._resolve); | |
final WidgetPropertyResolver<InputBorder> _resolve; | |
@override | |
InputBorder resolve(Set<WidgetState> states) => _resolve(states); | |
} |
Thanks a lot 👍
can you please guide in terms of usage (how to use it).
tried below in ThemeData
inputDecorationTheme: const InputDecorationTheme(border: CustomOutlinedInputBorder()),
have named it as CustomOutlinedInputBorder.
doing so , below error comes
custom_input_border.dart:158:16: Error: Type 'WidgetStateProperty' not found.
implements WidgetStateProperty {
^^^^^^^^^^^^^^^^^^^
can you please guide in terms of usage (how to use it).
tried below in ThemeData
inputDecorationTheme: const InputDecorationTheme(border: CustomOutlinedInputBorder()),
have named it as CustomOutlinedInputBorder. doing so , below error comes
custom_input_border.dart:158:16: Error: Type 'WidgetStateProperty' not found. implements WidgetStateProperty { ^^^^^^^^^^^^^^^^^^^
In Flutter 3.22 the interfaces associated with widget state have been renamed (more). If your project uses Flutter version prior to 3.22, just use the previous revision of this gist.
save me lots of work. thanks.