最佳答案
我也很惊讶地发现它不支持开箱即用。在查看了 InputBorder
类之后,我了解到它可能会变得相当复杂。
复制整个 UnderlineInputBorder
类并将 onPaint
方法替换为 OutlineInputBorder
类中的方法对我有用。
自定义 InputBorder 类:
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,
)),
)
),
重要提示:如果您只设置 TextField 的 border
参数,它将使用 onFocus(默认为蓝色)和 onError(默认为红色)的主题颜色。如果您想让 BorderSide(color: [yourCustomColor])
正常工作,您必须为每个特定状态传递边框参数:
errorBorder
focusedBorder
focusedErrorBorder
disabledBorder
enabledBorder
关于flutter - 如何让 float 标签停留在边框内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71621132/