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.borderRadius = const BorderRadius.only(
topLeft: Radius.circular(4.0),
topRight: Radius.circular(4.0),
bottomLeft: Radius.circular(4.0),
bottomRight: Radius.circular(4.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;
@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.resolve(textDirection).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 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 InputBorder && other.borderSide == borderSide;
}
@override
int get hashCode => borderSide.hashCode;
}
用法:**
TextFormField(
decoration: InputDecoration(
border: CustomOutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
borderSide: BorderSide(
color: Colors.white,
/// NOTE: Color argument won't work on border argument
width: 1,
style: BorderStyle.solid,
)),
enabledBorder: CustomOutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
borderSide: BorderSide(
color: Colors.white,
/// NOTE: Color argument works here! :hooray:
width: 1,
style: BorderStyle.solid,
)),
)
),
3条答案
按热度按时间htrmnn0y1#
我也很惊讶地看到它不是开箱即用的,在查看了
InputBorder
类之后,我明白了它可以变得相当复杂。复制整个
UnderlineInputBorder
类并将onPaint
方法替换为OutlineInputBorder
类中的方法对我很有效。重要提示:如果你只设置了TextField的
border
参数,它将使用主题Colors作为onFocus(默认为蓝色)和onError(默认为红色)。如果你想让BorderSide(color: [yourCustomColor])
正常工作,你必须为每个特定的状态传递border参数:s4n0splo2#
您可以使用
contentPadding
添加填充,然后使用FloatingLabelBehavior.always
使浮动标签始终显示。您可以根据浮动标签是否具有焦点,为浮动标签指定不同的样式。例如:gorkyyrv3#
上面的答案并不完全适合我,我不得不稍微调整一下绘制方法: