我需要创建一个具有特定行为的文本字段,例如松弛文本字段:
向上滑动时,文本字段应动画为全屏,向下滑动时应最小化。
当处于最小化状态时,TextField 应根据内容动态调整其高度,最多 5 行。达到 5 行后,它应该启用滚动。
我使用 AnimatedContainer 来处理动画。当我有条件地设置高度时,就会出现问题,动画停止工作:
height: isFullScreen ? textFieldHeight : null,
但是,如果我设置像
height: textFieldHeight
这样的固定高度或在条件下给出默认高度,动画将按预期工作。缺点是 TextField 在最小化状态下不会动态调整其高度。当我这样做时,文本字段保持其初始状态,并且不会通过添加新行来增长 height: textFieldHeight
.
这是我的函数代码:
KeyboardVisibilityBuilder _getTextFieldContainer(BuildContext context) {
return KeyboardVisibilityBuilder(
builder: (context, isKeyboardVisible) {
return Stack(
children: [ SingleChildScrollView(
child: Container(
width: double.infinity,
decoration: BoxDecoration(
border:
Border.all(color: Get.isDarkMode ? darkGrey : lightGrey),
color: widget.backgroundColor,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(8), topRight: Radius.circular(8)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(left: 12, right: 12),
child: GestureDetector(
onVerticalDragUpdate: (details) {
if (details.delta.dy > 0) { // Swipe down
if (isFullScreen) {
toggleFullScreen(context);
}
}
else if (details.delta.dy < 0) { // Swipe up
if (!isFullScreen) {
toggleFullScreen(context);
}
}
},
child: AnimatedContainer(
duration: Duration(milliseconds: 500),
curve: Curves.easeInOut,
height: isFullScreen ? textFieldHeight : bottomBarHeight,
child: TextField(
focusNode: _textFieldFocusNode,
controller: _chatController.textEditingController.value,
minLines: 1,
maxLines: isFullScreen ? null : (isKeyboardVisible ? 5 : 1),
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
autocorrect: false,
cursorColor:
Get.isDarkMode ? Colors.white : primaryColor,
decoration: InputDecoration(
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
),
focusedBorder: InputBorder.none,
hintText: widget.submitType == SubmitType.view
? 'Have a question? Ask now!'
: 'Type here',
suffixIcon: isKeyboardVisible || isFullScreen
? null
: Row(
mainAxisSize: MainAxisSize.min,
children: [
Obx(() => _getSpeechToText()),
Obx(() => _getTextFieldSuffix()),
],
),
),
onChanged: (value) {
setState(
() {},
);
},
))
)),
isKeyboardVisible
? _textFieldBottomBar(context)
: const SizedBox.shrink(),
],
)),
) ,
if (isKeyboardVisible || isFullScreen)
Positioned(
bottom: 0,
left: 0,
right: 0,
child: _textFieldBottomBar(context),
)]);
},
);
}
@override
Widget build(BuildContext context) {
return _getTextFieldContainer(context);
}
这是用于向上滑动和向下滑动以及设置全屏的textFieldHeight:
double textFieldHeight = 50.0;
double bottomBarHeight = 50.0;
bool isFullScreen = false;
void toggleFullScreen(BuildContext context) {
setState(() {
isFullScreen = !isFullScreen;
double screenHeight = MediaQuery.of(context).size.height;
textFieldHeight = isFullScreen ? screenHeight - bottomBarHeight : 50.0;
});
}
如何实现最小化状态下的上下滑动动画和动态高度调整?具体如何实现动画效果?
不管怎样,我现在已经解决了
当 isFullScreen 为 false 时,我将 AnimatedContainer 的高度设置为 null。我将 BoxConstraints 添加到 AnimatedContainer 以在 isFullScreen 为 false 时设置最小和最大高度。这允许 TextField 动态增长最多 5 行。我用 IntrinsicHeight 小部件包装了 TextField,以确保它具有所需的最小高度。 这将允许您在最小化状态下同时具有向上滑动/向下滑动动画和动态高度调整。
child: AnimatedContainer(
duration: Duration(milliseconds: 500),
curve: Curves.easeInOut,
height: isFullScreen
? textFieldHeight
: null,
constraints: isFullScreen
? null
: BoxConstraints(
minHeight: bottomBarHeight,
maxHeight: 5 * bottomBarHeight),
child: IntrinsicHeight(
child: TextField(