Flutter & OpenHarmony 社交App消息输入框组件开发实战

前言
消息输入框是社交应用中用户交互最频繁的组件之一。一个优秀的输入框组件需要支持文本输入、表情选择、附件发送等多种功能,同时还要具备良好的用户体验和性能表现。本文将深入讲解如何在Flutter和OpenHarmony平台上构建功能完善的消息输入框组件。
Flutter消息输入框实现
我们首先来实现Flutter版本的消息输入框,包含文本输入、发送按钮和附件按钮。
class MessageInputBar extends StatefulWidget {
final Function(String) onSend;
final VoidCallback? onAttachmentTap;
const MessageInputBar({
Key? key,
required this.onSend,
this.onAttachmentTap,
}) : super(key: key);
State<MessageInputBar> createState() => _MessageInputBarState();
}
组件定义为StatefulWidget因为需要管理输入框的状态。onSend回调在用户发送消息时触发,onAttachmentTap处理附件按钮点击。
class _MessageInputBarState extends State<MessageInputBar> {
final TextEditingController _controller = TextEditingController();
bool _hasText = false;
void initState() {
super.initState();
_controller.addListener(_onTextChanged);
}
void _onTextChanged() {
setState(() {
_hasText = _controller.text.trim().isNotEmpty;
});
}
State类中定义TextEditingController来管理输入内容。_hasText状态变量追踪输入框是否有内容,用于控制发送按钮的显示状态。在initState中添加监听器,每当文本变化时更新状态。这种响应式设计确保UI始终与数据同步。
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: Offset(0, -2),
),
],
),
Container设置内边距和装饰样式。boxShadow创建向上的阴影效果,让输入栏与聊天内容区域形成视觉分隔。阴影透明度设置为5%,既能起到分隔作用又不会过于突兀,符合现代UI设计的轻量化趋势。
child: SafeArea(
top: false,
child: Row(
children: [
IconButton(
icon: Icon(Icons.add_circle_outline),
color: Colors.grey[600],
onPressed: widget.onAttachmentTap,
),
SafeArea确保在有底部安全区域的设备上正确显示。Row组件水平排列各个子元素。附件按钮使用IconButton实现,图标颜色设置为灰色,与整体设计风格协调。点击时触发父组件传入的回调函数。
Expanded(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(24),
),
child: TextField(
controller: _controller,
maxLines: 4,
minLines: 1,
decoration: InputDecoration(
hintText: '输入消息...',
border: InputBorder.none,
),
),
),
),
Expanded让输入框占据剩余空间。外层Container创建圆角背景,内部TextField支持多行输入,maxLines限制最大行数防止输入框过度扩展。InputDecoration移除默认边框,hintText提供输入提示。这种设计让输入框看起来更加现代简洁。
SizedBox(width: 8),
AnimatedSwitcher(
duration: Duration(milliseconds: 200),
child: _hasText
? IconButton(
key: ValueKey('send'),
icon: Icon(Icons.send),
color: Colors.blue,
onPressed: _sendMessage,
)
: IconButton(
key: ValueKey('mic'),
icon: Icon(Icons.mic),
color: Colors.grey[600],
onPressed: () {},
),
),
],
),
),
);
}
AnimatedSwitcher实现发送按钮和语音按钮之间的平滑切换动画。当输入框有内容时显示蓝色发送按钮,否则显示灰色麦克风按钮。ValueKey确保动画正确识别不同的子组件。200毫秒的动画时长恰到好处,既能让用户感知到变化又不会造成等待感。
void _sendMessage() {
if (_controller.text.trim().isNotEmpty) {
widget.onSend(_controller.text.trim());
_controller.clear();
}
}
void dispose() {
_controller.dispose();
super.dispose();
}
}
_sendMessage方法处理消息发送逻辑,发送后清空输入框。dispose方法释放TextEditingController资源,防止内存泄漏。这是Flutter开发中的最佳实践,每个Controller都应该在组件销毁时正确释放。
OpenHarmony ArkTS实现
现在来看鸿蒙系统上的实现方案。
@Component
struct MessageInputBar {
@State inputText: string = ''
onSend: (message: string) => void = () => {}
onAttachmentTap: () => void = () => {}
build() {
Row() {
Image($r('app.media.ic_add'))
.width(28)
.height(28)
.margin({ left: 12 })
.onClick(() => this.onAttachmentTap())
@State装饰器声明响应式状态变量inputText。回调函数使用箭头函数语法定义默认空实现。Row作为根容器水平排列子元素。附件按钮使用Image组件加载本地图标资源,onClick绑定点击事件。
TextInput({ placeholder: '输入消息...', text: this.inputText })
.layoutWeight(1)
.height(40)
.backgroundColor('#F5F5F5')
.borderRadius(20)
.padding({ left: 16, right: 16 })
.margin({ left: 8, right: 8 })
.onChange((value: string) => {
this.inputText = value
})
TextInput组件实现文本输入功能,placeholder设置提示文字,text绑定状态变量实现双向数据绑定。layoutWeight(1)让输入框占据剩余空间,相当于Flutter的Expanded。onChange回调在输入变化时更新状态。圆角和背景色设置与Flutter版本保持一致的视觉风格。
if (this.inputText.trim().length > 0) {
Image($r('app.media.ic_send'))
.width(28)
.height(28)
.margin({ right: 12 })
.onClick(() => this.handleSend())
} else {
Image($r('app.media.ic_mic'))
.width(28)
.height(28)
.margin({ right: 12 })
.onClick(() => {})
}
}
.width('100%')
.height(56)
.backgroundColor(Color.White)
}
条件渲染根据输入内容切换发送按钮和麦克风按钮。ArkTS的条件渲染语法更加直观,直接使用if-else语句。整个Row设置固定高度和白色背景,形成清晰的输入区域。
handleSend() {
if (this.inputText.trim().length > 0) {
this.onSend(this.inputText.trim())
this.inputText = ''
}
}
}
handleSend方法封装发送逻辑,发送成功后清空输入框。由于inputText是响应式状态,清空后UI会自动更新,无需手动触发刷新。
总结
本文详细介绍了消息输入框组件在Flutter和OpenHarmony两个平台上的实现。输入框组件虽然看起来简单,但涉及状态管理、事件处理、动画效果等多个技术点。两个平台的实现思路相似,都采用响应式状态管理和条件渲染。在实际项目中,还可以扩展表情选择、@提及、话题标签等高级功能。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)