Flutter-Widgets: Unterschied zwischen den Versionen
Die Seite wurde neu angelegt: „= Links = * Flutter = Häufige Widgets = == Column / Row == Ein Container, in dem die Unterelemente senkrecht (Column) oder waagrecht (Row) angeordnet wer…“ |
|||
| (7 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 8: | Zeile 8: | ||
<pre> | <pre> | ||
List<Widget> = [ | List<Widget> = [ | ||
Col( children = [ | Col( | ||
crossAxisAlignment: CrossAxisAlignment.start, | |||
children = [ | |||
Row( children: [ | |||
Expanded( | |||
child: const Text('Be surprised!'), | |||
), | |||
const SizedBox(width: 16), | |||
ElevatedButton( | |||
child: Text('Click it'), | |||
onPressed: () => sayHello(), | |||
), | |||
]), | |||
const SizedBox(height: 16), | |||
Row( children: [ | |||
const Expanded (flex: 7, | |||
child: Text('You need help?'), | |||
), | ), | ||
const SizedBox(height: padding), | |||
const Expanded (flex: 2, | |||
child: ElevatedButton( | |||
child: Text('Help me'), | |||
onPressed: () => help(), | |||
), | |||
), | ), | ||
]), | ]), | ||
]), | |||
]; | ]; | ||
</pre> | </pre> | ||
=== Platzverteilung === | === Platzverteilung === | ||
Normalerweise bestimmen die Unterelemente (children) die Dimensionen, sie werden einfach untereinander / hintereinander positioniert. | Normalerweise bestimmen die Unterelemente (<code>children</code>) die Dimensionen, sie werden einfach untereinander / hintereinander positioniert. | ||
Will man eine '''automatische Anpassung''', werden die "dynamischen" Elemente jeweils in ein '''Expanded'''-Element eingebettet. | Will man eine '''automatische Anpassung''', werden die "dynamischen" Elemente jeweils in ein '''Expanded'''-Element eingebettet. | ||
In diesem Fall wird der Restplatz an alle dynamischen Elemente gleichmäßig verteilt. Mit dem Parameter | In diesem Fall wird der Restplatz an alle dynamischen Elemente gleichmäßig verteilt. Mit dem Parameter <code>flex</code> von Expanded kann das Verhältnis eingestellt werden. | ||
= Formular = | = Card = | ||
<pre> | |||
final widget = Card( | |||
margin: EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0), | |||
child: Padding( | |||
padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0), | |||
child: Text('Wow!'), | |||
), | |||
); | |||
</pre> | |||
= Abwandlungen = | |||
== Visibility == | |||
Damit kann die Sichtbarkeit eines Elements gesteuert werden. Ganz wichtig für GetX-Layouts! | |||
Im folgenden Beispiel wird entweder das eine oder das andere Element angezeigt. | |||
<pre> | |||
final widgets = <Widget>[ | |||
Visibility( | |||
visible: controller.isEmpty.value, | |||
child: buildEmptyImage() | |||
), | |||
Visibility( | |||
visible: !controller.isEmpty.value, | |||
child: buildImage() | |||
), | |||
]; | |||
</pre> | |||
== Tooltip == | |||
Dieses Element erzeugt einen Erklärungstext, der erscheint, wenn die Maus kurz auf dem Kindelement verweilt. | |||
<pre> | |||
final widget = Tooltip( | |||
message: 'Löschen', | |||
child: Icon(Icons.delete_forever_outlined) | |||
); | |||
</pre> | |||
== Inkwell (Reaktionsfläche) == | |||
Mit diesem Element ist es möglich, eine Aktion zu definieren, wenn das Kindelement berührt/angeklickt wird. | |||
<pre> | |||
final Widget = Material( | |||
color: Colors.green, | |||
child: InkWell( | |||
onTap: () async { Get.toNamed(Routes.routeAction); } | |||
child: SizedBox(width: 200, height: 200, child: image.value,), | |||
), | |||
); | |||
</pre> | |||
= Formular (Text und Dropdown) = | |||
Jedes Formular benötigt einen '''Key''', der normalerweise im Controller erzeugt/gespeichert wird: | Jedes Formular benötigt einen '''Key''', der normalerweise im Controller erzeugt/gespeichert wird: | ||
| Zeile 56: | Zeile 108: | ||
<pre> | <pre> | ||
final items = [ | |||
DropdownMenuItem<bool>(value: false, child: Text('inaktive)), | |||
DropdownMenuItem<bool>(value: true, child: Text('active)) | |||
]; | |||
final form = Form( | final form = Form( | ||
key: controller.formKey, | key: controller.formKey, | ||
| Zeile 61: | Zeile 117: | ||
children: [ | children: [ | ||
TextFormField( | TextFormField( | ||
decoration: InputDecoration(labelText: 'Age'), | |||
validator: checkInt, | validator: checkInt, | ||
onSaved: (input) => controller. | onSaved: (input) => controller.age.value = input, | ||
controller: , | controller: controller.controllerAge, | ||
), | |||
DropdownButtonFormField<bool>( | |||
value: fieldData.locationId, | |||
items: items, | |||
isExpanded: true, | |||
decoration: const InputDecoration(labelText: 'Status'), | |||
onSaved: (value) => controller.status.value = value, | |||
), | ), | ||
]), | ]), | ||
| Zeile 70: | Zeile 134: | ||
void store(controller, String input){ | void store(controller, String input){ | ||
if (controller, formKey.currentState?.validate() ?? false) { | |||
controller.formKey.currentState?.save(); | |||
} | |||
} | } | ||
</pre> | |||
= DropDownButton (Combobox) = | |||
<pre> | <pre> | ||
final items1 = [ | |||
DropdownMenuItem(child: Image.asset('img/undefined.png'), value: ''), | |||
DropdownMenuItem(child: Text('Active'), value: 'A'), | |||
DropdownMenuItem(child: Text('Inactive'), value: 'I'), | |||
]; | |||
final button1 = DropdownButton<String>( | |||
value: '', | |||
items: items1, | |||
onChanged: (value) { | |||
controller.active = value | |||
}, | |||
); | |||
final item2 = List<int>generate(5, (i) => i+1).map((no) => DropdownMenuItem(child: Text('Element $no'), value: no)); | |||
final button2 = DropdownButton<int>( | |||
value: 0, | |||
items: items2, | |||
onChanged: (value) { | |||
controller.no = value | |||
}, | |||
); | |||
</pre> | |||
== DropDownField == | |||
<pre> | |||
import 'package:dropdown_textfield/dropdown_textfield.dart'; | |||
... | |||
final widget = DropDownTextField( | |||
// initialValue: "name4", | |||
controller: controller.nameController, | |||
clearOption: false, | |||
enableSearch: true, | |||
searchDecoration: const InputDecoration(hintText: "Type part of the name"), | |||
validator: (value) value != null ? null : "Required field", | |||
dropDownItemCount: 6, | |||
dropDownList: const [ | |||
DropDownValueModel(name: 'name1', value: "value1"), | |||
DropDownValueModel(name: 'name2', value: "value2", toolTipMsg: "Select an item from the list"), | |||
DropDownValueModel(name: 'name3', value: "value3"), | |||
DropDownValueModel(name: 'name4', value: "value4", toolTipMsg: "This is value4", | |||
], | |||
onChanged: (val) { controller.selectedName = val; }, | |||
); | |||
</pre> | |||
= Rückgabe der GetView.build() Methode = | = Rückgabe der GetView.build() Methode = | ||
Aktuelle Version vom 27. September 2022, 05:06 Uhr
Links
[Bearbeiten]Häufige Widgets
[Bearbeiten]Column / Row
[Bearbeiten]Ein Container, in dem die Unterelemente senkrecht (Column) oder waagrecht (Row) angeordnet werden. Die Unterelemente bestimmen
List<Widget> = [
Col(
crossAxisAlignment: CrossAxisAlignment.start,
children = [
Row( children: [
Expanded(
child: const Text('Be surprised!'),
),
const SizedBox(width: 16),
ElevatedButton(
child: Text('Click it'),
onPressed: () => sayHello(),
),
]),
const SizedBox(height: 16),
Row( children: [
const Expanded (flex: 7,
child: Text('You need help?'),
),
const SizedBox(height: padding),
const Expanded (flex: 2,
child: ElevatedButton(
child: Text('Help me'),
onPressed: () => help(),
),
),
]),
]),
];
Platzverteilung
[Bearbeiten]Normalerweise bestimmen die Unterelemente (children) die Dimensionen, sie werden einfach untereinander / hintereinander positioniert.
Will man eine automatische Anpassung, werden die "dynamischen" Elemente jeweils in ein Expanded-Element eingebettet.
In diesem Fall wird der Restplatz an alle dynamischen Elemente gleichmäßig verteilt. Mit dem Parameter flex von Expanded kann das Verhältnis eingestellt werden.
Card
[Bearbeiten]final widget = Card(
margin: EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: Padding(
padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: Text('Wow!'),
),
);
Abwandlungen
[Bearbeiten]Visibility
[Bearbeiten]Damit kann die Sichtbarkeit eines Elements gesteuert werden. Ganz wichtig für GetX-Layouts!
Im folgenden Beispiel wird entweder das eine oder das andere Element angezeigt.
final widgets = <Widget>[
Visibility(
visible: controller.isEmpty.value,
child: buildEmptyImage()
),
Visibility(
visible: !controller.isEmpty.value,
child: buildImage()
),
];
Tooltip
[Bearbeiten]Dieses Element erzeugt einen Erklärungstext, der erscheint, wenn die Maus kurz auf dem Kindelement verweilt.
final widget = Tooltip( message: 'Löschen', child: Icon(Icons.delete_forever_outlined) );
Inkwell (Reaktionsfläche)
[Bearbeiten]Mit diesem Element ist es möglich, eine Aktion zu definieren, wenn das Kindelement berührt/angeklickt wird.
final Widget = Material(
color: Colors.green,
child: InkWell(
onTap: () async { Get.toNamed(Routes.routeAction); }
child: SizedBox(width: 200, height: 200, child: image.value,),
),
);
Formular (Text und Dropdown)
[Bearbeiten]Jedes Formular benötigt einen Key, der normalerweise im Controller erzeugt/gespeichert wird:
key = GlobalKey<FormState>(debugLabel: 'MyForm');
Ein Formular bietet die Möglichkeit der Eingabeprüfung (Validierung).
- Dazu wird für jedes Formularfeld eine (eventuell anonyme) Funktion angegeben, die im Fehlerfall einen Fehlertext zurückgibt, sonst
null. - Außerdem hat das Formularfeld einen Parameter
onSave, der eine Funktion entgegennimmt, die das Speichern des Wertes übernimmt. - Die Validierung wird normalerweise beim Anklicken eines Buttons angestoßen: Alle Textfelder werden validiert.
- Ist die Validierung erfolgreich, wird
formKey.currentKey.store()aufgerufen. - Dies löst bei allen Textfeldern den Aufruf der Parameterfunktion
onSaveauf.
final items = [
DropdownMenuItem<bool>(value: false, child: Text('inaktive)),
DropdownMenuItem<bool>(value: true, child: Text('active))
];
final form = Form(
key: controller.formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'Age'),
validator: checkInt,
onSaved: (input) => controller.age.value = input,
controller: controller.controllerAge,
),
DropdownButtonFormField<bool>(
value: fieldData.locationId,
items: items,
isExpanded: true,
decoration: const InputDecoration(labelText: 'Status'),
onSaved: (value) => controller.status.value = value,
),
]),
);
String? checkInt(String input) int.parseInt(input) == null ? 'Not an integer' : null;
void store(controller, String input){
if (controller, formKey.currentState?.validate() ?? false) {
controller.formKey.currentState?.save();
}
}
DropDownButton (Combobox)
[Bearbeiten]final items1 = [
DropdownMenuItem(child: Image.asset('img/undefined.png'), value: ''),
DropdownMenuItem(child: Text('Active'), value: 'A'),
DropdownMenuItem(child: Text('Inactive'), value: 'I'),
];
final button1 = DropdownButton<String>(
value: '',
items: items1,
onChanged: (value) {
controller.active = value
},
);
final item2 = List<int>generate(5, (i) => i+1).map((no) => DropdownMenuItem(child: Text('Element $no'), value: no));
final button2 = DropdownButton<int>(
value: 0,
items: items2,
onChanged: (value) {
controller.no = value
},
);
DropDownField
[Bearbeiten]import 'package:dropdown_textfield/dropdown_textfield.dart';
...
final widget = DropDownTextField(
// initialValue: "name4",
controller: controller.nameController,
clearOption: false,
enableSearch: true,
searchDecoration: const InputDecoration(hintText: "Type part of the name"),
validator: (value) value != null ? null : "Required field",
dropDownItemCount: 6,
dropDownList: const [
DropDownValueModel(name: 'name1', value: "value1"),
DropDownValueModel(name: 'name2', value: "value2", toolTipMsg: "Select an item from the list"),
DropDownValueModel(name: 'name3', value: "value3"),
DropDownValueModel(name: 'name4', value: "value4", toolTipMsg: "This is value4",
],
onChanged: (val) { controller.selectedName = val; },
);
Rückgabe der GetView.build() Methode
[Bearbeiten] Widget build(BuildContext context) {
return Scaffold(
appBar: controller.applicationData.appBarBuilder('Demo'),
drawer: controller.applicationData.drawerBuilder(context),
body: Text('Hello world!'),
}
Grundgerüst einer GUI-App
[Bearbeiten]void main() {
globalLogger = GetxLogger();
ApplicationData.createDummy();
runApp(
GetMaterialApp(
title: "MyApp",
initialRoute: AppPages.initialRoute,
getPages: AppPages.routes,
),
);
}