ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Flutter] Custom Button 만들기
    플러터 2024. 4. 7. 17:26

    직접 버튼을 만들어야 하는 상황이 생기는데, 어떻게 만들면 좋을지 직접 만들어 봤다.

    전략

    1. 버튼 디자인 state를 만들고 state에 맞춰서 버튼 그리기
      • normal, pressed, disable
      • 버튼 사용자는 state를 몰라도 되는 정보라서 숨김.
    2. Tab이 눌렸을때 pressed, Tab이 끝났을 때 normal
    3. 아이콘 유무에 따라 이미지 넣어줌

    Custom button 코드

    import 'package:flutter/material.dart';
    
    enum MyButtonState { normal, pressed, disabled }
    
    class MyButton extends StatefulWidget {
      final String label;
      final bool disable;
      final IconData? icons;
      final GestureTapCallback? onTap;
    
      const MyButton(
          {super.key,
          required this.label,
          this.disable = false,
          this.icons,
          this.onTap});
    
      @override
      State<MyButton> createState() => _MyButtonState();
    }
    
    class _MyButtonState extends State<MyButton> {
      MyButtonState state = MyButtonState.normal; // state 선언하고 state에 따라 디자인 바꿈.
    
      @override
      void initState() {
        if (widget.disable) {
          state = MyButtonState.disabled; // disable 일 때 disabled로 state바꿈.
        }
        super.initState();
      }
    
      Color backgroundColor(MyButtonState type) {
        if (type == MyButtonState.normal) {
          return Colors.black;
        } else if (type == MyButtonState.pressed) {
          return Colors.grey;
        } else {
          return Colors.grey;
        }
      }
    
      Color labelColor(MyButtonState type) {
        if (type == MyButtonState.normal) {
          return Colors.white;
        } else if (type == MyButtonState.pressed) {
          return Colors.black;
        } else {
          return Colors.black.withOpacity(0.4);
        }
      }
    
      Widget iconWidget() {
        if (widget.icons == null) {
          return Container();
        } else {
          return Icon(
            widget.icons,
            size: 20,
            color: Colors.blue,
          );
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
            onTapDown: (details) { // 누르면 pressed로 상태 바꿈.
              if (state == MyButtonState.normal) {
                setState(() {
                  state = MyButtonState.pressed;
                });
              }
            },
            onTapCancel: () { // 탭 취소 하면 normal로 상태 바꿈.
              if (state == MyButtonState.pressed) {
                setState(() {
                  state = MyButtonState.normal;
                });
              }
            },
            onTapUp: (details) { // 터치 때면 normal로 상태 바꿈.
              if (state == MyButtonState.pressed) {
                setState(() {
                  state = MyButtonState.normal;
                });
              }
            },
            onTap: () {
              if (state == MyButtonState.disabled) {
                return;
              }
              widget.onTap?.call();
            },
            child: Container(
              decoration: BoxDecoration(
                  color: backgroundColor(state), // state에 따라서 색 바꿈.
                  borderRadius: const BorderRadius.all(Radius.circular(10))),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  iconWidget(), 
                  Text(
                    widget.label,
                    style: TextStyle(color: labelColor(state)), // state에 따라서 색 바꿈.
                  )
                ],
              ),
            ));
      }
    }

    사용 코드

    const SizedBox(
      width: 100,
      height: 50,
      child: MyButton(
        label: "Button",
        icons: Icons.add,
      )),

    결과

Designed by Tistory.