일단 우리는 이 어플리케이션이 한 회사에 종속된 애플리케이션이 아닌 다른 회사 또한 사용할 수 있도록 만들기로 했기때문에 회원가입 후에 제일 먼저 회사를 정하도록 유도하는게 맞다고 생각되어, 회원가입 후 아래와 같은 멀티 스텝 로직을 통해 등록하도록 유도하고자 했습니다. 

 

1. 조사 

위와 같이 검색을 하면 제일 먼저 Reference로 나오는 것들이 Stepper Widget을 이용한 예제 였습니다. 역시.. 믿고 있었다구 플러터.. 

 

2. 스테퍼 위젯이란  ? 

 

https://api.flutter.dev/flutter/material/Stepper-class.html

 

Stepper class - material library - Dart API

A material stepper widget that displays progress through a sequence of steps. Steppers are particularly useful in the case of forms where one step requires the completion of another one, or where multiple steps need to be completed in order to submit the w

api.flutter.dev

일련의 단계에 대한 진행 상황을 표시하는 스텝 위젯입니다. Stepper는 한 단계를 완료하기 위해 다른 단계를 완료해야 하거나 전체 양식을 제출하기 위해 여러 단계를 완료해야 하는 양식의 경우에 특히 유용합니다. 부모 클래스는 이 위젯이 제공하는 세 개의 콜백에 의해 트리거되는 일부 로직에 따라 currentStep을 이 위젯에 전달해야 합니다.

 

그리고 직접사용하면서 실질적으로 필요했던 프로퍼티를 한번 적어보도록 하겠습니다. 

 

type - 현재 스텝에 대한 표시를 해주는 인디케이터의 방향을 정해줍니다. 

 

controlsBuilder - 이전, 다음 단계를 컨트롤하는 네비게이션 버튼을 만들거나 커스텀 컨트롤 위젯을 구현할 수 있습니다. 

밑에를 보시면 알겠지만 버튼을 좌측이 기본 버튼이고, 오른쪽은 제가 커스텀 위젯으로 바꾼겁니다. 

 

 

currentStep - 현재 스텝 인덱스를 넣어주면 됩니다. 

onStepCancel - cancel 버튼을 탭하면 호출되는 콜백입니다.

onStepContinue - continue 버튼을 탭하면 호출되는 콜백입니다. 

 

기본 설정되어있는 버튼들에 대한 콜백함수에 대한 프로퍼티인데요.  저는 사실상 현재 스텝에 대한 인덱스를 관리하는데에만 사용하였습니다. 
 
steps - 스텝을 배열로 받는 프로퍼티입니다. 그리고 스텝은 title과 content를 반드시 넘겨줘야합니다. 그리고 content에 원하는 커스텀 위젯을 넣어주면 됩니다. 

 

3. 결과물 

 

 

4. 예제코드 

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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import 'package:flutter/material.dart';
 
class Step_Example extends StatefulWidget {
  const Step_Example({Key? key}) : super(key: key);
 
  @override
  _RegisterState createState() => _RegisterState();
}
 
class _RegisterState extends State<Step_Example> {
  int _currentStep = 0;
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        iconTheme: const IconThemeData(color: Colors.greenAccent),
        title: const Text(
          'Stepper',
          style: TextStyle(
            color: Colors.greenAccent,
          ),
        ),
      ),
      body: Theme(
        data: ThemeData(
          colorScheme: const ColorScheme.light(primary: Colors.greenAccent),
        ),
        child: Stepper(
          currentStep: _currentStep,
          onStepContinue: _onStepContinue,
          onStepCancel: _onStepCancel,
          controlsBuilder: _controlsBuilder,
          type: StepperType.horizontal,
          steps: _buildSteps(),
        ),
      ),
    );
  }
 
  @override
  void initState() {
    super.initState();
  }
 
  Step _buildStep({
    required String title,
    required Widget content,
    required bool isActive,
    required bool isEditing,
  }) {
    return Step(
      title: Text(title),
      contentcontent,
      isActive: isActive,
      state: isEditing
          ? StepState.editing
          : isActive
              ? StepState.complete
              : StepState.disabled,
    );
  }
 
  List<Step> _buildSteps() {
    return [
      _buildStep(
        title: 'Step 1',
        contentconst Text('Step 1'),
        isActive: _currentStep >= 0,
        isEditing: _currentStep == 0,
      ),
      _buildStep(
        title: 'Step 2',
        contentconst Text('Step 2'),
        isActive: _currentStep >= 1,
        isEditing: _currentStep == 1,
      ),
      _buildStep(
        title: 'Step 3',
        contentconst Text('Step 3'),
        isActive: _currentStep >= 2,
        isEditing: _currentStep == 2,
      ),
    ];
  }
 
  Widget _controlsBuilder(BuildContext context, _) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          _currentStep != 0
              ? OutlinedButton(
                  style: ButtonStyle(
                    side: MaterialStateProperty.all(
                        const BorderSide(color: Colors.greenAccent, width: 1)),
                  ),
                  onPressed: _.onStepCancel,
                  child: const Text('PREV'),
                )
              : Container(),
          _currentStep != 2
              ? ElevatedButton(
                  onPressed: _.onStepContinue,
                  child: const Text('NEXT'),
                )
              : ElevatedButton(
                  onPressed: () {
                    print('submit');
                  },
                  child: const Text('FINISH'),
                ),
        ],
      ),
    );
  }
 
  void _onStepCancel() {
    if (_currentStep <= 0return;
    setState(() {
      _currentStep -= 1;
    });
  }
 
  void _onStepContinue() {
    if (_currentStep >= 2return;
    setState(() {
      _currentStep += 1;
    });
  }
}
 
cs