참고:
https://medium.com/flutter-community/flutter-reusable-widgets-38e270846d59
https://github.com/aanalmehta/flutter_reusable_widgets/blob/master/lib/text_form_widget.dart
우리는 위젯을 조금만 바꾸어 사용하는 일이 잦습니다. 텍스트만 바꾼 동일한 디자인의 텍스트박스, 여러 버튼 등이 그 예입니다.
단 한번만 사용할 위젯을 만드는 것이 아니라면, 재사용 가능한 위젯을 만드는 것이 훨씬 더 편리하고, 관리하기 쉽습니다.
만드는 방법은 쉬운데, 크게 2가지 방법이 있습니다.
자주 사용할 위젯의 class를 만들어주는 방법,
위젯에서 수정할 부분만 빼고 원형을 미리 만들어 놓는 방법입니다.
class TextFormFieldWidget extends StatefulWidget {
final TextInputType textInputType;
final String hintText;
final Widget prefixIcon;
final String defaultText;
final FocusNode focusNode;
final bool obscureText;
final TextEditingController controller;
final Function functionValidate;
final String parametersValidate;
final TextInputAction actionKeyboard;
final Function onSubmitField;
final Function onFieldTap;
const TextFormFieldWidget(
{ this.hintText,
this.focusNode,
this.textInputType,
this.defaultText,
this.obscureText = false,
this.controller,
this.functionValidate,
this.parametersValidate,
this.actionKeyboard = TextInputAction.next,
this.onSubmitField,
this.onFieldTap,
this.prefixIcon});
_TextFormFieldWidgetState createState() => _TextFormFieldWidgetState();
}
class _TextFormFieldWidgetState extends State<TextFormFieldWidget> {
double bottomPaddingToError = 12;
Widget build(BuildContext context) {
return Theme(
data: Theme.of(context).copyWith(
primaryColor: primaryColor,
),
child: TextFormField(
cursorColor: primaryColor,
obscureText: widget.obscureText,
keyboardType: widget.textInputType,
textInputAction: widget.actionKeyboard,
focusNode: widget.focusNode,
style: TextStyle(
color: colorBlack,
fontSize: 16.0,
fontWeight: FontWeight.w200,
fontStyle: FontStyle.normal,
letterSpacing: 1.2,
),
initialValue: widget.defaultText,
decoration: InputDecoration(
prefixIcon: widget.prefixIcon,
hintText: widget.hintText,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: primaryColor),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: primaryColor),
),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 14.0,
fontWeight: FontWeight.w300,
fontStyle: FontStyle.normal,
letterSpacing: 1.2,
),
contentPadding: EdgeInsets.only(
top: 12, bottom: bottomPaddingToError, left: 8.0, right: 8.0),
isDense: true,
errorStyle: TextStyle(
color: colorRed,
fontSize: 12.0,
fontWeight: FontWeight.w300,
fontStyle: FontStyle.normal,
letterSpacing: 1.2,
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: primaryColor),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(color: primaryColor),
),
),
controller: widget.controller,
validator: (value) {
if (widget.functionValidate != null) {
String resultValidate =
widget.functionValidate(value, widget.parametersValidate);
if (resultValidate != null) {
return resultValidate;
}
}
return null;
},
onFieldSubmitted: (value) {
if (widget.onSubmitField != null) widget.onSubmitField();
},
onTap: () {
if (widget.onFieldTap != null) widget.onFieldTap();
},
),
);
}
}
해당 class는 밑의 코드처럼 사용합니다.
Widget _buildPassword() {
return TextFormFieldWidget(
hintText: "Password",
obscureText: true,
textInputType: TextInputType.visiblePassword,
actionKeyboard: TextInputAction.done,
functionValidate: commonValidation,
controller: _passwordController,
focusNode: _passwordControllerFocus,
onSubmitField: () {},
parametersValidate: "Please enter password.",
prefixIcon: Icon(Icons.keyboard_hide),
);
}
코드가 길어 보이지만, 핵심은
조금씩 바꿀 속성들은 widget.XXXX로 실제 사용할 곳에서 지정해주고, 나머지는 다른 속성들을 미리 만들어놓습니다.
다음 방법입니다. 수정할 부분만 제거한, 함수 원형을 만들어 놓는 방법입니다.
import 'package:flutter/material.dart';
Container customToggleBtnWidget({
required List<bool> isSelected,
required Function(int) onClick,
}) {
return Container(
margin: const EdgeInsets.all(30),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: ToggleButtons(
isSelected: isSelected,
onPressed: (int index) {
return onClick(index);
},
color: Colors.grey,
disabledColor: Colors.white,
renderBorder: false,
borderWidth: 0,
borderColor: Colors.white,
selectedColor: Colors.black,
borderRadius: BorderRadius.circular(10),
fillColor: Colors.white,
selectedBorderColor: Colors.white,
children: const [
Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'기록',
style: TextStyle(
fontSize: 24,
),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'조회',
style: TextStyle(
fontSize: 24,
),
),
),
],
),
);
}
onclick 과 isSelected 를 다르게 사용할 것입니다.
class와 달라진 것은 한 가지입니다. 다르게 사용할 속성에 required를 적어놓고, 위젯을 만들 때는 required를 채워준 후 사용합니다.
Widget customToggleBtn2() {
return (customToggleBtnWidget(
onClick: (index) {
setState(() {
isSelected[index] = !isSelected[index];
});
if (isSelected[0]) {
Navigator.popAndPushNamed(context, '/');
isSelected[1] = false;
} else if (isSelected[1] && flag != 2) {
Navigator.popAndPushNamed(context, '/first');
isSelected[0] = false;
}
},
isSelected: isSelected,
));
}
이것으로 위젯을 재사용하는 방법에 대해 알아보았습니다.
모르시는 분들께 도움이 많이 되었으면 좋겠습니다.
설명 마치겠습니다. 감사합니다 : )