我的平面按钮就在我的文本字段下面,当键盘出现时,它会被隐藏起来



例如,在FlutterDev上提供的一个包中,我进行了一些编辑。下面是代码。如何让我的BottomButton在T点击textfield后立即显示?

(p.S.BottomButton已经在另一个文件中定义了,不用担心。我试过这样做——如果你愿意的话,请参阅底部——但没有完成任务。(

这是代码:

//library international_phone_input;
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:international_phone_input/src/phone_service.dart';
import 'country.dart';
import 'package:byteseal/components/bottom_button.dart';
import 'package:byteseal/screens/otp_screen1.dart';
class InternationalPhoneInput extends StatefulWidget {
final void Function(String phoneNumber, String internationalizedPhoneNumber,
String isoCode) onPhoneNumberChange;
final String initialPhoneNumber;
final String initialSelection;
final String errorText;
final String hintText;
final String labelText;
final TextStyle errorStyle;
final TextStyle hintStyle;
final TextStyle labelStyle;
final int errorMaxLines;
final List<String> enabledCountries;
final InputDecoration decoration;
final bool showCountryCodes;
final bool showCountryFlags;
final Widget dropdownIcon;
final InputBorder border;
InternationalPhoneInput(
{this.onPhoneNumberChange,
this.initialPhoneNumber,
this.initialSelection,
this.errorText,
this.hintText,
this.labelText,
this.errorStyle,
this.hintStyle,
this.labelStyle,
this.enabledCountries = const [],
this.errorMaxLines,
this.decoration,
this.showCountryCodes = true,
this.showCountryFlags = true,
this.dropdownIcon,
this.border});
static Future<String> internationalizeNumber(String number, String iso) {
return PhoneService.getNormalizedPhoneNumber(number, iso);
}
@override
_InternationalPhoneInputState createState() =>
_InternationalPhoneInputState();
}
class _InternationalPhoneInputState extends State<InternationalPhoneInput> {
Country selectedItem;
List<Country> itemList = [];
String errorText;
String hintText;
String labelText;
TextStyle errorStyle;
TextStyle hintStyle;
TextStyle labelStyle;
int errorMaxLines;
bool hasError = false;
bool showCountryCodes;
bool showCountryFlags;
InputDecoration decoration;
Widget dropdownIcon;
InputBorder border;
_InternationalPhoneInputState();
final phoneTextController = TextEditingController();
@override
void initState() {
errorText = widget.errorText ?? 'Please enter a valid phone number';
hintText = widget.hintText ?? 'eg. 244056345';
labelText = widget.labelText;
errorStyle = widget.errorStyle;
hintStyle = widget.hintStyle;
labelStyle = widget.labelStyle;
errorMaxLines = widget.errorMaxLines;
decoration = widget.decoration;
showCountryCodes = widget.showCountryCodes;
showCountryFlags = widget.showCountryFlags;
dropdownIcon = widget.dropdownIcon;
phoneTextController.addListener(_validatePhoneNumber);
phoneTextController.text = widget.initialPhoneNumber;
_fetchCountryData().then((list) {
Country preSelectedItem;
if (widget.initialSelection != null) {
preSelectedItem = list.firstWhere(
(e) =>
(e.code.toUpperCase() ==
widget.initialSelection.toUpperCase()) ||
(e.dialCode == widget.initialSelection.toString()),
orElse: () => list[0]);
} else {
preSelectedItem = list[0];
}
setState(() {
itemList = list;
selectedItem = preSelectedItem;
});
});
super.initState();
}
_validatePhoneNumber() {
String phoneText = phoneTextController.text;
if (phoneText != null && phoneText.isNotEmpty) {
PhoneService.parsePhoneNumber(phoneText, selectedItem.code)
.then((isValid) {
setState(() {
hasError = !isValid;
});
if (widget.onPhoneNumberChange != null) {
if (isValid) {
PhoneService.getNormalizedPhoneNumber(phoneText, selectedItem.code)
.then((number) {
widget.onPhoneNumberChange(phoneText, number, selectedItem.code);
});
} else {
widget.onPhoneNumberChange('', '', selectedItem.code);
}
}
});
}
}
Future<List<Country>> _fetchCountryData() async {
var list = await DefaultAssetBundle.of(context)
.loadString('packages/international_phone_input/assets/countries.json');
List<dynamic> jsonList = json.decode(list);
List<Country> countries = List<Country>.generate(jsonList.length, (index) {
Map<String, String> elem = Map<String, String>.from(jsonList[index]);
if (widget.enabledCountries.isEmpty) {
return Country(
name: elem['en_short_name'],
code: elem['alpha_2_code'],
dialCode: elem['dial_code'],
flagUri: 'assets/flags/${elem['alpha_2_code'].toLowerCase()}.png');
} else if (widget.enabledCountries.contains(elem['alpha_2_code']) ||
widget.enabledCountries.contains(elem['dial_code'])) {
return Country(
name: elem['en_short_name'],
code: elem['alpha_2_code'],
dialCode: elem['dial_code'],
flagUri: 'assets/flags/${elem['alpha_2_code'].toLowerCase()}.png');
} else {
return null;
}
});
countries.removeWhere((value) => value == null);
return countries;
}
@override
Widget build(BuildContext context) {
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
DropdownButtonHideUnderline(
child: Padding(
padding: EdgeInsets.only(top: 8),
child: DropdownButton<Country>(
value: selectedItem,
icon: Padding(
padding:
EdgeInsets.only(bottom: (decoration != null) ? 6 : 0),
child: dropdownIcon ?? Icon(Icons.arrow_drop_down),
),
onChanged: (Country newValue) {
setState(() {
selectedItem = newValue;
});
_validatePhoneNumber();
},
items: itemList.map<DropdownMenuItem<Country>>((Country value) {
return DropdownMenuItem<Country>(
value: value,
child: Container(
padding: const EdgeInsets.only(bottom: 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
if (showCountryFlags) ...[
Image.asset(
value.flagUri,
width: 32.0,
package: 'international_phone_input',
)
],
if (showCountryCodes) ...[
SizedBox(width: 4),
Text(value.dialCode, style: TextStyle(color: Colors.white),)
]
],
),
),
);
}).toList(),
),
),
),
Flexible(
child: TextField(
keyboardType: TextInputType.phone,
style: TextStyle(
color: Colors.white,
),
controller: phoneTextController,
decoration: decoration ??
InputDecoration(
hintText: hintText,
labelText: labelText,
errorText: hasError ? errorText : null,
hintStyle: hintStyle ?? null,
errorStyle: errorStyle ?? null,
labelStyle: labelStyle,
errorMaxLines: errorMaxLines ?? 3,
border: border ?? null,
),
onTap: () {
setState(() {
BottomButton(
buttonTitle: 'Next',
onTap: (info) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OTPScreen(number: phoneTextController.text, iso: info),
)
);
});
});
},
// onTap: BottomButton(
//     buttonTitle: 'Next',
//     onTap: () {
//       Navigator.push(
//           context,
//           MaterialPageRoute(
//             builder: (context) => OTPScreen(number: phoneTextController.value, iso: selectedItem),
//           )
//       );
//     }),
))
],
),
);
}
}

文本字段应使用GestureDetector(child: TextField, onTap: setState() {buttonShown = true})包装,按钮应使用参数Visibility(visibility: buttonShown, child: BottomButton)包装在Visibility()

使用带有FocusNodeVisiblity widget的有状态小部件

创建一个布尔值来保存可见状态和FocusNode对象。将FocusNode的侦听器设置为可以更改按钮可见性布尔值状态的方法。

bool buttonVisible;
FocusNode _focus = new FocusNode();
@override
void initState() {
super.initState();
buttonVisible = false;
_focus.addListener(_changeVisibility);
}
void _changeVisibility() {
setState(() {
buttonVisible = true;
});
}

然后使用带有TextField的Column和以按钮为子项的Visibility Widget。将可见性小部件的可见属性设置为您之前定义的按钮可见性布尔值。

Column(
children: <Widget>[
TextField(
focusNode: _focus,
),
Visibility(
visible: buttonVisible,
child: RaisedButton(
onPressed: () { },
child: Text("My Button")
),
),
]
)

相关内容

最新更新