Files
CompanyProject/moehu/moehu_fontend/lib/widget/InputWidget/input_widget.dart
2024-09-27 01:32:49 +08:00

351 lines
8.3 KiB
Dart

import 'dart:async';
import 'package:emojis/emoji.dart';
import 'package:flutter/material.dart';
import 'package:peach/config/_.dart';
import 'package:peach/event/_.dart';
import 'dart:ui' as ui;
import 'package:peach/utils/Screen.dart';
typedef void OnSend(String text);
ChatType _initType = ChatType.text;
double _softKeyHeight = 324.0;
class InputWidget extends StatefulWidget {
final TextEditingController controller;
final Widget extraWidget;
final Widget emojiWidget;
final Widget voiceWidget;
final OnSend onSend;
final Function onFocusNode;
final String hintText;
const InputWidget({
Key key,
@required this.controller,
this.extraWidget,
this.emojiWidget,
this.voiceWidget,
this.onSend,
this.onFocusNode,
this.hintText = "回复",
}) : super(key: key);
@override
InputWidgetState createState() =>
InputWidgetState(this.onSend, this.onFocusNode);
}
class InputWidgetState extends State<InputWidget>
with WidgetsBindingObserver, TickerProviderStateMixin {
final Function onSend;
final Function onFocusNode;
String hintText = "回复";
ChatType currentType = _initType;
FocusNode focusNode = FocusNode();
StreamController<String> inputContentStreamController =
StreamController.broadcast();
InputWidgetState(this.onSend, this.onFocusNode);
Stream<String> get inputContentStream => inputContentStreamController.stream;
AnimationController _bottomHeightController;
double maxHeight = 90;
List<Emoji> emList = Emoji.all().take(100).toList();
Color butColor = ColorConfig.TextColor;
@override
void initState() {
super.initState();
onFocusNode(focusNode);
WidgetsBinding.instance.addObserver(this);
focusNode.addListener(onFocus);
widget.controller.addListener(_onInputChange);
_bottomHeightController = AnimationController(
vsync: this,
duration: Duration(
milliseconds: 250,
),
);
Config.eventBus.on<ClasshHntTextEvent>().listen((event) {
if (event.text != "") {
hintText = event.text;
}
});
}
// bool checkShowSendButton(String text) {
// if (currentType == ChatType.voice) {
// return false;
// }
// if (text.trim().isNotEmpty) {
// return true;
// }
// return false;
// }
@override
void didChangeMetrics() {
final mediaQueryData = MediaQueryData.fromWindow(ui.window);
final keyHeight = mediaQueryData?.viewInsets?.bottom;
if (keyHeight != 0) {
_softKeyHeight = keyHeight;
// updateState(ChatType.text);
} else {
// setState(() {});
}
}
void onFocus() {
if (focusNode.hasFocus) {
updateState(ChatType.text);
}
}
void _onInputChange() {
inputContentStreamController.add(widget.controller.text);
if (widget.controller.text.length > 0) {
butColor = ColorConfig.ThemeColor;
} else {
butColor = ColorConfig.TextColor;
}
setState(() {});
}
@override
void dispose() {
_bottomHeightController.dispose();
inputContentStreamController.close();
widget.controller.removeListener(_onInputChange);
focusNode.removeListener(onFocus);
focusNode.dispose();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints(maxHeight: 390),
child: Container(
height: maxHeight,
// decoration: BoxDecoration(
// border: Border(
// top: BorderSide(color: ColorConfig.LineColor, width: 1),
// ),
// ),
child: Column(
children: <Widget>[
buildInputButton(),
Container(
margin: EdgeInsets.only(bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
buildEmojiButton(),
buildRightButton(),
],
),
),
// Divider(),
_buildBottomContainer(child: _buildBottomItems())
],
),
),
);
}
Widget buildRightButton() {
return ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 25,
),
child: IconButton(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
iconSize: 32,
color: butColor,
enableFeedback: true,
padding: EdgeInsets.only(top: 0),
icon: Icon(Icons.send),
onPressed: () {
if (widget.controller.text.length <= 0) return;
this.onSend(widget.controller.text);
widget.controller.text = "";
},
),
);
}
Widget buildEmojiButton() {
return ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 25,
),
child: IconButton(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
iconSize: 32,
color: ColorConfig.TextColor,
padding: EdgeInsets.only(top: 0),
icon: currentType != ChatType.emoji
? Icon(Icons.mood)
: Icon(Icons.keyboard),
onPressed: () {
if (currentType != ChatType.emoji) {
updateState(ChatType.emoji);
} else {
updateState(ChatType.text);
}
},
),
);
}
Widget buildInputButton() {
final inputButton = TextField(
focusNode: focusNode,
controller: widget.controller,
cursorHeight: 20,
decoration: InputDecoration(
isDense: true,
hintText: hintText,
fillColor: Colors.white,
border: OutlineInputBorder(borderSide: BorderSide.none),
),
);
return Container(
height: Screen.setHeight(35),
padding: EdgeInsets.only(top: 15),
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 25,
),
child: inputButton,
),
);
}
void changeBottomHeight(final double height) {
if (height > 0) {
_bottomHeightController.animateTo(1);
} else {
_bottomHeightController.animateBack(0);
}
}
Future<void> updateState(ChatType type) async {
if (type == ChatType.text || type == ChatType.voice) {
_initType = type;
}
if (type == currentType) {
return;
}
this.currentType = type;
ChangeChatTypeNotification(type).dispatch(context);
if (type != ChatType.text) {
hideSoftKey();
setState(() {
maxHeight = 390;
});
} else {
showSoftKey();
setState(() {
maxHeight = 90;
});
}
if (type == ChatType.emoji || type == ChatType.extra) {
// _currentOtherHeight = _softKeyHeight;
changeBottomHeight(1);
} else {
changeBottomHeight(0);
// _currentOtherHeight = 0;
}
setState(() {});
}
void showSoftKey() {
FocusScope.of(context).requestFocus(focusNode);
}
void hideSoftKey() {
focusNode.unfocus();
}
Widget _buildBottomContainer({Widget child}) {
return SizeTransition(
sizeFactor: _bottomHeightController,
child: Container(
child: child,
height: 300,
),
);
}
Widget _buildBottomItems() {
return Container(
decoration: BoxDecoration(
border: Border(top: BorderSide(width: 1, color: ColorConfig.LineColor)),
),
child: MediaQuery.removePadding(
context: context,
removeTop: true,
removeBottom: true,
child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 7,
),
children: [
...emList.asMap().keys.map(
(e) {
return GestureDetector(
onTap: () {
widget.controller.text += emList[e].toString();
},
child: Container(
alignment: Alignment.center,
child: Text(
"${emList[e]}",
style: TextStyle(
fontSize: 24,
),
),
),
);
},
).toList(),
],
),
),
);
}
}
enum ChatType {
text,
voice,
emoji,
extra,
}
class ChangeChatTypeNotification extends Notification {
final ChatType type;
ChangeChatTypeNotification(this.type);
}