반응형

저번 포스팅에서는 프로젝트 세팅을 했는데 일단 거지같은 모양새다.

 

밑에 푸터도 주고 위에 헤더도 설정해보자

 

1. layout 나누기

header / body / footer 영역을 나눠보자.

우선 home : Scaffold 설정을 하고 appBar / body / bottomNavigationBar 로 나누면 된다

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {

    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
              backgroundColor: Colors.white,
              title: SizedBox(
                height: 40,
                child: TextField(
                  decoration: InputDecoration(
                      hintText: '검색어를 입력하세요', //힌트 텍스트
                      filled: false, //배경색 활성화
                      fillColor: Colors.white,
                      suffixIcon: const Icon(Icons.search, color: Colors.grey),
                      enabledBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(20),
                          borderSide: const BorderSide(color: Colors.grey, width: 1)
                      ),
                      focusedBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(20),
                          borderSide: const BorderSide(color: Colors.grey, width: 1)
                      ),
                      contentPadding: const EdgeInsets.only(left: 15, right: 10)
                  ),
                ),
              ),
            ),
            body: Container(
              width: 150, height: 50, color: Colors.black,
              margin: const EdgeInsets.fromLTRB(10, 10, 10, 10),
            ),
            bottomNavigationBar: const BottomAppBar(
                child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      Icon(Icons.star),
                      Icon(Icons.confirmation_num_sharp),
                      Icon(Icons.co2_outlined)]
                )
            )
        )
    );

  }
}

 

 

대충이렇게하면 뭔가 많이본 모양이 나오긴 한다

input 필드를 생성하고 그 안에 hint 와 suffix icon 돋보기 이미지를 설정하였다

 

하지만 상단의 시간쪽이랑 로고도 넣으면 좋을것같다.

 

2. Header 꾸미기

appBar 에 leading 속성을 추가해서 로고 이미지를 넣어보자.

 

이미지를 넣으려면 pubspec.yaml 에 이미지 root 설정을 해야한다.

assets 설정을 추가하자

...

flutter:
  assets:       # <- 여기 추가
    - assets/    # <- 여기 추가
  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true
  ....

 

그리고 인텔리제이기준 우측상단에 pub get, pub upgrade를 한번씩 눌러주자

 

그리고 재실행해주면 이제뭔가 앱같긴 하다.

 

상단에 회색영역도 지워보자

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  // 상태 바 배경 색상 변경 (흰색으로 설정)
  SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
    statusBarColor: Colors.white, // 상태 바 색상을 흰색으로 설정
    statusBarIconBrightness: Brightness.dark, // 상태 바 아이콘을 어두운 색으로 설정 (흰색 배경에 어울리도록)
  ));

  runApp(const MyApp());
}

 

이렇게까지하면 헤더는 정리된 느낌 근데 폰트가 맘에안든다.

 

국룰폰트 Noto Sans Kr 을 넣어보자

 

3. 폰트 추가

https://fonts.google.com/noto/specimen/Noto+Sans+KR

 

Noto Sans Korean - Google Fonts

Noto is a global font collection for writing in all modern and ancient languages. Noto Sans KR is an unmodulated (“sans serif”) design for the Korean language u

fonts.google.com

 

여기서 get Font -> Download All

해서 모든 ttf 파일을 다운로드하고 프로젝트의 root 경로에 fonts 폴더생성 후 모두 집어넣는다

 

이걸이제 어케쓰냐면, pubspec 에 선언하고 사용하면 된다

pubspec 하단에 example이 나와있긴한데, 만드려면 복잡시러우니까 그냥 밑에 복사해서 쓰자

 

헷깔릴까봐 flutter 부터 복사해봄

flutter:
  assets:
    - assets/

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  fonts:
    - family: NotoSansKR
      fonts:
        - asset: fonts/NotoSansKR-Thin.ttf
          weight: 100
        - asset: fonts/NotoSansKR-ExtraLight.ttf
          weight: 200
        - asset: fonts/NotoSansKR-Light.ttf
          weight: 300
        - asset: fonts/NotoSansKR-Regular.ttf
          weight: 400
        - asset: fonts/NotoSansKR-Medium.ttf
          weight: 500
        - asset: fonts/NotoSansKR-SemiBold.ttf
          weight: 600
        - asset: fonts/NotoSansKR-Bold.ttf
          weight: 700
        - asset: fonts/NotoSansKR-ExtraBold.ttf
          weight: 800
        - asset: fonts/NotoSansKR-Black.ttf
          weight: 900

 

그리고 main.dart 에서 hoem 상단에 theme 을 추가하자

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {

    return MaterialApp(
        theme: ThemeData( //추가
            fontFamily: 'NotoSansKR'
        ),
        home: Scaffold(
        ...생략

 

 

4. Footer 추가

푸터를 추가한다는것은 클릭할때마다 페이지가 바뀌면 좋겠기 때문이다.

flutter 페이지 이동방식에는 두가지가 있다.

 

header, footer 를 유지하지않고 전체페이지가 바뀌는방식과 header,footer를 고정시키고 body 만 바뀌는 방식이 있는데, 이번엔 body 만 바꿔보겠다.

 

푸터에 탭을 3개둔다고 가정하고 이동할 페이지를 3개 더 생성해보자

 

main.dart는 페이지변경을 관장하는곳으로 인식하고 나머지페이지는 이동할 대상이다.

나는 달력을 넣을것이기때문에 home, calendar, mypage 이렇게 3개로 만들어봤다.

 

home.dart

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('홈 화면'),
      ),
    );
  }
}

 

calendar.dart

import 'package:flutter/cupertino.dart';

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

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text('달력 화면'),
    );
  }
}

 

mypage.dart

import 'package:flutter/material.dart';

class MyPageScreen extends StatelessWidget {
  const MyPageScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('여기는 마이페이지 화면입니다!'),
      ),
    );
  }
}

 

이렇게 3개를 만들었으면 이제 main.dart에 이어보자

 

MyApp build 부분을 이렇게 간단하게 바꿔놓는다

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(fontFamily: 'NotoSansKR'),
      home: MainScreen(), // MainScreen이 앱의 첫 화면이 됨
    );
  }
}

 

그리고 MainScreen 을 정의해준다.

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(fontFamily: 'NotoSansKR'),
      home: MainScreen(), // MainScreen이 앱의 첫 화면이 됨
    );
  }
}

class MainScreen extends StatefulWidget {
  const MainScreen({super.key});

  @override
  _MainScreenState createState() => _MainScreenState();
}

 

이제 MainScreen State 에 들어갈 요소들을 넣어주자

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(fontFamily: 'NotoSansKR'),
      home: MainScreen(), // MainScreen이 앱의 첫 화면이 됨
    );
  }
}

class MainScreen extends StatefulWidget {
  const MainScreen({super.key});

  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  int _selectedIndex = 0;

  static final List<Widget> _widgetOptions = <Widget>[
    HomeScreen(), //import 필요 
    CalendarScreen(),  //import 필요
    MyPageScreen(),  //import 필요
  ];

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: Header(),
      body: _widgetOptions.elementAt(_selectedIndex),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: '홈',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.calendar_today),
            label: '달력',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: '마이페이지',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.blue,
        onTap: _onItemTapped,
      ),
    );
  }
}

 

요로코롬하면 탭 클릭 시 페이지 변경 완료

728x90

'Mobile > Hybrid' 카테고리의 다른 글

Flutter 프로젝트 시작하기 (intelliJ)  (1) 2025.03.25
Cordova (코르도바) 시작하기  (1) 2024.09.06

+ Recent posts