코드를 보다 더 간결하게 만들고 코드의 재사용성을 증대시키는 방법.
이 한페이지에 고작 버튼 3개 들어있는데 코드가 이~~렇게 길다 🤨🤨
import 'package:flutter/material.dart';
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
@override
State<Login> createState() => _Login();
}
class _Login extends State<Login> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Sign in',style: TextStyle(color: Colors.white)),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ButtonTheme(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.white,
),
onPressed: () {},
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
children: [
Image.asset('assets/images/google.png', width: 30),
SizedBox(width: 40),
Text('Login with Google'),
],
),
))),
SizedBox(height: 3),
ButtonTheme(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.white,
),
onPressed: () {},
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
children: [
Image.asset('assets/images/facebook.png',
width: 30),
SizedBox(width: 40),
Text('Login with Facebook',
style: TextStyle(color: Color(0xffb3A589E))),
],
),
))),
SizedBox(height: 3),
ButtonTheme(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Color(0xffb499959),
),
onPressed: () {},
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
children: [
Image.asset('assets/images/mail.png', width: 30),
SizedBox(width: 40),
Text('Login with Email',
style: TextStyle(color: Colors.white)),
],
),
)))
],
),
));
}
}
코드 리팩토링을 통해 정리해보자
lib폴더안에 따로 빼둔 버튼을 모아둘 폴더를 만들고 그 안에 my_login_button.dart파일을 만들었다.
만든 파일에 따로 빼두고 싶은 버튼을 그대로 복사해서 붙여넣기 한다
싹 긁어서
Container()위치에 붙여넣기~!(이때 리턴 마지막의 세미콜론이 빠지지않게 주의)
이렇게 만들어 준다.
이제 이걸 활용해서 재사용이 가능한 코드를 만들어보자~!
바뀌는요소: 1. 로고이미지, 2.텍스트, 3.버튼색상, 4.클릭이벤트
지난번 build메서드내에서 리빌드 될수 있는건 final변수였다.
속성들을 위한 저 변수 모두 final로 지정을 하고 속성을 필요로 하는 곳에 변수의 타입을 지정해주면된다.
class 왜 자꾸 밑줄로 경고뜨나했더니 카멜케이스 안썼다고 뜨는거였다 ,,기억하자 클래스는 첫글자대문자..카멜케이스..
많은 코드를 함수로 한번에 묶는방법
body뒤의 코드들을 한번에 묶고 싶다~!
그러면 body:~부터 닫는곳까지 드래그 하고 우클릭후 Refactor-Extract Method를 눌러주면
짜잔~ 이런식으로 함수명이 생기고(설정할수있다) 아래에 따로 코드가 분리 된걸 볼수 있다.
_ 함수명에 언더스코어를 붙여서 접근불가능한 프라이빗한요소로 만들자(접근제어자)
같은파일내에서만 접근 가능하다(외부에서 불필요한 접근을 못하게 해서 함부로 데이터가 변경되는걸 막음)
이제 만들어둔 MyLoginButton클래스를 이용해서 버튼하나를 더 추가해보자
결과
다른 버튼들도 MyLoginButton으로 바꾸자~!
속이다 후련하네~~~!
vue로 컴포넌트 짤때 느낌이 나는데 prop emit에 비해 더 간편하고 직관적인거 같다!😍
그리고 따로 my_login_button.dart를 어딘가에 전역적으로 선포하지 않더라도 편하게 가져다 쓸수있는점이 굉장히 맘에든다(vue는 만들고 index.js에서 export하고..main.js에서 import하고..폴더위치 바뀌면 index.js가서 또 수정해주고......파일명 다르면 에러뜨고...)
➕ 추가
보다보니 저 코드도 불-편 해졌다
변수는 다 빼놓고 공통된요소하나로 반복해서 보여줄수 없을까 생각하다가 ListView가 생각났다
MyLoginButton()의 위젯에서 변수도 조금더 쏙쏙 들어갈수있게 변수 자리에 넣어줬다(기존 Widget타입에서 String으로 바꿈)
버튼이 생성되는페이지(login.dart)에서 변수요소들을 배열로 따로 다 빼주었다.
그리고 기존 MyLoginButton이 있던곳에 ListView.builder로 리스트 형식으로 만들어 줬다.
itemCount는 ButtonList갯수만큼,itemBuilders는 만들어둔 MyLoginButton을 리턴하게 하고 인자로 ButtonList[index]의 변수를 넣어주었다.
shrinkWrap:true를 안넣으면 상위 Column의 MainAxisAlignment.center가 적용되질 않아서 세로축중앙 정렬이 되지않는다.
shrinkWrap가 어떤속성일까 하고 찾아보니 스크롤보기 범위가 보고있는 내용에 따라 결정되어야 하는지 여부라고 한다 😦
(일반적으로 ListView뿐만 아니라 GridView, PageView 및 CustomScrollView 는 목록 항목에 필요한 공간이 더 적은 경우에도 상위 요소에서 제공하는 모든 사용가능한 공간을 채우려고 한다고 한다)
기본값은 false이고
ShrinkWrap 속성 을 설정하지 않으면 ListView 가 부모만큼 커진다. true로 설정하면 목록이 콘텐츠를 래핑하고 자식이 허용하는 만큼 커진다.
결과
코드
<script>
import 'package:flutter/material.dart';
import 'package:newflutter/my_button/my_login_button.dart';
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
@override
State<Login> createState() => _Login();
}
class _Login extends State<Login> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Sign in', style: TextStyle(color: Colors.white)),
centerTitle: true,
),
body: _buildPadding());
}
Widget _buildPadding() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ListView.builder(
padding: const EdgeInsets.all(10.0),
itemCount:ButtonList.length ,
shrinkWrap: true,
itemBuilder:(BuildContext context, int index){
return MyLoginButton(
image:'${ButtonList[index]['image']}',
text:'${ButtonList[index]['text']}',
btnColor:'${ButtonList[index]['btnColor']}',
onPressed: () {},
textColor: '${ButtonList[index]['textColor']}',
);
} ,
),
],
);
}
}
const ButtonList = [
{
"image":"facebook.png",
"text":"Login with Facebook",
"textColor":"b3A589E",
"btnColor":"ffffff",
},
{
"image":"dog.jpg",
"text":"Login with Dog",
"textColor":"AF496F",
"btnColor":"ffffff",
},
{
"image":"google.png",
"text":"Login with Google",
"textColor":"000000",
"btnColor":"ffffff",
},
{
"image":"mail.png",
"text":"Login with Mail",
"textColor":"ffffff",
"btnColor":"489959",
},
];
</script>
조금...맘이 편해진거 같다 🥰🥰
더 간결한 방법이 있으면 또 바꿔야지