본문으로 바로가기

커스텀 위젯 만들기

category 📱 Mobile/📱 (old) Flutter v 1.0 2020. 5. 19. 08:36

 

다음과 같이 작성했다고 가정해보자. 한 화면에 여러 FAB가 들어가는 건 추천하지 않는 바이고 (공식 문서에 따르면 그렇다) 비슷한 위젯이 연속해서 2개 들어갔다. 

 

만약 앞으로도 비슷한 위젯을 여기저기서 써야 한다면 커스텀 위젯을 만드는 방법을 고려해보자. 

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    FloatingActionButton(
       onPressed: () {},
       child: Icon(
         Icons.add,
       ),
    ),
    SizedBox(
      width: 20,
    ),
    FloatingActionButton(
      onPressed: () {},
      child: Icon(Icons.add),
    ),
  ],
)

 

 

커스텀위젯을 만들기 위해서 우리는 가급적 RAW한, 저수준의 위젯을 골라야 한다. 버튼에 있어 낮은 수준을 제공하는 위젯은 RawMaterialButton이 있다. 문서에서도 "It's intended to be used for custom Material buttons that optionally incorporate defaults from the themes or from app-specific sources."라며 커스텀 위젯을 만드는 데 사용될 목적으로 만들어졌다고 한다.

 

FAB도 뜯어보면 이 위젯을 기반으로 만들어진 것임을 알 수 있다.

 

 

RawMaterialButton class - material library - Dart API

Creates a button based on Semantics, Material, and InkWell widgets. This class does not use the current Theme or ButtonTheme to compute default values for unspecified parameters. It's intended to be used for custom Material buttons that optionally incorpor

api.flutter.dev

 

위젯은 그냥 클래스일 뿐이므로 생성자 함수를 만들어서 child나 icon과 같이 원하는 속성을 지정하도록 넣어주고, 기존 부분을 오버라이딩하면 그게 커스텀 위젯이다.

 

class RoundIconButton extends StatelessWidget {
  final Icon icon;
  final Function onPressed;

  RoundIconButton({this.icon, @required this.onPressed});

  @override
  Widget build(BuildContext context) {
    return RawMaterialButton(
      child: this.icon,
      onPressed: this.onPressed,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
      elevation: 0.0,
      fillColor: Colors.redAccent,
      constraints: BoxConstraints.tightFor(
        width: 56.0,
        height: 56.0,
      ),
    );
  }
}

 

 

인디케이터를 직접 만들어보았다. Container 위젯을 기반으로 만들었다.

 

import 'package:com/constants/size.dart';
import 'package:flutter/material.dart';

class MyProgressIndicator extends StatelessWidget {

  final double containerSize;
  final double progressSize;

  const MyProgressIndicator({
    Key key, this.containerSize, this.progressSize = 60,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
//      width: size.width,
//      height: size.width,
      width: containerSize,
      height: containerSize,
      child: Center(
        child: SizedBox(
          width: progressSize,
          height: progressSize,
          child: Image.asset("assets/loading_img.gif"),
        ),
      ),
    );
  }
}

darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체