Forms 2: Sliders and Buttons

강아지의 능력을 평가 할 수 있는 매우 중요한 기능을 추가할때가 됐다.

1. Add the Form

dog_detail_page.dart에 폼 UI를 추가하는것부터 시작하자.

아래 그림은 페이지가 어떻게 보여줄지를 보여준다:
sliders

인터페이스는 두개의 중요 위젯으로 이루어 진다.

  1. 점수를 변경하는 Slider.
  2. slider의 값을 제출하는 RaisedButton.

_DogDetailPageState에 둘다 추가하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// dog_detail_page.dart

class _DogDetailPageState extends State<DogDetailPage> {
final double dogAvatarSize = 150.0;
// slider의 초기값
double _sliderValue = 10.0;

// ...

Widget get addYourRating {
return Column(
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(
vertical: 16.0,
horizontal: 16.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
// row, column, listvie, 기타 등에서 Flexbile(유연한) 위젯은
// CSS의 flex-grow속성과 매우 유사하게 작동하는 래퍼(wrapper)다.
Flexible(
flex: 1,
// 많은 폼 요소와 마찬가지로 slider는 자체 값을 알고 그 값을 업데이트하는 방법을 알야야함.
//
// slider는 값이 변경될때 onChanged가 호출 되지만,
// 오직 setState를 사용하여 state의 value속성이 변경될때만 다시 그린다.
//
// The workflow is:
// 작동흐름은
// 1. 사용자가 slider를 드래그(drag)한다.
// 2. onChanged가 호출된다.
// 3. onChanged의 콜백이 sliderValue state를 설정한다.
// 4. 플러터는 SliderValue에 의존하는 모든것을 다시 그린다.
// 이 경우에는 slidera만 새로운 값으로 변경한다.
child: Slider(
activeColor: Colors.indigoAccent,
min: 0.0,
max: 15.0,
onChanged: (newRating) {
setState(() => _sliderValue = newRating);
},
value: _sliderValue,
),
),

// slider의 값을 표시하는 부분.
Container(
width: 50.0,
alignment: Alignment.center,
child: Text('${_sliderValue.toInt()}',
style: Theme.of(context).textTheme.display1),
),
],
),
),
submitRatingButton,
],
);
}

// 현재로선 아무것도 하는게 없는 간단한 Raised 버튼.
Widget get submitRatingButton {
return RaisedButton(
onPressed: () => print('pressed!'),
child: Text('Submit'),
color: Colors.indigoAccent,
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black87,
appBar: AppBar(
backgroundColor: Colors.black87,
title: Text('Meet ${widget.dog.name}'),
),
// Make the body a ListView that displays
// both the profile and the rating form.
// body를 프로필(profile)과 평가 폼 두개를 모두 표시하는 ListView로 만든다.
body: ListView(
children: <Widget>[dogProfile, addYourRating],
),
);
}
}

앱을 hot reload 했다면 작동되는 slider가 있을것이다.

2. Wire up the Submit button (submit버튼 연결)

submitRatingButtonSlider onChanged 콜백에서 기술적으로 처리 할 수 있는 일을 한다.

Dog클래스 자체 평가(rating)를 업데이트한다. 그렇게 되면 플러터는 Dog평가가 포하는 모든것을 다시 작성하기 때문에 앱 전체에 걸쳐 새로운 평가가 보여진다.

_DogDetailPageState 클래스에 이 함수를 추가하고 submitButton이 눌려졌을때 이를 호출 하도록 추가하자.

1
2
3
4
5
6
7
// dog_detail_page.dart

// 다음 섹션에서 여러분은 error 처리를 추가할 것이지만,
// 지금은 이것이 전부 이다.
void updateRating() {
setState(() => widget.dog.rating = _sliderValue.toInt());
}

그리고 submitRatingButton 위젯을 다음과 같이 변경하자.

1
2
3
4
5
6
7
8
9
// dog_detail_page.dart

Widget get submitRatingButton {
return RaisedButton(
onPressed: updateRating,
child: Text('Submit'),
color: Colors.indigoAccent,
);
}

추가 후에 slider를 이동하고 submit을 누르면 메인 페이지로 돌아 가서 변경된 강아지 평가를 볼 수 있다.

Comment and share

