如何解决键盘在我的颤振应用程序中立即出现和消失
我在我的 flutter 应用程序中使用了 BottomNavigationBar,其中保存了每个选项卡的状态,并且我还使我的 BottomNavigationBar 除了具有文本输入的屏幕外可见。我做到了,但是当我想添加文本输入时出现了一个大问题。我无法专注于我的键盘。它会在不到一秒钟的时间内出现并返回。已经看到了一些人的解决方案,但它对我不起作用。我真的很高兴在这里得到帮助以修复键盘故障。谢谢
当我点击输入文本字段时,这会出现在我的终端上
W/IInputConnectionWrapper(29345): getSelectedText on inactive InputConnection
W/IInputConnectionWrapper(29345): requestCursorAnchorInfo on inactive InputConnection
3
W/IInputConnectionWrapper(29345): getTextBeforeCursor on inactive InputConnection
W/IInputConnectionWrapper(29345): getSelectedText on inactive InputConnection
D/InputConnectionAdaptor(29345): The input method toggled cursor monitoring on
I/SurfaceView(29345): updateWindow -- setFrame,this = io.flutter.embedding.android.FlutterSurfaceView{f394ae6 V.E...... ......I. 0,0-720,1204}
这是我的 flutter 医生,如果您需要更多文件,请告诉我。谢谢。
Doctor summary (to see all details,run flutter doctor -v):
[√] Flutter (Channel stable,2.0.6,on Microsoft Windows [Version 10.0.19043.985],locale en-US)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[X] Chrome - develop for the web (Cannot find Chrome executable at .\Google\Chrome\Application\chrome.exe)
! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
[√] Android Studio (version 4.1.0)
[√] VS Code (version 1.56.2)
[√] Connected device (2 available)
>
这是我的主页类文件
import 'package:flutter/material.dart';
import 'package:my_time_tracker/app/home/account/account_page.dart';
import 'package:my_time_tracker/app/home/entries/entries_page.dart';
import 'package:my_time_tracker/app/home/home_scaffold.dart';
import 'package:my_time_tracker/app/home/jobs/edit_job_page.dart';
import 'package:my_time_tracker/app/home/tab_item.dart';
import 'jobs/jobs_page.dart';
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
TabItem _currentTab = TabItem.jobs;
int _selectedIndex = 0;
List<GlobalKey<NavigatorState>> navigatorKeys = [
GlobalKey<NavigatorState>(),GlobalKey<NavigatorState>(),];
Map<int,Widget> get widgets {
return {
0: JobsPage(),1: EntriesPage.create(context),2: AccountPage(),};
}
void _onItemTapped(int index) {
if (_selectedIndex == index) {
navigatorKeys[index].currentState.popUntil((route) => route.isFirst);
} else {
setState(() {
_selectedIndex = index;
});
}
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
final isFirstRouteInCurrentTab =
!await navigatorKeys[_selectedIndex].currentState.maybePop();
print(
'isFirstrouteInCurrentTab:' + isFirstRouteInCurrentTab.toString());
return isFirstRouteInCurrentTab;
},child: HomeScaffold(
navigatorKeys: navigatorKeys,currentTabItem: _currentTab,onSelectTab: _onItemTapped,currentIndex: _selectedIndex,widget: widgets,),);
}
}
这是我的 HomeScaffold 类
import 'package:flutter/material.dart';
import 'package:my_time_tracker/app/home/account/account_page.dart';
import 'package:my_time_tracker/app/home/entries/entries_page.dart';
import 'package:my_time_tracker/app/home/jobs/jobs_page.dart';
import 'package:my_time_tracker/app/home/tab_item.dart';
import 'package:my_time_tracker/common_widgets/custom_text_style.dart';
class HomeScaffold extends StatefulWidget {
const HomeScaffold({
Key key,@required this.currentTabItem,@required this.onSelectTab,@required this.navigatorKeys,@required this.currentIndex,@required this.widget,}) : super(key: key);
final TabItem currentTabItem;
final int currentIndex;
final ValueChanged<int> onSelectTab;
final Map<int,Widget> widget;
final List<GlobalKey<NavigatorState>> navigatorKeys;
@override
_HomeScaffoldState createState() => _HomeScaffoldState();
}
class _HomeScaffoldState extends State<HomeScaffold> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,bottomNavigationBar: BottomNavigationBar(
items: [
_buildItem(TabItem.jobs),_buildItem(TabItem.entries),_buildItem(TabItem.account),],type: BottomNavigationBarType.shifting,onTap: (index) => widget.onSelectTab(index),selectedItemColor: Colors.teal,unselectedItemColor: Colors.grey[700].withOpacity(.60),backgroundColor: Colors.white,elevation: 5.0,currentIndex: widget.currentIndex,showUnselectedLabels: true,selectedLabelStyle: CustomTextStyles.textStyleBold(),body: Stack(
children: [
_buildOffStageNavigator(0),_buildOffStageNavigator(1),_buildOffStageNavigator(2),);
}
BottomNavigationBarItem _buildItem(TabItem tabItem) {
final itemData = TabItemData.allTabs[tabItem];
return BottomNavigationBarItem(
icon: Icon(itemData.icon),label: itemData.label,backgroundColor: itemData.backgroundColor,);
}
Map<String,WidgetBuilder> _routeBuilders(BuildContext context,int index) {
return {
'/': (context) {
return [
JobsPage(),EntriesPage.create(context),AccountPage(),].elementAt(index);
}
};
}
Widget _buildOffStageNavigator(int index) {
var routeBuilders = _routeBuilders(context,index);
return Offstage(
offstage: widget.currentIndex != index,child: Navigator(
key: widget.navigatorKeys[index],onGenerateRoute: (routeSettings) {
return MaterialPageRoute(
builder: (context) => routeBuilders[routeSettings.name](context),);
},);
}
}
这是我的 TabItem 类
import 'package:flutter/material.dart';
enum TabItem { jobs,entries,account }
class TabItemData {
const TabItemData({
@required this.label,@required this.icon,this.backgroundColor,});
final String label;
final IconData icon;
final Color backgroundColor;
static const Map<TabItem,TabItemData> allTabs = {
TabItem.jobs: TabItemData(
label: 'Jobs',icon: Icons.work,//backgroundColor: Colors.white,TabItem.entries: TabItemData(
label: 'Entries',icon: Icons.view_headline,//backgroundColor: Colors.tealAccent,TabItem.account: TabItemData(
label: 'Account',icon: Icons.account_circle,//backgroundColor: Colors.lightBlueAccent,};
}
这是我的 EditJob 页面,其中包含文本输入
import 'package:flutter/material.dart';
import 'package:my_time_tracker/common_widgets/custom_text_style.dart';
//import 'package:my_time_tracker/common_widgets/firebase_exception_alert_dialog.dart';
import 'package:my_time_tracker/common_widgets/form_submit_button.dart';
import 'package:my_time_tracker/common_widgets/platform_alert_dialog.dart';
import 'package:my_time_tracker/common_widgets/show_snack_bar.dart';
import 'package:my_time_tracker/services/database.dart';
import 'package:provider/provider.dart';
import '../models/job.dart';
class EditJobPage extends StatefulWidget {
final Database database;
final Job job;
final ValueChanged<int> onPush;
const EditJobPage({Key key,@required this.database,this.job,this.onPush})
: super(key: key);
static Future<void> show(BuildContext context,{Job job}) async {
final database = Provider.of<Database>(context,listen: false);
await Navigator.of(context,rootNavigator: true).push(MaterialPageRoute(
fullscreenDialog: true,builder: (context) => EditJobPage(
database: database,job: job,));
}
@override
_EditJobPageState createState() => _EditJobPageState();
}
class _EditJobPageState extends State<EditJobPage> {
final _formKey = GlobalKey<FormState>();
String _name;
int _ratePerHour;
bool isLoading = false;
@override
void initState() {
super.initState();
if (widget.job != null) {
_name = widget.job.name;
_ratePerHour = widget.job.ratePerHour;
}
}
bool _validateAndSaveForm() {
final form = _formKey.currentState;
if (form.validate()) {
form.save();
return true;
}
return false;
}
String get scaffoldContent {
if (widget.job != null) {
return '${widget.job.name} updated successfully.';
} else {
return '$_name added successfully.';
}
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.teal),title: Text(
widget.job == null ? 'New Job' : 'Edit Job',style: CustomTextStyles.textStyleTitle(
fontSize: size.height * 0.035,color: Colors.teal,centerTitle: true,elevation: 0.0,body: _buildContent(),);
}
InputDecoration _buildInputDecoration(
String labelText,IconData icon,bool value,) {
Size size = MediaQuery.of(context).size;
return InputDecoration(
labelText: labelText,labelStyle: CustomTextStyles.textStyleBold(fontSize: size.height * 0.025),icon: Icon(
icon,color: Colors.teal[700],size: size.height * 0.05,enabled: value,);
}
Widget _buildContent() {
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),child: Card(
elevation: 5.0,child: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),child: _buildForm(),SizedBox(
height: 5.0,SizedBox(
width: MediaQuery.of(context).size.width * 0.62,child: FormSubmitButton(
onPressed: isLoading ? null : _submit,text: 'Save',SizedBox(
height: 15.0,);
}
Widget _buildForm() {
return Form(
key: _formKey,autovalidateMode: AutovalidateMode.onUserInteraction,child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,children: _buildFormChildren(),);
}
List<Widget> _buildFormChildren() {
return [
_buildJobNameField(),_buildJobRateField(),SizedBox(
height: 15.0,)
];
}
Widget _buildJobNameField() {
return TextFormField(
decoration: _buildInputDecoration(
'Job name',Icons.work,isLoading == false,initialValue: _name,validator: (value) =>
value == null || value.isEmpty ? 'Name can\'t be empty' : null,textInputAction: TextInputAction.next,textCapitalization: TextCapitalization.words,onSaved: (value) => _name = value,);
}
Widget _buildJobRateField() {
return TextFormField(
decoration: _buildInputDecoration(
'Rate Per Hour',Icons.attach_money,initialValue: _ratePerHour != null ? '$_ratePerHour' : '',keyboardType:
TextInputType.numberWithOptions(decimal: false,signed: false),onSaved: (value) => _ratePerHour = int.tryParse(value) ?? 0,onEditingComplete: _submit,);
}
Future<void> _submit() async {
//Future.delayed(Duration(seconds: 5));
if (_validateAndSaveForm()) {
print('Error doesnt occur here0');
setState(() {
isLoading = true;
});
print('Error doesnt occur here1');
try {
final jobs = await widget.database
.jobsStream()
.first
.onError((error,stackTrace) {
return Future.error(error);
});
print('Error doesnt occur here2');
final allNames = jobs.map((job) => job.name).toList();
if (widget.job != null) {
allNames.remove(widget.job.name);
}
if (allNames.contains(_name)) {
PlatformAlertDialog(
title: 'Job already exist',content: 'Please use a different job name.',defaultActionText: 'Ok',).show(context);
} else {
final id = widget.job?.id ?? documentIdFromCurrentDate();
final job = Job(
id: id,name: _name,ratePerHour: _ratePerHour,);
await widget.database.setJob(job);
print('Error doesnt occur here5');
Navigator.of(context).pop();
MyCustomSnackBar(
enabled: widget.job == null ? true : false,text: scaffoldContent,onPressed: () => widget.database.deleteJob(job),).show(context);
}
} catch (e) {
// FirebaseExceptionAlertDialog(title: 'Operation Failed',exception: e)
// .show(context);
print(e);
}
setState(() {
isLoading = false;
});
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。