플러터에서 버튼의 종류는 TextButton, ElevatedButton, OutlinedButton이 세가지이다.
위 세가지 버튼에도 클릭시 기본 효과가 존재하지만, 내가 원하는 느낌은 눌려서 작아지는 느낌이었다. 그래서 두고두고 쓰고자 작성함.
아래 위젯은 Flutter Hooks를 사용하여 작성됨.
flutter_hook가 싫다면 걍 useState부분을 setState로 대체해서 사용하면 될듯함.
먼저 flutter_hooks를 프로젝트에 추가
flutter pub add flutter_hooks
아래의 위젯에 사용되는 flutter_hooks의 함수는 useState()이다. 이를 사용하면 statefulWidget을 사용한 코드보다 훨씬 길이가 단축된다.
var data = useState(*)에서 *자리에 initialData을 입력. 입력시 data의 자료형은 ValueNotifier<*의 자료형>이 된다.
data.value로 값을 사용하면 됨.
위젯을 만들건데, AnimatedContainer와 AnimatedDefaultTextStyle를 사용하고, 이들을 GestureDetector로 wrap하여 onTapUp과 onTapDown으로 버튼 효과주기.
탭업 할때 isClicked를 false로 변경 + 함수 실행. 탭다운시 isClicked를 true로 변경.
Widget의 속성들을 optional parameter로 입력받도록 작성할 것임.
어떤 값들을 입력받을지 구상한다.
- text: 버튼에 표시될 텍스트. (String)
- defaultSize: 클릭 전 기본 크기, Offset의 dx는 width이고 dy는 height. (Offset)
- clickedSize: 클릭시 줄어든 크기, Offset의 dx는 width이고 dy는 height. (Offset)
- defaultFontSize: 클릭 전 기본 폰트 크기. (double)
- clickedFontSize: 클릭시 줄어든 폰트 크기. (double)
- defaultColor: 클릭 전 기본 컨테이너 색상. (Color)
- clickedFontSize: 클릭시 컨테이너 색상. (Color)
- circularRadius: Container의 BorderRadius.circular의 값 (double)
- buttonDuration: Container의 Animation의 시간길이(밀리초). (int)
- textDuration: Container안의 Text의 Animation의 시간길이(밀리초). (int)
- textColor: 버튼에 표시될 텍스트의 색상. (Color)
- onTap_: 버튼 클릭시 발생할 이벤트를 입력받음. (Function())
코드:
Widget animationButton({
required String text,
Offset defaultSize = const Offset(100, 105), //(width,height)
Offset clickedSize = const Offset(100, 105), //(width,height)
double defaultFontSize = 15,
double clickedFontSize = 14,
required Color defaultButtonColor,
required Color clickedButtonColor,
double circularRadius = 10,
int buttonDuration = 300,
int textDuration = 300,
required Color defaultTextColor,
required Color clickedTextColor,
required void Function() onTap_,
}) {
var isClicked = useState(false);
return GestureDetector(
onTapDown: (_) => isClicked.value = true,
onTapUp: (_) {
isClicked.value = false;
onTap_();
},
child: AnimatedContainer(
duration: Duration(milliseconds: buttonDuration),
width: isClicked.value ? clickedSize.dx : defaultSize.dx,
height: isClicked.value ? clickedSize.dy : defaultSize.dy,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(circularRadius),
color: isClicked.value ? clickedButtonColor : defaultButtonColor,
),
child: Center(
child: AnimatedDefaultTextStyle(
duration: Duration(milliseconds: textDuration),
style: TextStyle(
color: isClicked.value ? clickedTextColor : defaultTextColor,
fontSize: isClicked.value ? clickedFontSize : defaultFontSize,
),
child: Text(text),
),
),
),
);
}
적용:
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
class CustomButton extends HookWidget {
const CustomButton({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: animationButton(
text: 'Button',
defaultSize: const Offset(110, 50),
clickedSize: const Offset(108, 48),
defaultFontSize: 14,
clickedFontSize: 13,
defaultButtonColor: const Color(0xFF2D2D36),
clickedButtonColor: const Color(0xFF282830),
defaultTextColor: Colors.white,
clickedTextColor: Colors.white70,
onTap_: () {
print('ClickEvent');
},
),
);
}
}
참고:
'Flutter' 카테고리의 다른 글
Flutter; GestureDetector의 onTapUp 오류(onTapDown 유지되는 오류) 해결방법 (0) | 2024.03.31 |
---|---|
Flutter; ElevatedButton으로 클릭 효과 구현 (MaterialStateProperty) (0) | 2024.03.29 |
댓글