크리에이티브 커먼즈 라이선스
이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-변경금지 2.0 대한민국 라이선스에 따라 이용할 수 있습니다.

Forms 1: User Input

AddDogForm에 기능을 추가하는것은 쉬운 일이다.
기본적으로 폼 입력을 추적하고 라우터를 통해 메인 페이지로 데이터를 반환하는 함수를 플러터 클래스에 추가하면 된다.

1. TextEditingController class

입력 폼 요소를 추적하려면 Form위젯을 추가하거나, 텍스트 입력을 별도로 추적 하면 된다.

이 예제에선 후자(텍스트 입력을 별도로 추적)를 통해서 처리 하는 방법을 보여줄 것이다. TextEditingController 는 플러터에서 중요하고 기본적인 것이다.

TextEditingController는 기본적으로 할당된 TextField를 청취(listens)하는 클래스이고 TextField의 텍스트가 변경 될때마다 내부 상태를 업데이트 한다.

여러분의 _AddDogFormPageState 클래스에서 각 TextFieldcontrolleronChanged속성을 추가하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// new_dog_form.dart

class _AddDogFormPageState extends State<AddDogFormPage> {
// One TextEditingController for each form input:
TextEditingController nameController = TextEditingController();
TextEditingController locationController = TextEditingController();
TextEditingController descriptionController = TextEditingController();

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add a new Dog'),
backgroundColor: Colors.black87,
),
body: Container(
color: Colors.black54,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 32.0,
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: TextField(
// TextField에 controller를 지정.
controller: nameController,
// TextField의 텍스트가 변경될때마다 onChanged 콜백 함수가 호출되고 값이 전달된다.
//
// controller의 텍스트를 다음 value로 설정.
onChanged: (v) => nameController.text = v,
decoration: InputDecoration(
labelText: 'Name the Pup',
)),
),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: TextField(
controller: locationController,
onChanged: (v) => locationController.text = v,
decoration: InputDecoration(
labelText: "Pups location",
)),
),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: TextField(
controller: descriptionController,
onChanged: (v) => descriptionController.text = v,
decoration: InputDecoration(
labelText: 'All about the pup',
)),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Builder(
builder: (context) {
return RaisedButton(
onPressed: () => print('PRESSED'),
color: Colors.indigoAccent,
child: Text('Submit Pup'),
);
},
),
),
],
),
),
),
);
}
}

새로운 일이 일어나고 있는 것처럼 보이지는 않지만, TextEditingControllers는 여러분의 폼(form)을 추적하고 있다.

2. Submit The Form

new_dog_form.dart 파일에 dog_model.dart import처리.

1
2
3
4
5
// new_dog_form.dart

import 'package:flutter/material.dart';

import 'dog_model.dart';

동일한 _AddDogFormPageState 클래스에 Navigator를 통해 폼 정보를 다시 전달하는 submitPup함수를 추가한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// new_dog_form.dart

// Navigator가 작동하려면 context가 필요하다.
void submitPup(BuildContext context) {
// 먼저 몇몇 폼 정보가 있는지 확인한다.
// 강아지는 name을 필요로 하지만 location은 불필요할 수도 있으므로, name이 없으면 저장을 포기해야 한다.
if (nameController.text.isEmpty) {
print('Dogs need names!');
} else {
// 폼 정보로 새로운 강아지를 생성한다.
var newDog = Dog(nameController.text, locationController.text,
descriptionController.text);
// route stack에서 page를 pop하고 페이지가 만들어진곳으로 새로운 강아지를 다시 전달한다.
Navigator.of(context).pop(newDog);
}
}

마지막으로, 'RaisedButton’의 onPressed 콜백에 submitPop을 추가한다.

1
2
3
4
5
6
7
8
9
// new_dog_form.dart

builder: (BuildContext context) {
return RaisedButton(
onPressed: () => submitPup(context),
color: Colors.indigoAccent,
child: Text('Submit Pup'),
);
},

그게 다다.(이게 끝이다) 이제 새로운 강아지를 제출해서 main페이지에서 확인해 보자.

Comment and share

크리에이티브 커먼즈 라이선스
이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-변경금지 2.0 대한민국 라이선스에 따라 이용할 수 있습니다.
  • page 1 of 1
Author's picture

Jace Shim


Seoul, Korea