-
Flutter - 인별 클론 코딩 V1.0, 프로필 화면-3개발/Flutter 2021. 10. 8. 00:16반응형
프로필 헤더 인포메이션
프로필 페이지의 프사옆은 테이블을 이용해서 만든다. Table의 children안에는 TableRow로 만든다. 그냥 Table만 쓰면 이상하게 나오는데 Expanded로 나머지 공간을 차지하게해서 적당히 쓰이게 한다.
그리고 TableRow안에 childredn: [] 안에 Text를 _getStatusValueWidget로 리팩터 메소드를 해줘서 쓴다. 아래 Posts, Followers, Following는 _getStatusLabelWidget로 만들어 준다. 그리고 textAlign은 중앙으로 정렬해준다. 그리고 숫자는 fontweight를 bold로 글자 부분은 w300으로 준다. 그런데 여기서 문제점은 화면이 작아졌을때이다. 그때 숫자나 글자가 길어져서 넘치면 잘리거나 모양이 이상해 진다. 그걸 해결 할 수 있는 방법은 FittedBox로 해주고 fit 옵션에 BoxFit.scaleDown으로 해주면 된다. Padding부분이 모양이 이상해져서 Center로 감싸주고 클래스를 Widget로 변경해주면 된다.
Row get _getProfileHeader => Row( children: [ Padding( padding: const EdgeInsets.all(common_gap), child: CircleAvatar( radius: 40, backgroundImage: NetworkImage(getProfileImgPath('username')), ), ), Expanded( child: Table( children: [ TableRow(children: [ _getStatusValueWidget('12311111141256111'), _getStatusValueWidget('123'), _getStatusValueWidget('123'), ]), TableRow(children: [ _getStatusLabelWidget('Posts'), _getStatusLabelWidget('Followers'), _getStatusLabelWidget('Following'), ]), ], ), ), ], ); Widget _getStatusValueWidget(String value) => Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: common_s_gap), child: FittedBox( fit: BoxFit.scaleDown, child: Text( value, textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.bold), ), ),), ); Widget _getStatusLabelWidget(String value) => Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: common_s_gap), child: FittedBox( fit: BoxFit.scaleDown, child: Text( value, textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.w300), ), )), );
프로필 페이지 유저네임 레이아웃
사진밑에 아이디가 들어가는 부분. _getProfileHeader 밑에 우선 확인을 위해 Text로 해준다. 그러면 패딩을 줘야 할 것 같고 글씨체가 더 두꺼워야 하는것이 보인다. style에 fontWight에 bold를 주고 Text는 Padding으로 감싸줘서 left에 common_gap만큼 주면 된다.
Padding( padding: const EdgeInsets.only(left: common_gap,), child: Text( 'User Real Name', style: TextStyle(fontWeight: FontWeight.bold), ), ),
유저네임 BIO 레이아웃
유저네임 밑에 자기소개란 부분. 유저네임과 같이 똑같이 만들어 준다. 그대신에 bold를 w400으로만 해주면 된다.
Padding( padding: const EdgeInsets.only(left: common_gap,), child: Text( 'Bio from User. So Say Something.', style: TextStyle(fontWeight: FontWeight.w400), ), ),
에디트 프로필 버튼
프로필 수정하는 버튼. 버튼으로 만들어야 할 것 같지만 일단 Text로 확인해가면서 만들면 된다. Text로 Edit Profile을 해서 만들고 style에 fontWeight로 bold를 준다. 그리고 버튼을 주기 위해 OutlineButton으로 감싸준다. flutter 2.0에서는 다른 버튼으로 변경해줘야 한다. 그리고 버튼이 너무 붙어있으므로 Padding으로 common_gap을 줘서 감싸준다. borderSide로 버튼의 아웃라인 색을 black45로 해준다. 그리고 모서리를 둥글게 하기 위해서 shape 옵션에 RoundedRectangleBorder를 주고 borderRadius 옵션에 BorderRadius.circular를 6으로 줘서 둥글게 해준다. 버튼의 높이가 다른데 꼭 높이를 비슷하게 하거나 직접 버튼 만들때 높이를 바꿔주고 싶다면 OutlineButton을 SizedBox로 감싸고 height를 24로 주면 된다.
Padding( padding: const EdgeInsets.all(common_gap), child: SizedBox( height: 24, child: OutlineButton( onPressed: () {}, borderSide: BorderSide( color: Colors.black45, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(6), ), child: Text( 'Edit Profile', style: TextStyle(fontWeight: FontWeight.bold), ), ), ), ),
디바이스 화면 크기 가져오기
프로필 페이지에서 MediaQuery.of(context).size로 사이즈를 가져왔는데 이걸 이페이지만이 아닌 글로벌로 변경하려한다. 앱이 시작할때 사이즈를 가져와서 저장하려 한다. constants에 size에 Size size;로 해준다. 그리고 main_page에서 미디어쿼리를 불러와주거나 나중에 로그인에서 해주면 된다. 그러나 main.dart에서는 하면 안된다. 왜냐하면 MaterialApp 안에 있어서 MyApp에서는 사용을 못한다. 그래서 그안인 main_page의 build 안에 if로 size가 null일때 미디어 쿼리를 불러오는걸 해준다.
if(size==null){ size = MediaQuery.of(context).size; }
커스텀 탭 만들기
자기가 올린 이미지와 내가 태깅된 이미지를 왔다갔다 하는 탭 만들기. Row로 만든다. 두개의 Expanded로 만들어 준다. 버튼처럼 눌러서 기능을 해야 하므로 IconButton으로 만들어주고 미리 받은 이미지를 쓰기위해 ImageIcon안에 AssetImage로 gred.png와 saved.png 이미지를 해주고 리팩터 메소드로 Widget get _getTabIconButtons 로 만들어 주면 된다.
Widget get _getTabIconButtons => Row( children: [ Expanded( child: IconButton( icon: ImageIcon(AssetImage("assets/grid.png")), onPressed: () {}, ), ), Expanded( child: IconButton( icon: ImageIcon(AssetImage("assets/saved.png")), onPressed: () {}, ), ), ], );
그리고 위 탭이 눌렸을때 하단에 줄이 생기는 부분도 만들어 준다.
Widget get을 만들어 주고 _getAnimatedSelectedBar로 AnimatedContainer을 만들어 준다. duration은 200 밀리세컨드로 해주고 alignment는 왼쪽으로 줄건데 페이지 상단에 AlignmentGeometry로 만들어 준다. Alignmnet.centerleft로 왼쪽부터 시작하게 한다. 그리고 탭이 눌릴때 이값을 centerright와 centerleft와 서로 눌린곳으로 바꿔준다. curve는 easeInOut을 주고 color은 transparent를 준다. 그리고 높이는 1을 주고 넓이는 size.width만큼 준다. 이게 바가 왔다갔다하는 영역이고 child에 그 선을 표시하면 된다. Container로 높이 1, width는 size.width/2로 해주고 color은 black87정도로 해주면 된다. 그리고 이게 왔다갔다 해주는 부분은 버튼에서 해주면 된다. onPressed안에 _setTab(true or false) 가 오게 해준다. _setTab는 하단에 bool을 받고 그 안에 setState로 if문에 값에 따라 this.tabAlign = Alignment.centerLeft; 또는 this.tabAlign = Alignment.centerRight; 를 주면 된다. 정상 작동 되는것을 알 수 있다.
Widget get _getTabIconButtons => Row( children: [ Expanded( child: IconButton( icon: ImageIcon(AssetImage("assets/grid.png")), onPressed: () { _setTab(true); }, ), ), Expanded( child: IconButton( icon: ImageIcon(AssetImage("assets/saved.png")), onPressed: () { _setTab(false); }, ), ), ], ); Widget get _getAnimatedSelectedBar => AnimatedContainer( alignment: tabAlign, // 탭 하단줄 왼쪽으로 시작 duration: Duration(milliseconds: 200), //그냥 다른값을 안집어 넣거 duration만 집어넣어도 알아서 애니메이션을 잘 해줌 curve: Curves.easeInOut, color: Colors.transparent, height: 1, width: size.width, child: Container( height: 1, width: size.width/2, color: Colors.black87, ), ); _setTab(bool tabLeft){ setState(() { if(tabLeft){ this.tabAlign = Alignment.centerLeft; }else{ this.tabAlign = Alignment.centerRight; } }); }
그리고 탭 버튼이 눌렸을때 눌리지 않은 곳은 회색으로 변경해줘야 한다. 상단에 _tabIconGridSelected를 bool로 주고 기본을 true로 준다. 우선 기본이 왼쪽 탭이기 때문이다. 그리고 _setTab에서 if문에 추가로 넣어서 true와 false를 넣어주면 된다. 그리고 ImageIcon에 color을 _tabIconGridSelected?Colors.black:Colorsblack26으로 해주면 된다. 다른 버튼은 반대로 넣어주면 된다. 이때 ImageIcon에 넣어줘야 한다. IconButton에 넣으면 색이 안변한다. 왜냐하면 이미지를 가져와서 했기때문에 버튼이 아니라 이미지 아이콘에 색을 정해줘야 하기 때문이다.
상단에 bool _tabIconGridSelected = true; _setTab(bool tabLeft){ setState(() { this._tabIconGridSelected = tabLeft;// tabLeft와 같기때문에 이런식으로 하는것도 됨. 코드간결화하고 좋음 그러나 밑으로 하면 더 직관적. if(tabLeft){ this.tabAlign = Alignment.centerLeft; //this._tabIconGridSelected = true; }else{ this.tabAlign = Alignment.centerRight; //this._tabIconGridSelected = false; } }); }
다음시간은 커스텀 탭 애니메이션이다.
반응형'개발 > Flutter' 카테고리의 다른 글
Flutter - 인별 클론 코딩 V1.0, 팔로우/언팔로우목록, 로그인페이지 (0) 2021.10.12 Flutter - 인별 클론 코딩 V1.0, 프로필 화면-4 (0) 2021.10.08 Flutter - 인별 클론 코딩 V1.0, 프로필 화면-2 (0) 2021.10.06 Flutter - 인별 클론 코딩 V1.0, 프로필 화면-1 (0) 2021.10.05 Flutter - 인별 클론 코딩 V1.0, 피드화면 (0) 2021.10.01 댓글