Flutter

[Flutter] 박스 디자인 및 레이아웃 구성

hminor 2023. 7. 28. 21:13

Flutter에서 박스디자인하는 법(Margin, Padding, 정렬)

  • 지난 시간 강사님의 작성 코드는 아래와 같다.
    • Container 또는 SizedBox를 사용해서 높이를 지정하는 방식을 사용
import 'package:flutter/material.dart';

void main() {
  //runApp 안에 있는 MyApp을 실행해달라는 코드
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('앱임'),
        ),
        body: Container(
          child: Text('안녕'),
        ),
        bottomNavigationBar: BottomAppBar(
          // Container를 사용할 수 있지만 박스를 만드는데
          // 높이, 너비, 자식 요소만 사용한다면 SizedBox를 사용하면 좋다
          child: SizedBox(
            height: 60,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Icon(Icons.phone, size: 30),
                Icon(Icons.message, size: 30),
                Icon(Icons.contact_page, size: 30),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
  • 박스 디자인하는 법
    • 기존에 작성한 것과 같이 Container로 감싼 뒤 작성해주면 되는데 margin과 padding은 EdgeInsets 속성을 사용해 작성해줄 수 있으며, 해당 박스를 꾸미는 요소를 작성하려고 한다면 decoration 속성에 BoxDecoration을 작성 후 다양한 속성을 추가하며 꾸밀 수 있다.
    import 'package:flutter/material.dart';
    
    void main() {
      //runApp 안에 있는 MyApp을 실행해달라는 코드
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
    
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('앱임'),
            ),
            body: Center(
              child: Container(
                width: 100, height: 80,
                margin: EdgeInsets.all(20),
                padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
                decoration: BoxDecoration(
                    color: Colors.blue,
                    border: Border.all(color: Colors.black),
                    borderRadius: BorderRadius.all(Radius.circular(20))
                ),
                child: Text('하이염'),
              ),
            ),
          ),
        );
      }
    }
    
  • 만약 박스를 Center가 아닌 다른 곳으로 배치 하고자 한다면
    • Center() 대신에 Align() 으로 변경 후
      • alignment 속성을 추가하면 다양한 곳으로 배치를 할 수 있다.
      import 'package:flutter/material.dart';
      
      void main() {
        //runApp 안에 있는 MyApp을 실행해달라는 코드
        runApp(const MyApp());
      }
      
      class MyApp extends StatelessWidget {
        const MyApp({super.key});
      
        @override
        Widget build(BuildContext context) {
      
          return MaterialApp(
            home: Scaffold(
              appBar: AppBar(
                title: Text('앱임'),
              ),
              body: Align(
                alignment: Alignment.bottomCenter,
                child: Container(
                  width: 100, height: 80,
                  margin: EdgeInsets.all(20),
                  padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
                  decoration: BoxDecoration(
                      color: Colors.blue,
                      border: Border.all(color: Colors.black),
                      borderRadius: BorderRadius.all(Radius.circular(20))
                  ),
                  child: Text('하이염'),
                ),
              ),
            ),
          );
        }
      }
      
  • 그리고 해당 박스의 크기를 꽉 채우고 싶다면 원하는 속성에서 double.infinity 를 작성하면 된다.
    • 아래 코드에선 margin 속성이 있기에 좌우 20씩 떨어져있는걸 확인할 수 있다.
    • 또한 상위 요소 내에서 속성이 적용된다는 것도 잊지 않기!
    import 'package:flutter/material.dart';
    
    void main() {
      //runApp 안에 있는 MyApp을 실행해달라는 코드
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
    
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('앱임'),
            ),
            body: Align(
              alignment: Alignment.bottomCenter,
              child: Container(
                width: double.infinity, height: 80,
                margin: EdgeInsets.all(20),
                padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
                decoration: BoxDecoration(
                    color: Colors.blue,
                    border: Border.all(color: Colors.black),
                    borderRadius: BorderRadius.all(Radius.circular(20))
                ),
                child: Text('하이염'),
              ),
            ),
          ),
        );
      }
    }
    

Flutter Typography와 Layout 만드는 법

  • Typography
    • 글자 디자인 하기
    • Text에 스타일을 주고 싶을 경우
      • Text( “텍스트 문구”, style: TextStyle() ) 로 작성하면 된다.
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('앱임'),
        ),
        body: SizedBox(
          child: Text(
            '안녕하세용 :)',
            style: TextStyle( fontWeight: FontWeight.w900),
          ),
        ),
      ),
    );
  }
}

아이콘에 스타일을 주고 싶을 땐 간단하게 아래와 같이 그냥 적용하면 된다.

import 'package:flutter/material.dart';

void main() {
  //runApp 안에 있는 MyApp을 실행해달라는 코드
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('앱임'),
        ),
        body: SizedBox(
          child: Icon(Icons.star, color: Colors.amber),
        ),
      ),
    );
  }
}
  • 이제 버튼을 추가하고 싶다면 총 3가지의 방법이 있다.
    1. TextButton(): 일반 텍스트만 있는 버튼
    2. IconButton(): 아이콘으로 생긴 버튼
    3. ElevatedButton(): 색상이 채워진 버튼
    • 여기서 중요한 것으로 버튼에는 꼭 child와 onPressed 속성을 넣어야 한다.
import 'package:flutter/material.dart';

void main() {
  //runApp 안에 있는 MyApp을 실행해달라는 코드
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('앱임'),
        ),
        body: SizedBox(
            child: TextButton( child: Text('버튼'), onPressed: (){},)
            // child: ElevatedButton( child: Text('버튼'), onPressed: (){},)
            // child: IconButton( icon: Icon(Icons.star), onPressed: (){},
        ),
      ),
    );
  }
}
  • 숙제
    • 당근 마켓의 물품 리스트를 그대로 작성해보기!
    • 뭔가 완벽하지는 않지만 유사하게 해봤음
    • 이미지의 경우엔 기존에 추가한 짱구 이미지로 대체했음
import 'package:flutter/material.dart';

void main() {
  //runApp 안에 있는 MyApp을 실행해달라는 코드
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.white,
          title: Text('금호동3가', style: TextStyle(color: Colors.black, fontWeight: FontWeight.w900)),
          actions: [
            Row(
              children: [Icon(Icons.search), SizedBox(width: 20), Icon(Icons.menu), SizedBox(width: 20), Icon(Icons.notifications_none_sharp)],
            )
          ],
          actionsIconTheme: IconThemeData(color: Colors.black, size: 40),
          leading: Icon(Icons.access_time),
        ),
        body: Container(
          child: Row(
            children: [
              Expanded(
                flex: 3,
                child: Container(
                  height: 300,
                  alignment: Alignment.topCenter,
                  child: Image.asset('JJangu.jpg'),
                  margin: EdgeInsets.fromLTRB(15, 30, 15, 0),
                ),
              ),
              Expanded(
                flex: 7,
                child: Container(
                  height: 300,
                  margin: EdgeInsets.fromLTRB(15, 30, 15, 0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text('캐논 DSLR 100D (단렌즈, 충전기 16기가SD 포함)', style: TextStyle(fontSize: 30, fontWeight: FontWeight.w700)),
                      Text('성동구 행당동 끌올 10분 전', style: TextStyle(fontSize: 12, color: Colors.grey, fontWeight: FontWeight.w700)),
                      Text('210.000원', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700)),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: [
                          Icon(Icons.favorite_border, color: Colors.grey),
                          Text('4', style: TextStyle(fontSize: 20, color: Colors.grey, fontWeight: FontWeight.w300),)
                        ],
                      )
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

안드로이드 스튜디오 데모 화면