문제를 먼저 보겠다.
위의 해시태그 버튼을 만들기 위해서
아래의 GrapperHashtag라는 컴포넌트를 만들었다.
import 'package:flutter/material.dart';
import 'package:grapper/utils/grapper_color.dart';
import 'package:grapper/utils/grapper_font.dart';
class GrapperHashtag extends StatelessWidget {
const GrapperHashtag({
super.key,
required this.text,
this.isSelected = false,
});
final String text;
final bool isSelected;
@override
Widget build(BuildContext context) {
return Container(
height: 30,
alignment: Alignment.center,
padding: isSelected
? const EdgeInsets.symmetric(horizontal: 20)
: const EdgeInsets.all(0),
decoration: BoxDecoration(
color: isSelected ? GrapperColorRed.normal : Colors.black,
borderRadius: const BorderRadius.all(
Radius.circular(20),
),
),
child: GrapperText(
text: '#$text',
grapperFont: GrapperFonts.pretendard_500,
size: 17,
color: Colors.white,
),
);
}
}
그리고 main_page에 아래처럼 GrapperHashtag를 선언을 해줬다.
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
GrapperHashtag(text: '핫딜'),
GrapperHashtag(
text: '추천',
isSelected: true,
),
GrapperHashtag(text: '인디게임'),
GrapperHashtag(text: '매드무비'),
],
)
지금까지 보면 별 문제 없는 코드이다.
하지만, 저 GrapperHashTag도 어떻게 해서든 버튼처럼 눌러야한다
그리고 GrapeprHashtag라는 위젯을 4번씩이나 선언을 한다는 불편함이 있었다.
그래서 ListView를 사용해서 코드를 짜봤다.
SizedBox(
height: 30,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: hashtags.length,
itemBuilder: (context, index) => GestureDetector(
onTap: () {
setState(() {
hashtagIndex = index;
});
},
child: GrapperHashtag(
text: hashtags[index],
isSelected: hashtagIndex == index,
),
),
),
)
위 코드가 listview를 사용해서 만든 코드이다.
빌드 하는것에는 문제가 없지만, 실행된 화면을 본다면
이런식으로 각각의 컴포넌트들이 띄어져있지 않고 같이 붙어있는것을 볼 수 있다.
그럼 그냥 ListView.separated를 사용하면 되는거 아니냐? 싶을것이다.
사실 맞는 말이다.
Mediaquery 사용해서 화면 Width 구하고 Width만큼 반응형으로 컴포넌트 사이 벌리려고
그걸 또 separated에 sepatatorBuilder에 또 SizedBox(width * 0.012)....
가능은 하다.
각자 취향이 있듯이 이렇게 만드는 사람도 있을것이다.
하지만 난
Row나 Column이라는 위젯에서
mainAxisAlignment와 crossAxisAlignment에 있는
spaceBetween이라는 좋은 기술이 있는데
굳이 Mediaquery로 불안정한 값들 찾아서 sizedBox로 공백이 있는것이 나는 개인적으로 싫었다.
그래서 mainAxisAlignment를 사용하면서 코드 효율성을 높이는 방법이 무엇이 있나 찾아봤다.
그리고 찾은
List.generate
일반적인 List는
List<int> test = [0, 1, 2, 3];
이런식으로 하나씩 추가 하지만,
List.generate는
List<int> test = List.generate(3,(index)=>index);
이런식으로 주어진 길이에 따라 함수 안에 있는 것으로 새로운 리스트를 만든다.
이걸 응용하면
List<String> test1 = ['hello', 'world'];
List<Widget> test2 = List.generate(test1.length, (index)=>Text(test1[index]));
이런식으로 사용할 수 있다.
그래서 난 List.generate를 사용해서
아래코드로 spaceBetween을 사용하면서 코드 효율성을 높혔다.
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(
hashtags.length,
(index) => GestureDetector(
onTap: () {
setState(() {
hashtagIndex = index;
});
},
child: GrapperHashtag(
text: hashtags[index],
isSelected: hashtagIndex == index,
),
),
),
)
물론 어디까지나 취향이기때문에 굳이 이 방식으로 사용할 필요는 없다.
'Flutter' 카테고리의 다른 글
[Flutter] 크로스 플랫폼 (1) | 2025.04.01 |
---|---|
[Flutter] pub.dev에 나만의 package를 만들고 올리기 #2 (1) | 2025.03.24 |
[Flutter] pub.dev에 나만의 package를 만들고 올리기 #1 (0) | 2025.03.24 |
[Flutter] Flutter 프로젝트에 .env 적용하기 (0) | 2024.07.25 |
[Flutter] Github Action에서 Github Secrets로 .env파일 만들기 (0) | 2024.07.24 |