[flutter] 하단 바에 그라데이션 적용하기 (snake navigation bar)
여러 앱을 살펴보다가 그라데이션으로 포인트를 준 앱을 발견했다. 하단바에 그라데이션을 적용해보았다.
하단 바는 snake navigation bar 패키지를 이용해서 구현했다.
1. snake navigation bar 설치 (선택)
// pubspec.yaml
dependencies:
flutter_snake_navigationbar: ^0.6.1
2. 색상 추출하기 (선택)
아래의 tinEye 사이트에서 이미지의 색상을 추출했다.
https://labs.tineye.com/color/
TinEye Labs - Color Extraction Lab
TinEye is an image search and recognition company. We are experts in computer vision, pattern recognition, neural networks, and machine learning. Our mission is to make your images searchable. How to use TinEye
labs.tineye.com
3. 그라데이션 결과 미리보기 (선택)
아래 사이트에서 색을 조합하고 그라데이션 적용 결과를 예측해볼 수 있다. 여러 색 중에 어떤 조합이 어울릴지 미리 확인해볼 수 있다.
CSS Gradient — Generator, Maker, and Background
As a free css gradient generator tool, this website lets you create a colorful gradient background for your website, blog, or social media profile.
cssgradient.io
4. 하단바에 그라데이션 적용
하단바는 기본 흰 바탕, 선택되지 않았을 때 아이콘의 색은 회색, 선택되었을 때 아이콘의 색은 회색, 배경 색은 그라데이션 선형으로을 넣어주기 위해 다음과 같이 적용했다. (패키지를 사용하지 않을 경우에는 Container의 BoxDecoration 내의 gradient 속성을 사용하면 된다. - 아래의 참고 블로그 글)
Color 안에는 0x + FF(투명도가 0임을 뜻함) + 색상 코드에서 나오는 16진수 (# 다음의 숫자)를 넣어주면 된다.
// 하단 바 위젯
class CustomSnakeBottomBar extends StatefulWidget {
final int selectedIndex; // 현재 선택된 페이지/아이콘의 인덱스
final List<BottomNavigationBarItem> items; // 아이콘 리스트
final void Function(int) changeIndex; // 인덱스가 변경되었을 때 실행될 함수
const CustomSnakeBottomBar({
super.key,
required this.selectedIndex,
required this.items,
required this.changeIndex,
});
@override
State<CustomSnakeBottomBar> createState() => _CustomSnakeBottomBarState();
}
class _CustomSnakeBottomBarState extends State<CustomSnakeBottomBar> {
final whiteColor = Colors.white;
final greyColor = const Color(0xFF757070);
final paleRedColor = const Color(0xFFE59394);
final palePinkColor = const Color(0xFFEFB9B3);
@override
Widget build(BuildContext context) {
return SnakeNavigationBar.gradient(
elevation: 0.8,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25),
topRight: Radius.circular(25),
),
),
snakeViewGradient: LinearGradient(
colors: [paleRedColor, palePinkColor],
),
unselectedItemGradient: LinearGradient(
colors: [greyColor, greyColor],
),
selectedItemGradient: LinearGradient(
colors: [whiteColor, whiteColor],
),
currentIndex: widget.selectedIndex,
onTap: widget.changeIndex,
items: widget.items,
);
}
}
// 위젯 사용
class Main extends StatefulWidget {
const Main({super.key});
@override
State<Main> createState() => _MainState();
}
class _MainState extends State<Main> {
int selectedIndex = 1;
WidgetList nextPages = const [Settings(), MainTabBar(), CustomSearchBar()];
final List<BottomNavigationBarItem> items = [
customBottomBarIcon(label: '설정 페이지', iconData: Icons.settings),
customBottomBarIcon(label: '메인 페이지', iconData: Icons.home),
customBottomBarIcon(label: '그룹 검색 바 띄우기', iconData: Icons.search_rounded),
];
void changeIndex(int index) {
setState(() {
selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: CustomAnimatedPage(
changeIndex: changeIndex,
nextPages: nextPages,
selectedIndex: selectedIndex,
), // 페이지 변경 시 바뀌는 부분
bottomNavigationBar: CustomSnakeBottomBar(
selectedIndex: selectedIndex,
items: items,
changeIndex: changeIndex,
),
);
}
}
// custombottombar icon
BottomNavigationBarItem customBottomBarIcon({
required String label,
required IconData iconData,
}) {
return BottomNavigationBarItem(
icon: Icon(iconData),
label: label,
);
}
// custom animated page
class CustomAnimatedPage extends StatelessWidget {
final void Function(int) changeIndex;
final int initialPage, selectedIndex;
final WidgetList nextPages;
const CustomAnimatedPage({
super.key,
required this.changeIndex,
this.initialPage = 1,
required this.nextPages,
required this.selectedIndex,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
child: PageView.builder(
controller: PageController(initialPage: initialPage),
onPageChanged: (value) => changeIndex(value),
itemCount: 3,
itemBuilder: (context, index) => nextPages[selectedIndex],
),
),
);
}
}
참고
이미지 색상 추출 사이트 추천 및 이용 방법 (이미지에서 색상 코드 찾기)
오늘 포스팅에서는 이미지를 통해 색상을 추출할 수 있는 사이트 소개와 간단한 이용 방법을 정리해보려 합니다. 말씀드린 부분과 같이 이미지에서 색상 정보를 얻길 원하시거나, 색상 조합의
makene.tistory.com
https://papabee.tistory.com/83
플러터, flutter) Gradient 사용하기
그라디언트는 Contatiner 내의 데코레이션 항목에서 BoxDecoration을 쓸 때, 사용할 수 있다. 그라디언트를 속성에는 LinerGradient말고도 다양한 형태가 있다. 아무튼 colors 속성은 List를 받고, 비긴은 시작
papabee.tistory.com