Merge pull request #433 from orz12/mod-video-detail-reply
mod: 视频评论输入框高度自适应
This commit is contained in:
@ -2,12 +2,10 @@ import 'dart:async';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:pilipala/http/video.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/common/reply_type.dart';
|
import 'package:pilipala/models/common/reply_type.dart';
|
||||||
import 'package:pilipala/models/video/reply/item.dart';
|
import 'package:pilipala/models/video/reply/item.dart';
|
||||||
import 'package:pilipala/utils/feed_back.dart';
|
import 'package:pilipala/utils/feed_back.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
|
||||||
|
|
||||||
class VideoReplyNewDialog extends StatefulWidget {
|
class VideoReplyNewDialog extends StatefulWidget {
|
||||||
final int? oid;
|
final int? oid;
|
||||||
@ -34,25 +32,16 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
final TextEditingController _replyContentController = TextEditingController();
|
final TextEditingController _replyContentController = TextEditingController();
|
||||||
final FocusNode replyContentFocusNode = FocusNode();
|
final FocusNode replyContentFocusNode = FocusNode();
|
||||||
final GlobalKey _formKey = GlobalKey<FormState>();
|
final GlobalKey _formKey = GlobalKey<FormState>();
|
||||||
double _keyboardHeight = 0.0; // 键盘高度
|
|
||||||
final _debouncer = Debouncer(milliseconds: 100); // 设置延迟时间
|
|
||||||
bool ableClean = false;
|
|
||||||
Timer? timer;
|
|
||||||
Box localCache = GStrorage.localCache;
|
|
||||||
late double sheetHeight;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// 监听输入框聚焦
|
// 监听输入框聚焦
|
||||||
// replyContentFocusNode.addListener(_onFocus);
|
// replyContentFocusNode.addListener(_onFocus);
|
||||||
_replyContentController.addListener(_printLatestValue);
|
|
||||||
// 界面观察者 必须
|
// 界面观察者 必须
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
// 自动聚焦
|
// 自动聚焦
|
||||||
_autoFocus();
|
_autoFocus();
|
||||||
|
|
||||||
sheetHeight = localCache.get('sheetHeight');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_autoFocus() async {
|
_autoFocus() async {
|
||||||
@ -62,12 +51,6 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_printLatestValue() {
|
|
||||||
setState(() {
|
|
||||||
ableClean = _replyContentController.text != '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future submitReplyAdd() async {
|
Future submitReplyAdd() async {
|
||||||
feedBack();
|
feedBack();
|
||||||
String message = _replyContentController.text;
|
String message = _replyContentController.text;
|
||||||
@ -90,24 +73,6 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeMetrics() {
|
|
||||||
super.didChangeMetrics();
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
// 键盘高度
|
|
||||||
final viewInsets = EdgeInsets.fromViewPadding(
|
|
||||||
View.of(context).viewInsets, View.of(context).devicePixelRatio);
|
|
||||||
_debouncer.run(() {
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
_keyboardHeight =
|
|
||||||
_keyboardHeight == 0.0 ? viewInsets.bottom : _keyboardHeight;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
@ -117,8 +82,10 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
double keyboardHeight = EdgeInsets.fromViewPadding(
|
||||||
|
View.of(context).viewInsets, View.of(context).devicePixelRatio)
|
||||||
|
.bottom;
|
||||||
return Container(
|
return Container(
|
||||||
height: 500,
|
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(
|
||||||
@ -130,10 +97,15 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxHeight: 200,
|
||||||
|
minHeight: 120,
|
||||||
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
top: 6, right: 15, left: 15, bottom: 10),
|
top: 12, right: 15, left: 15, bottom: 10),
|
||||||
|
child: SingleChildScrollView(
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
@ -154,6 +126,7 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
Divider(
|
Divider(
|
||||||
height: 1,
|
height: 1,
|
||||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||||
@ -183,7 +156,8 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
MaterialStateProperty.resolveWith((states) {
|
MaterialStateProperty.resolveWith((states) {
|
||||||
return Theme.of(context).highlightColor;
|
return Theme.of(context).highlightColor;
|
||||||
}),
|
}),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
TextButton(
|
TextButton(
|
||||||
@ -196,7 +170,7 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: _keyboardHeight,
|
height: keyboardHeight,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -204,22 +178,3 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef DebounceCallback = void Function();
|
|
||||||
|
|
||||||
class Debouncer {
|
|
||||||
DebounceCallback? callback;
|
|
||||||
final int? milliseconds;
|
|
||||||
Timer? _timer;
|
|
||||||
|
|
||||||
Debouncer({this.milliseconds});
|
|
||||||
|
|
||||||
run(DebounceCallback callback) {
|
|
||||||
if (_timer != null) {
|
|
||||||
_timer!.cancel();
|
|
||||||
}
|
|
||||||
_timer = Timer(Duration(milliseconds: milliseconds!), () {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user