如何用 Flutter 做这个 bottomsheet?
How to do this bottomsheet with Flutter?
底页怎么能这样?
BottomSheet(
onClosing: () {},
builder: (context) {
return Container(
height: 200,
width: double.infinity,
color: Colors.grey.shade200,
alignment: Alignment.center,
child: Text('Bottomsheet'),
);
},
);
这会让您了解如何制作自定义键盘,custom-in-app-keyboard:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: KeyboardDemo(),
);
}
}
class KeyboardDemo extends StatefulWidget {
@override
_KeyboardDemoState createState() => _KeyboardDemoState();
}
class _KeyboardDemoState extends State<KeyboardDemo> {
TextEditingController _controller = TextEditingController();
bool _readOnly = true;
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: [
SizedBox(height: 50),
TextField(
controller: _controller,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(3),
),
),
style: TextStyle(fontSize: 24),
autofocus: true,
showCursor: true,
readOnly: _readOnly,
),
IconButton(
icon: Icon(Icons.keyboard),
onPressed: () {
setState(() {
_readOnly = !_readOnly;
});
},
),
Spacer(),
CustomKeyboard(
onTextInput: (myText) {
_insertText(myText);
},
onBackspace: () {
_backspace();
},
),
],
),
);
}
void _insertText(String myText) {
final text = _controller.text;
final textSelection = _controller.selection;
final newText = text.replaceRange(
textSelection.start,
textSelection.end,
myText,
);
final myTextLength = myText.length;
_controller.text = newText;
_controller.selection = textSelection.copyWith(
baseOffset: textSelection.start + myTextLength,
extentOffset: textSelection.start + myTextLength,
);
}
void _backspace() {
final text = _controller.text;
final textSelection = _controller.selection;
final selectionLength = textSelection.end - textSelection.start;
// There is a selection.
if (selectionLength > 0) {
final newText = text.replaceRange(
textSelection.start,
textSelection.end,
'',
);
_controller.text = newText;
_controller.selection = textSelection.copyWith(
baseOffset: textSelection.start,
extentOffset: textSelection.start,
);
return;
}
// The cursor is at the beginning.
if (textSelection.start == 0) {
return;
}
// Delete the previous character
final previousCodeUnit = text.codeUnitAt(textSelection.start - 1);
final offset = _isUtf16Surrogate(previousCodeUnit) ? 2 : 1;
final newStart = textSelection.start - offset;
final newEnd = textSelection.start;
final newText = text.replaceRange(
newStart,
newEnd,
'',
);
_controller.text = newText;
_controller.selection = textSelection.copyWith(
baseOffset: newStart,
extentOffset: newStart,
);
}
bool _isUtf16Surrogate(int value) {
return value & 0xF800 == 0xD800;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
class CustomKeyboard extends StatelessWidget {
CustomKeyboard({
Key key,
this.onTextInput,
this.onBackspace,
}) : super(key: key);
final ValueSetter<String> onTextInput;
final VoidCallback onBackspace;
void _textInputHandler(String text) => onTextInput?.call(text);
void _backspaceHandler() => onBackspace?.call();
@override
Widget build(BuildContext context) {
return Container(
height: 160,
color: Colors.blue,
child: Column(
children: [
buildRowOne(),
buildRowTwo(),
buildRowThree(),
],
),
);
}
Expanded buildRowOne() {
return Expanded(
child: Row(
children: [
TextKey(
text: '1',
onTextInput: _textInputHandler,
),
TextKey(
text: '2',
onTextInput: _textInputHandler,
),
TextKey(
text: '3',
onTextInput: _textInputHandler,
),
TextKey(
text: '4',
onTextInput: _textInputHandler,
),
TextKey(
text: '5',
onTextInput: _textInputHandler,
),
],
),
);
}
Expanded buildRowTwo() {
return Expanded(
child: Row(
children: [
TextKey(
text: 'a',
onTextInput: _textInputHandler,
),
TextKey(
text: 'b',
onTextInput: _textInputHandler,
),
TextKey(
text: 'c',
onTextInput: _textInputHandler,
),
TextKey(
text: 'd',
onTextInput: _textInputHandler,
),
TextKey(
text: 'e',
onTextInput: _textInputHandler,
),
],
),
);
}
Expanded buildRowThree() {
return Expanded(
child: Row(
children: [
TextKey(
text: ' ',
flex: 4,
onTextInput: _textInputHandler,
),
BackspaceKey(
onBackspace: _backspaceHandler,
),
],
),
);
}
}
class TextKey extends StatelessWidget {
const TextKey({
Key key,
@required this.text,
this.onTextInput,
this.flex = 1,
}) : super(key: key);
final String text;
final ValueSetter<String> onTextInput;
final int flex;
@override
Widget build(BuildContext context) {
return Expanded(
flex: flex,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Material(
color: Colors.blue.shade300,
child: InkWell(
onTap: () {
onTextInput?.call(text);
},
child: Container(
child: Center(child: Text(text)),
),
),
),
),
);
}
}
class BackspaceKey extends StatelessWidget {
const BackspaceKey({
Key key,
this.onBackspace,
this.flex = 1,
}) : super(key: key);
final VoidCallback onBackspace;
final int flex;
@override
Widget build(BuildContext context) {
return Expanded(
flex: flex,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Material(
color: Colors.blue.shade300,
child: InkWell(
onTap: () {
onBackspace?.call();
},
child: Container(
child: Center(
child: Icon(Icons.backspace),
),
),
),
),
),
);
}
}
家你可以玩风格和设计键盘。
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// home: LayoutControll(),
home: Scaffold(body: SampleTT()),
);
}
}
class SampleTT extends StatefulWidget {
const SampleTT({Key? key}) : super(key: key);
@override
_SampleTTState createState() => _SampleTTState();
}
class _SampleTTState extends State<SampleTT> {
final TextEditingController controller = TextEditingController();
bool _isFocued = false;
textField(BuildContext context) => Padding(
padding: const EdgeInsets.all(2.0),
child: TextField(
controller: controller,
onTap: () {
setState(() {
_isFocued = true;
});
_showBottomSheet(context);
},
textAlign: TextAlign.end,
textCapitalization: TextCapitalization.words,
keyboardType: TextInputType.text,
decoration: InputDecoration(fillColor: Colors.white, filled: true),
showCursor: true,
readOnly: true,
),
);
_showBottomSheet(BuildContext context) {
showBottomSheet(
context: context,
builder: (context) => Container(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(
onPressed: () {
setState(() {
controller.text = "${controller.text}1";
});
},
child: Text("1"),
),
ElevatedButton(
onPressed: () {
setState(() {
controller.text = "${controller.text}3";
});
},
child: Text("3"),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(
onPressed: () {
setState(() {
controller.text = "${controller.text}5";
});
},
child: Text("5"),
),
ElevatedButton(
onPressed: () {
setState(() {
_isFocued = false;
});
Navigator.of(context).pop();
},
child: Text("Done"),
),
],
)
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
SizedBox(
height: 100,
),
Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.blue, width: 1),
),
child: _isFocued
? textField(context)
: Column(
children: [
textField(context),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(
Icons.send,
color: Colors.white,
),
Text("Send to USD to CAD"),
],
),
Text("View qoute"),
],
),
),
],
)),
],
),
);
}
}
底页怎么能这样?
BottomSheet(
onClosing: () {},
builder: (context) {
return Container(
height: 200,
width: double.infinity,
color: Colors.grey.shade200,
alignment: Alignment.center,
child: Text('Bottomsheet'),
);
},
);
这会让您了解如何制作自定义键盘,custom-in-app-keyboard:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: KeyboardDemo(),
);
}
}
class KeyboardDemo extends StatefulWidget {
@override
_KeyboardDemoState createState() => _KeyboardDemoState();
}
class _KeyboardDemoState extends State<KeyboardDemo> {
TextEditingController _controller = TextEditingController();
bool _readOnly = true;
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: [
SizedBox(height: 50),
TextField(
controller: _controller,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(3),
),
),
style: TextStyle(fontSize: 24),
autofocus: true,
showCursor: true,
readOnly: _readOnly,
),
IconButton(
icon: Icon(Icons.keyboard),
onPressed: () {
setState(() {
_readOnly = !_readOnly;
});
},
),
Spacer(),
CustomKeyboard(
onTextInput: (myText) {
_insertText(myText);
},
onBackspace: () {
_backspace();
},
),
],
),
);
}
void _insertText(String myText) {
final text = _controller.text;
final textSelection = _controller.selection;
final newText = text.replaceRange(
textSelection.start,
textSelection.end,
myText,
);
final myTextLength = myText.length;
_controller.text = newText;
_controller.selection = textSelection.copyWith(
baseOffset: textSelection.start + myTextLength,
extentOffset: textSelection.start + myTextLength,
);
}
void _backspace() {
final text = _controller.text;
final textSelection = _controller.selection;
final selectionLength = textSelection.end - textSelection.start;
// There is a selection.
if (selectionLength > 0) {
final newText = text.replaceRange(
textSelection.start,
textSelection.end,
'',
);
_controller.text = newText;
_controller.selection = textSelection.copyWith(
baseOffset: textSelection.start,
extentOffset: textSelection.start,
);
return;
}
// The cursor is at the beginning.
if (textSelection.start == 0) {
return;
}
// Delete the previous character
final previousCodeUnit = text.codeUnitAt(textSelection.start - 1);
final offset = _isUtf16Surrogate(previousCodeUnit) ? 2 : 1;
final newStart = textSelection.start - offset;
final newEnd = textSelection.start;
final newText = text.replaceRange(
newStart,
newEnd,
'',
);
_controller.text = newText;
_controller.selection = textSelection.copyWith(
baseOffset: newStart,
extentOffset: newStart,
);
}
bool _isUtf16Surrogate(int value) {
return value & 0xF800 == 0xD800;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
class CustomKeyboard extends StatelessWidget {
CustomKeyboard({
Key key,
this.onTextInput,
this.onBackspace,
}) : super(key: key);
final ValueSetter<String> onTextInput;
final VoidCallback onBackspace;
void _textInputHandler(String text) => onTextInput?.call(text);
void _backspaceHandler() => onBackspace?.call();
@override
Widget build(BuildContext context) {
return Container(
height: 160,
color: Colors.blue,
child: Column(
children: [
buildRowOne(),
buildRowTwo(),
buildRowThree(),
],
),
);
}
Expanded buildRowOne() {
return Expanded(
child: Row(
children: [
TextKey(
text: '1',
onTextInput: _textInputHandler,
),
TextKey(
text: '2',
onTextInput: _textInputHandler,
),
TextKey(
text: '3',
onTextInput: _textInputHandler,
),
TextKey(
text: '4',
onTextInput: _textInputHandler,
),
TextKey(
text: '5',
onTextInput: _textInputHandler,
),
],
),
);
}
Expanded buildRowTwo() {
return Expanded(
child: Row(
children: [
TextKey(
text: 'a',
onTextInput: _textInputHandler,
),
TextKey(
text: 'b',
onTextInput: _textInputHandler,
),
TextKey(
text: 'c',
onTextInput: _textInputHandler,
),
TextKey(
text: 'd',
onTextInput: _textInputHandler,
),
TextKey(
text: 'e',
onTextInput: _textInputHandler,
),
],
),
);
}
Expanded buildRowThree() {
return Expanded(
child: Row(
children: [
TextKey(
text: ' ',
flex: 4,
onTextInput: _textInputHandler,
),
BackspaceKey(
onBackspace: _backspaceHandler,
),
],
),
);
}
}
class TextKey extends StatelessWidget {
const TextKey({
Key key,
@required this.text,
this.onTextInput,
this.flex = 1,
}) : super(key: key);
final String text;
final ValueSetter<String> onTextInput;
final int flex;
@override
Widget build(BuildContext context) {
return Expanded(
flex: flex,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Material(
color: Colors.blue.shade300,
child: InkWell(
onTap: () {
onTextInput?.call(text);
},
child: Container(
child: Center(child: Text(text)),
),
),
),
),
);
}
}
class BackspaceKey extends StatelessWidget {
const BackspaceKey({
Key key,
this.onBackspace,
this.flex = 1,
}) : super(key: key);
final VoidCallback onBackspace;
final int flex;
@override
Widget build(BuildContext context) {
return Expanded(
flex: flex,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Material(
color: Colors.blue.shade300,
child: InkWell(
onTap: () {
onBackspace?.call();
},
child: Container(
child: Center(
child: Icon(Icons.backspace),
),
),
),
),
),
);
}
}
家你可以玩风格和设计键盘。
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// home: LayoutControll(),
home: Scaffold(body: SampleTT()),
);
}
}
class SampleTT extends StatefulWidget {
const SampleTT({Key? key}) : super(key: key);
@override
_SampleTTState createState() => _SampleTTState();
}
class _SampleTTState extends State<SampleTT> {
final TextEditingController controller = TextEditingController();
bool _isFocued = false;
textField(BuildContext context) => Padding(
padding: const EdgeInsets.all(2.0),
child: TextField(
controller: controller,
onTap: () {
setState(() {
_isFocued = true;
});
_showBottomSheet(context);
},
textAlign: TextAlign.end,
textCapitalization: TextCapitalization.words,
keyboardType: TextInputType.text,
decoration: InputDecoration(fillColor: Colors.white, filled: true),
showCursor: true,
readOnly: true,
),
);
_showBottomSheet(BuildContext context) {
showBottomSheet(
context: context,
builder: (context) => Container(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(
onPressed: () {
setState(() {
controller.text = "${controller.text}1";
});
},
child: Text("1"),
),
ElevatedButton(
onPressed: () {
setState(() {
controller.text = "${controller.text}3";
});
},
child: Text("3"),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(
onPressed: () {
setState(() {
controller.text = "${controller.text}5";
});
},
child: Text("5"),
),
ElevatedButton(
onPressed: () {
setState(() {
_isFocued = false;
});
Navigator.of(context).pop();
},
child: Text("Done"),
),
],
)
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
SizedBox(
height: 100,
),
Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.blue, width: 1),
),
child: _isFocued
? textField(context)
: Column(
children: [
textField(context),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(
Icons.send,
color: Colors.white,
),
Text("Send to USD to CAD"),
],
),
Text("View qoute"),
],
),
),
],
)),
],
),
);
}
}