'Flutter 앱/Layout'에 해당되는 글 11건

Flutter Stack

Flutter 앱/Layout 2023. 12. 27. 15:04
728x90

이미지 위에 또다른 이미지를 겹쳐서 보이도록 하고 싶을 때는 Stack 위젯을 사용한다.

 

child: Stack(
  children: [
    // 사진
    Positioned.fill(
      child: Image.network(
        catImage,
        fit: BoxFit.cover,
      ),
    ),
    // 좋아요
    Positioned(
      bottom: 8,
      right: 8,
      child: Icon(
        Icons.favorite,
        color: catService.favoriteImages.contains(catImage)
            ? Colors.amber
            : Colors.transparent,
      ),
    ),
  ],
),
 

 

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter Custom Button  (0) 2022.07.25
Flutter Row 위젯  (0) 2022.06.24
Flutter Column 위젯  (0) 2022.06.24
Flutter Container 위젯  (0) 2022.06.24
Flutter CustomScrollView  (0) 2022.06.21
블로그 이미지

Link2Me

,
728x90

플러터에서 제공하는 버튼이 몇개 있다.

기존 버튼들인 FlatButton, OutlineButton, RaisedButton  -> TextButton, OutlinedButton, ElevatedButton 으로 변경 되었다.

이런 버튼에 개발자가 맞춤형 버튼을 별도로 구현할 수 있다.

아래 예제 이외에도 몇 개 더 있지만 이 버튼이 사용법에 좋은 예시인거 같아서 이걸 적어둔다.

import 'package:flutter/material.dart';
 
class CustomGradientButton extends StatelessWidget {  
  final Function()? onTap;
  final String? btnText;
  final Color? firstColor;
  final Color? secondColor;
 
  const CustomGradientButton({
    Key? key,
    required this.onTap,
    this.btnText = 'Gradient Button',
    this.firstColor = Colors.green,
    this.secondColor = Colors.greenAccent,
  }) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    double width = MediaQuery.of(context).size.width;
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 24.0),
      child: InkWell(
        onTap: onTap,
        borderRadius: BorderRadius.circular(10.0),
        splashColor: Colors.blue.withOpacity(0.4),
        child: Ink(
          height: 50.0,
          width: width,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10.0),
            gradient: LinearGradient(
              colors: [
                firstColor!,
                secondColor!,
              ],
              begin: Alignment.topRight,
              end: Alignment.bottomLeft,
            ),
          ),
          child: Center(
            child: Text(
              btnText!,
              style: const TextStyle(
                fontSize: 24.0,
                color: Colors.white,
              ),
            ),
          ),
        ),
      ),
    );
  }
}
 

 

출처 : https://skillypro.com/how-to-make-a-custom-gradient-button-in-flutter/

 

 

import 'package:flutter/material.dart';
 
class RoundedButton extends StatelessWidget {
  const RoundedButton({
    Key? key,
    required this.colour,
    required this.title,
    required this.onPressed,
  }) : super(key: key);
 
  final Color colour;
  final String title;
  final VoidCallback onPressed;
 
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 16.0),
      child: Material(
        elevation: 5.0,
        color: colour,
        borderRadius: BorderRadius.circular(30.0),
        child: MaterialButton(
          onPressed: onPressed,
          minWidth: 200.0,
          height: 42.0,
          child: Text(
            title,
            style: const TextStyle(
              color: Colors.white,
              fontSize: 30.0,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }
}

 

 

참고하면 좋은 자료

https://nilenpatelinc.com/post/flutter-ui-3-fun-with-buttons-in-flutter/

 

Flutter UI #3: Fun with Buttons in Flutter - Nilen Patel Inc.

Tutorial and code of Buttons in Flutter. Copy and paste the below code as per your requirements. import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key key}) : super(key: key); @

nilenpatelinc.com

 

 

 

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter Stack  (0) 2023.12.27
Flutter Row 위젯  (0) 2022.06.24
Flutter Column 위젯  (0) 2022.06.24
Flutter Container 위젯  (0) 2022.06.24
Flutter CustomScrollView  (0) 2022.06.21
블로그 이미지

Link2Me

,
728x90

수평방향으로 위젯들을 나란히 배치하는 위젯이다.

children 프로퍼티에 여러 위젯들을 나열한다.

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Row(
        mainAxisAlignment: MainAxisAlignment.start, // 가로 방향 왼쪽 정렬
        children: [
          Container(
            color: Colors.red,
            width: 100,
            height: 100,
            padding: const EdgeInsets.all(8.0),
            margin: const EdgeInsets.all(8.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Container',
                ),
              ],
            ),
          ),
          Container(
            color: Colors.green,
            width: 100,
            height: 100,
            padding: const EdgeInsets.all(8.0),
            margin: const EdgeInsets.all(8.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Container',
                ),
              ],
            ),
          ),
          Container(
            color: Colors.blue,
            width: 100,
            height: 100,
            padding: const EdgeInsets.all(8.0),
            margin: const EdgeInsets.all(8.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Container',
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
 

 

FloatingActionButton 에 Row 위젯을 적용한 예제

floatingActionButton: Row(
  mainAxisAlignment: MainAxisAlignment.end,
  children: [
    FloatingActionButton(
        onPressed: () {},
        backgroundColor: Colors.green,
        child: const Icon(Icons.add)),
    SizedBox(width: 10, height: 10,), // 여백을 만들기 위해서 넣음.
    FloatingActionButton(
        onPressed: () {},
        backgroundColor: Colors.blue,
        child: const Text('5')),
    SizedBox(width: 10, height: 10,), // 여백을 만들기 위해서 넣음.
    FloatingActionButton(
        onPressed: () {},
        backgroundColor: Colors.pink,
        child: const Icon(Icons.remove)),
  ],
),

 

FloatingActionButton 크기 조절 예제

floatingActionButton: Row(
  mainAxisAlignment: MainAxisAlignment.end,
  children: [
    SizedBox(
      width: 30.0,
      height: 30.0,
      child: FittedBox(
        child: FloatingActionButton(
            onPressed: () {},
            backgroundColor: Colors.green,
            child: const Icon(Icons.add)),
      ),
    ),
    SizedBox(width: 10, height: 10,), // 여백을 만들기 위해서 넣음.
    SizedBox(
      width: 60.0,
      height: 60.0,
      child: FittedBox(
        child: FloatingActionButton(
            onPressed: () {},
            backgroundColor: Colors.blue,
            child: const Text('5')),
      ),
    ),
    SizedBox(width: 10, height: 10,), // 여백을 만들기 위해서 넣음.
    SizedBox(
      width: 80.0,
      height: 80.0,
      child: FittedBox(
        child: FloatingActionButton(
            onPressed: () {},
            backgroundColor: Colors.pink,
            child: const Icon(Icons.remove)),
      ),
    ),
  ],
),

 

floatingActionButton IconButton 적용 예제

floatingActionButton: Row(
  mainAxisAlignment: MainAxisAlignment.end,
  children: [
    SizedBox(
      width: 30.0,
      height: 30.0,
      child: FittedBox(
        child: IconButton(onPressed: () {}, icon: const Icon(Icons.add)),
      ),
    ),
    SizedBox(
      width: 10,
      height: 10,
    ), // 여백을 만들기 위해서 넣음.
    Text(
      '5',
      style: TextStyle(
        fontSize: 18,
        fontWeight: FontWeight.w500,
        fontStyle: FontStyle.italic,
        color: Colors.black,
      ),
    ),
    SizedBox(
      width: 10,
      height: 10,
    ), // 여백을 만들기 위해서 넣음.
    SizedBox(
      width: 60.0,
      height: 60.0,
      child: FittedBox(
        child: IconButton(
            onPressed: () {},
            color: Colors.red,
            icon: const Icon(Icons.remove)),
      ),
    ),
  ],
),
 

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter Stack  (0) 2023.12.27
Flutter Custom Button  (0) 2022.07.25
Flutter Column 위젯  (0) 2022.06.24
Flutter Container 위젯  (0) 2022.06.24
Flutter CustomScrollView  (0) 2022.06.21
블로그 이미지

Link2Me

,
728x90

수직방향으로 위젯들을 나란히 배치하는 위젯이다.

Layout은 대부분 Column 과 Row를 조합하여 만들기 때문에 매우 자주 사용된다.

children 프로퍼티에는 여러 위젯의 리스트를 지정할 수 있다.

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: [
          Container(
            color: Colors.red,
            width: 100,
            height: 100,
            padding: const EdgeInsets.all(8.0),
            margin: const EdgeInsets.all(8.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Container',
                ),
              ],
            ),
          ),
          Container(
            color: Colors.green,
            width: 100,
            height: 100,
            padding: const EdgeInsets.all(8.0),
            margin: const EdgeInsets.all(8.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Container',
                ),
              ],
            ),
          ),
          Container(
            color: Colors.blue,
            width: 100,
            height: 100,
            padding: const EdgeInsets.all(8.0),
            margin: const EdgeInsets.all(8.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Container',
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

 

 

 

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter Custom Button  (0) 2022.07.25
Flutter Row 위젯  (0) 2022.06.24
Flutter Container 위젯  (0) 2022.06.24
Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
블로그 이미지

Link2Me

,
728x90

아무것도 없는 위젯이다. 다양한 프로퍼티를 가지고 있기 때문에 사용하기에 따라서 다양한 응용이 가능하다.

색, 가로와 세로 길이, padding, margin 등의 설정이 가능하고 child 프로퍼티로 또다른 위젯을 자식으로 가질 수 있다.

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(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Container Widget'),
    );
  }
}
 
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
 
  final String title;
 
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
 
class _MyHomePageState extends State<MyHomePage> {
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        color: Colors.red,
        width: 100,
        height: 100,
        padding: const EdgeInsets.all(8.0),
        margin: const EdgeInsets.all(8.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              'Container',
            ),
          ],
        ),
      ),
    );
  }
}

 

Container 위젯 부분만 발췌한 코드이다.

Container(
  color: Colors.red,
  width: 100,
  height: 100,
  padding: const EdgeInsets.all(8.0),
  margin: const EdgeInsets.all(8.0),
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      const Text(
        'Container',
      ),
    ],
  ),
),

 

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter Row 위젯  (0) 2022.06.24
Flutter Column 위젯  (0) 2022.06.24
Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
Flutter Layout  (0) 2021.12.26
블로그 이미지

Link2Me

,
728x90

SliverAppBar를 사용하면 스크롤 시 앱바의 크기가 줄어들거나 색이 변하는 등의 효과를 넣을 수 있다.

 

Scaffold의 AppBar를 지정하지 않고 body 에 CustomScrollView의 인스턴스를 저장했다.

SliverFillRemaining 위젯은 하나의 정적인 화면을 구성할 때 사용한다.

import 'package:flutter/material.dart';
 
class SliverPage extends StatelessWidget {
  const SliverPage({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        SliverAppBar(
          pinned: true// 축소될 때 AppBar가 고정될지 사라질지 설정
          expandedHeight: 180.0// 확대될 때의 최대 높이
          flexibleSpace: FlexibleSpaceBar(  // 확대/축소되는 영역의 UI 
            title: Text('Sliver'),
            background: Image.asset(
              'assets/images/header-01.png',
              fit: BoxFit.cover,
            ),
          ),
        ),
        SliverFillRemaining( // 내용 영역
          child: Center(
            child: Image.asset('assets/images/nature-01.png'),
          ),
        ),
      ],
    );
  }
}

 

SliverGrid 예제

이미지를 추가하는 과정에서 여백이 생겨 보기가 좋지 않았다.

이미지를 대략 일정한 높이와 너비로 미리 맞춰 준비하는 것이 필요했다.

그리고 옵션을 주지 않으면 정사각형 이미지를 추가하므로

childAspectRatio: (1.26 / 1), // (itemWidth / itemHeight) 높이와 너비에 대한 비율로 계산하여 표기하는 것이 중요하다.

import 'package:flutter/material.dart';
 
class SliverPage extends StatelessWidget {
  const SliverPage({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        SliverAppBar(
          pinned: true// 축소될 때 AppBar가 고정될지 사라질지 설정
          expandedHeight: 180.0// 확대될 때의 최대 높이
          flexibleSpace: FlexibleSpaceBar(
            // 확대/축소되는 영역의 UI
            title: Text('Sliver'),
            background: Image.asset(
              'assets/images/header-01.png',
              fit: BoxFit.cover,
            ),
          ),
        ),
        SliverGrid(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
            childAspectRatio: (1.26 / 1), // (itemWidth / itemHeight)
          ),
          delegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) {
              return Container(
                alignment: Alignment.center,
                child: Image.asset('assets/images/nature-0${index}.png'),
              );
            },
            childCount: 6,
          ),
        ),
        //Sliver 2
        SliverGrid(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 3,
            ),
            delegate: SliverChildListDelegate(
              [
                Container(color: Colors.red, height: 150.0),
                Container(color: Colors.purple, height: 150.0),
                Container(color: Colors.green, height: 150.0),
                Container(color: Colors.cyan, height: 150.0),
                Container(color: Colors.indigo, height: 150.0),
                Container(color: Colors.black, height: 150.0),
              ],
            )),
      ],
    );
  }
}

 

이미지 가져오는 과정

assets 폴더와 서브 폴더로 images 를 추가하고 이곳에 이미지를 추가했다.

 

pubspec.yaml 파일 내에 아래와 같이 이미지를 등록해줘야 한다.

 

 

SliverToBoxAdapter(
  child: Container(
    height: 100.0,
    child: ListView.builder(
        scrollDirection: Axis.horizontal,
        itemCount: 10,
        itemBuilder: (context, index) {
          return Container(
            width: 100.0,
            child: Card(
              child: Text('data-${index + 1}'),
            ),
          );
        }),
  ),
),
SliverPadding(
  padding: EdgeInsets.all(2.0),
  sliver: SliverList(
    delegate: SliverChildListDelegate(
      [
        Card(
          child: Text('data'),
        ),
        Card(
          child: Text('data'),
        ),
        Card(
          child: Text('data'),
        ),
        Card(
          child: Text('data'),
        ),
      ],
    ),
  ),
),

 

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter Column 위젯  (0) 2022.06.24
Flutter Container 위젯  (0) 2022.06.24
Flutter Drawer Widget  (0) 2022.06.16
Flutter Layout  (0) 2021.12.26
Flutter Theme(테마) 변경  (0) 2021.12.24
블로그 이미지

Link2Me

,
728x90

android DrawerLayout 을 구글 검색하면 어떤 사항인지 정보가 나온다.

 

https://api.flutter.dev/flutter/material/Drawer-class.html 를 검색하면 매뉴얼로 제공되는 정보를 알 수 있다.

Drawer Navigation 메뉴는 앱의 Main UI 로 구현하는 경우가 많다.

 

StatefulWidget 으로 전환하는 것도 쉽게 가능하다. StatelessWidget 에 마우스를 놓고 변경하면 된다.

사용자 반응 앱을 만들려면 StatefulWidget 으로 구성한다.

// lib 폴더에서 dartfile을 선택하고 drawer 입력하면 drawer.dart 파일이 생성된다.
import 'package:flutter/material.dart';
 
// stless 입력하고 TAB키를 누르면 자동완성 Class 가 생성된다.
class Drawer extends StatelessWidget {
  const Drawer({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

 

main.dart 파일에서 Class 분리하여 별도 파일 생성하여 처리한다.

import 'package:codingapple/drawer.dart';
import 'package:flutter/material.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);
 
  @override
  State<MyApp> createState() => _MyAppState();
}
 
class _MyAppState extends State<MyApp> {
 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const DrawerMenu(title: 'Drawer Demo'),
    );
  }
}

 

drawer.dart

// lib 폴더에서 dartfile을 선택하고 drawer 입력하면 drawer.dart 파일이 생성된다.
import 'package:flutter/material.dart';
 
import 'dialog.dart';
 
// stful 입력하고 TAB키를 누르면 자동완성 Class 가 생성된다.
// 예약어에 해당하는 클래스명은 피한다.
class DrawerMenu extends StatefulWidget {
  const DrawerMenu({Key? key, required this.title}) : super(key: key);
 
  final String title; // 부모 위젯으로부터 전달받은 변수
 
  @override
  State<DrawerMenu> createState() => _DrawerMenuState();
}
 
class _DrawerMenuState extends State<DrawerMenu> {
  @override
  Widget build(BuildContext context) {
    // https://api.flutter.dev/flutter/material/Drawer-class.html 에서
    // 복사하여 Container를 덮어쓰기 한다.
    // 아래 코드와 비교하면 약간 수정된 사항이 있으니 참고하시라.
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: <Widget>// const <Widget> 에서 const 를 삭제한다.
            DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
              child: Text(
                'Drawer Header',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 24,
                ),
              ),
            ),
            ListTile(
              leading: Icon(Icons.message),
              title: Text('Messages'),
              tileColor: Colors.red,
              trailing: Icon(Icons.more_vert),
            ),
            ListTile(
              leading: Icon(Icons.account_circle),
              title: Text(
                'Profile',
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w700,
                  color: Colors.blue,
                ),
              ),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => LView(title: '연락처 앱'),
                  ),
                );
              },
            ),
            ListTile(
              leading: Icon(Icons.settings),
              title: Text('Settings'),
            ),
            ListTile(
              leading: Icon(Icons.account_circle),
              title: Text('Two-line ListTile'),
              subtitle: Text('Here is a second line'),
              trailing: Icon(Icons.more_vert),
              isThreeLine: true,
            ),
          ],
        ),
      ),
    );
  }
}

 

Android 앱 개발시 사용하는 에뮬레이터를 공용으로 사용할 수 있으며, 위 코드의 결과 UI 이다.

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter Container 위젯  (0) 2022.06.24
Flutter CustomScrollView  (0) 2022.06.21
Flutter Layout  (0) 2021.12.26
Flutter Theme(테마) 변경  (0) 2021.12.24
Flutter BottomNavigationBar 예제  (0) 2021.12.22
블로그 이미지

Link2Me

,

Flutter Layout

Flutter 앱/Layout 2021. 12. 26. 20:02
728x90

일반적으로 플러터의 레이아웃은 그리드 구조로 이뤄지고, 이는 행과 열을 의미한다.

따라서 행 위젯과 열 위젯이 있다. 각 항목에는 하나 이상의 자식이 있을 수 있고, 행 위젯의 경우 가로로 배치하고, 열 위젯은 세로로 배치한다.

 

플러터 Layout 구성에 필요한 위젯은 https://docs.flutter.dev/development/ui/layout 에 잘 설명되어 있다.

한글 설명 일부는 https://flutter-ko.dev/docs/development/ui/layout/tutorial 를 참조한다.

 

 

 

Container 위젯 : 기본적으로 최대한의 공간을 차지하여 표시된다.

Padding 위젯 : 자식 위젯 주위에 padding을 표시

Center 위젯 : 자식 위젯을 중앙에 표시

Column 위젯 : 자식 위젯들을 세로로 정렬하여 표시

Row 위젯 : 자식 위젯들을 가로로 정렬하여 표시

 

예제 소스코드

import 'package:flutter/material.dart';
 
import 'bottom_navi_bar.dart';
import 'myapp_demo.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  // 화면 표시에 대한 역할은 Scaffold 위젯이 담당한다.
  // MaterialApp 위젯은 화면 이동과 테마 지정이 주요 역할이다.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          brightness: Brightness.light,
          appBarTheme: AppBarTheme(
            color: Color.fromARGB(13152215229),
          ),
          primaryColor: Colors.lightBlue,
          accentColor: Colors.greenAccent,
          fontFamily: 'Raleway'),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
      ),
      //home: const BottomNaviBar(title: '플러터 데모 Main'),
      home: MyAppDemo(),
    );
  }
}
 
 

 

import 'package:flutter/material.dart';
 
// Android Studio 에서 stless 탭키(또는 엔터키)를 누르면 자동으로 만들어진다.
// 여기에서 클래스 이름만 지정하면 된다.
class MyAppDemo extends StatelessWidget {
  //const MyAppDemo({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: Column(
        children: <Widget>[titleSelection],
      ),
    );
  }
 
  // 컨테이너 위젯 구현
  Widget titleSelection = Container(
    // 컨테이너 내부 상하좌우에 32픽셀만큼의 패딩 삽입
    padding: const EdgeInsets.all(32),
    // 자식으로 row를 추가
    child: Row(
      // 위젯들(Expanded, Icon, Text)을 자식들로 추가
      children: <Widget>[
        // 1 : Expanded widget안에 Column을 넣으면 row의 남은 공간을 모두 채우게 된다.
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start, // 자식들을 왼쪽정렬로 배치함
            // 컬럼의 자식들로 컨테이너와 텍스트를 추가
            children: <Widget>[
              Container(
                padding: const EdgeInsets.only(bottom: 8),
                // 컨테이너 내부 하단에 8픽셀만큼 패딩 삽입
                child: Text(
                  "서울시 종로구",
                  style: TextStyle(fontWeight: FontWeight.bold // 텍스트 강조 설정
                      ),
                ),
              ),
              Text(
                '세종로 100번지',
                style: TextStyle(color: Colors.grey[600// 텍스트의 색상을 설정
                    ),
              )
            ],
          ),
        ),
 
        Icon(
          Icons.star, // 별모양 아이콘 삽입
          color: Colors.red[500], // 빨간색으로 설정
        ),
        Padding(padding: EdgeInsets.all(4)),
        Text(
          '43',
          style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
        ), // 텍스트 표시
      ],
    ),
  );
}
 

 

Expanded 위젯

 

Expanded 위젯은 Column 위젯, Row 위젯과 함께 사용하여 웹 개발에서 사용되는 flex와 같은 기능을 구현할 수 있다.

 

 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: Row(
        children: <Widget>[
          Expanded(
            child: Container(
              color: Colors.blue[200],
            ),
            flex: 3,
          ),
          Expanded(
            child: Container(
              color: Colors.grey[100],
            ),
            flex: 7,
          ),
        ],
      ),
    );
  }

 

Stack 위젯

 

Stack 위젯을 사용하면, 위젯 위에 위젯을 표시할 수 있다.

 

 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: Container(
        padding: const EdgeInsets.all(10),
        child: Stack(
          children: [
            Container(
              width: 400,
              height: 200,
              color: Colors.green,
            ),
            Container(
              width: 100,
              height: 100,
              color: Colors.deepOrange,
            ),
            Container(
              width: 50,
              height: 50,
              color: Colors.blue,
            ),
          ],
        ),
      ),
    );
  }
 
 

 

SizedBox 위젯

Container 위젯과 SizedBox 위젯은 둘 다 width와 height를 가진다.

Container 위젯은 width와 height를 넣지 않으면, 최대 크기로 확장해준다.

SizedBox 위젯의 height나 width의 default 값은 double.infinity 이다.
그리고, color 속성이 없어서 색상을 지정할 수 없다.

간단하게 height, width 만 설정하는 것이면 SizedBox 위젯을 사용하는 것이 가볍다.

 

SizedBox는 크게 2가지의 용도가 있다.

1) Container, button과 같은 다른 위젯을 child로 두면서 높이와 너비를 고정시키고 싶을때 사용함.

2) Row나 Column과 같은 위젯의 children들 사이에 간격을 두고 싶을때 공백을 두기 위해서 사용함.

 

 

 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: SafeArea(
        child: SizedBox(
          width: 200.0,
          height: 150.0,
          child: Card(
            child: Center(child: Text('Hello World!')),
            color: Color.fromRGBO(11518419019),
          ),
        ),
      ),
    );
  }
 

 

 

SizedBox 위젯의 height와 width 값만큼 위젯 사이의 공간을 만들기 위해 사용하는 경우

Sizedbox가 편리한 이유는, column에서 쓸경우 width가, Row에서 쓸경우 height가 고정되므로 나머지 하나만 지정해 두면 된다는 점과, 복잡한 각 children 내부의 padding대신 다른 children으로 두기만 하면 되서 디버깅이 쉽다.

 

 

 

 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: SafeArea(
        child: Container(
          padding: EdgeInsets.all(10),
          child: Column(
            children: [
              Container(
                width: 100,
                height: 100,
                color: Colors.redAccent,
              ),
              SizedBox(height: 10),
              Container(
                width: 100,
                height: 100,
                color: Colors.greenAccent,
              )
            ],
          ),
        ),
      ),
    );
  }
 

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
Flutter Theme(테마) 변경  (0) 2021.12.24
Flutter BottomNavigationBar 예제  (0) 2021.12.22
Flutter TabBar  (0) 2021.12.22
블로그 이미지

Link2Me

,
728x90

플러터에서는 테마 지정이 엄청 쉽다.

Light 테마와 Dark 테마 지정이 코드 몇줄로 쉽게 해결된다.

테마 지정 안된 코드

import 'package:flutter/material.dart';
 
import 'bottom_navi_bar.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
      ),
      home: const BottomNaviBar(title: '플러터 데모 Main'),
    );
  }
}

 

테마 지정한 코드

import 'package:flutter/material.dart';
 
import 'bottom_navi_bar.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  // 화면 표시에 대한 역할은 Scaffold 위젯이 담당한다.
  // MaterialApp 위젯은 화면 이동과 테마 지정이 주요 역할이다.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          brightness: Brightness.light,
          primaryColor: Colors.lightBlue,
          accentColor: Colors.cyan[600],
          fontFamily: 'Raleway'),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
      ),
      home: const BottomNaviBar(title: '플러터 데모 Main'),
    );
  }
}
 
 

 

Custom Color 를 지정하고 싶은 경우에는

https://flutter-color-picker.herokuapp.com/ 에서 색상을 임의로 선택한 다음에 코드를 아래와 같이 변경하면 된다.

primaryColor 의 색에 적용했더니 에러 발생해서, appBarTheme 에 색상 적용 테스트했다.

// 화면 표시에 대한 역할은 Scaffold 위젯이 담당한다.  
// MaterialApp 위젯은 화면 이동과 테마 지정이 주요 역할이다.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          brightness: Brightness.light,
          appBarTheme: AppBarTheme(
            color: Color.fromARGB(13152215229),
          ),
          //primaryColor: Colors.lightBlue,
          fontFamily: 'Raleway'),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
      ),
      home: const BottomNaviBar(title: '플러터 데모 Main'),
    );
  }
 

 

이전 게시글의 ListView_Demo 클래스에도 테마를 적용했다.

 
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
 
// Android Studio 에서 stless 를 입력후 엔터키를 치면
// 자동완성 코드가 작성되고 클래스명을 지정하면 된다.
class ListView_Demo1 extends StatelessWidget {
  const ListView_Demo1({Key? key}) : super(key: key);
 
  // ListView 위젯 정적 데모
  static const List<String> _data = [
    'Mercury(수성)',
    'Venus(금성)',
    'Earth(지구)',
    'Mars(화성)',
    'Jupiter(목성)',
    'Saturn(토성)',
    'Uranus(천왕성)',
    'Neptune(해왕성)',
    'Pluto(명왕성)',
  ];
 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
          brightness: Brightness.light,
          primaryColor: Colors.lightBlue,
          accentColor: Colors.cyan[600],
          fontFamily: 'Raleway'),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
      ),
      home: Scaffold(
        appBar: CupertinoNavigationBar(
          leading: CupertinoNavigationBarBackButton(
            onPressed: () => Navigator.of(context).pop(),
          ),
          middle: Text('쿠퍼티노 UI'),
          trailing: GestureDetector(
            child: Icon(CupertinoIcons.search),
            onTap: (){},
          ),
          backgroundColor: CupertinoColors.activeGreen,
          border: Border(
              bottom:BorderSide(
                  width: 1,
                  color: CupertinoColors.activeGreen,
                  style: BorderStyle.solid
              )
          ),
        ),
        //body: _buildStaticListView(),
        body: _buildStaticListViewSeperated(),
      ),
    );
  }
 
  Widget _buildStaticListView() {
    return ListView.builder(
      itemCount: _data.length,
      itemBuilder: (BuildContext _context, int i) {
        return ListTile(
          title: Text(_data[i],
              style: TextStyle(
                fontSize: 23,
              )),
          trailing: Icon(
            Icons.favorite_border,
          ),
        );
      },
    );
  }
 
  Widget _buildStaticListViewSeperated() {
    return ListView.separated(
      itemCount: _data.length,
      itemBuilder: (BuildContext _context, int i) {
        return ListTile(
          title: Text(_data[i],
              style: TextStyle(
                fontSize: 23,
              )),
          trailing: Icon(
            Icons.favorite_border,
          ),
        );
      },
      separatorBuilder: (BuildContext _context, int i) {
        return const Divider();
      },
    );
  }
}
 

 

UI 에 대한 사항을 좀더 알아보고 싶다면....

https://github.com/lohanidamodar/flutter_ui_challenges 에 있는 자료를 활용한다.

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
Flutter Layout  (0) 2021.12.26
Flutter BottomNavigationBar 예제  (0) 2021.12.22
Flutter TabBar  (0) 2021.12.22
블로그 이미지

Link2Me

,
728x90

플러터 BottomNavigationBar 예제를 나중에 활용하는데 도움될 수 있게 작성해본 예제다.

BottomNavigationBar 검색하면 단순한 것이 대부분이라 향후 기능 구현시 활용 목적으로 약간 더 추가했다.

 

import 'package:flutter/material.dart';
 
void main() {
  runApp(MyApp());
}
 
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
 
class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
        brightness: Brightness.light,
      ),
      debugShowCheckedModeBanner: false,
      home: const MyHomePage(title: '플러터 데모 Main'),    );
  }
}
 
// Android Studio 에서 stful 엔터를 치면 자동으로 만들어진다.
// 여기에서 클래스 이름만 지정하면 자동으로 만들어진다.
class MyHomePage extends StatefulWidget {
  final String title; // 선언한 변수는 final을 붙여야 한다.
  const MyHomePage({Key? key, required this.title}) : super(key: key);
 
  @override
  _MyHomePageState createState() => _MyHomePageState();
  // Stateless 위젯과 다른 점은 createState() 메소드를 통해
  // 상태를 담당하는 클래스를 지정할 수 있다.
}
 
// 클래스 이름 앞에 _가 붙어 있으면 private 클래스로 본다.
// 다트에서는 Java와 같이 public, protected, private 같은 접근 제어자 키워드 없음
class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0// _를 붙이면 private
  static const TextStyle optionStyle =
  TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
 
  static const List<Widget> _widgetOptions = <Widget>[
    Text(
      'Index 0: Home',
      style: optionStyle,
    ),
    CallsfloatBtn(), // class 호출
    Text(
      'Index 2: School',
      style: optionStyle,
    ),
  ];
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BottomNavigationBar Sample'),
      ),
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex, // 선택된 Index
        backgroundColor: Colors.grey[200], //Bar의 배경색
        selectedItemColor: Colors.amber[800],
        selectedFontSize: 15//선택된 아이템의 폰트사이즈
        unselectedFontSize: 12//선택 안된 아이템의 폰트사이즈
        onTap: _onItemTapped,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business),
            label: 'Business',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.school),
            label: 'School',
          ),
        ],
      ),
    );
  }
 
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }
}
 
class CallsfloatBtn extends StatefulWidget {
  const CallsfloatBtn({Key? key}) : super(key: key);
 
  @override
  _CallsfloatBtnState createState() => _CallsfloatBtnState();
}
 
class _CallsfloatBtnState extends State<CallsfloatBtn> {
  int _counter = 0;
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center, // 중앙정렬
          children: <Widget>[
            Text(
              '당신은 버튼을 눌렀어요 :',
              softWrap: false// 텍스트가 영역을 넘어갈 경우 줄바꿈 여부
              style: Theme.of(context).textTheme.headline5,
            ),
            Text(
              '$_counter 번',
              style: TextStyle(fontSize: 25),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
 
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
}
 

 

참고자료

https://blog.logrocket.com/how-to-build-a-bottom-navigation-bar-in-flutter/

 

How to build a bottom navigation bar in Flutter - LogRocket Blog

This tutorial demonstrates how to build, integrate, and customize a bottom navigation bar in a Flutter app.

blog.logrocket.com

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
Flutter Layout  (0) 2021.12.26
Flutter Theme(테마) 변경  (0) 2021.12.24
Flutter TabBar  (0) 2021.12.22
블로그 이미지

Link2Me

,

Flutter TabBar

Flutter 앱/Layout 2021. 12. 22. 11:04
728x90

Flutter 설치하면 기본 설치되는 소스코드를 수정하여 탭으로 화면 구성하는 방법 연습하고 적어둔다.

TabController 생성 → TabBar 에 Tab 추가 → TabBarView에 각 Tab에 해당하는 콘텐츠 구성

 

import 'package:flutter/material.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
        primaryColor: const Color(0xfff0c0f1),
        accentColor: const Color(0xfff0c0f1),
        canvasColor: const Color(0xFFfafafa),
      ),
      home: const MyHomePage(title: '플러터 데모 Main'),
    );
  }
}
 
// Android Studio 에서 stful 엔터를 치면 자동으로 만들어진다.
// 여기에서 클래스 이름만 지정하면 자동으로 만들어진다.
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
 
  final String title; // 선언한 변수는 final을 붙여야 한다.
 
  @override
  State<MyHomePage> createState() => _MyHomePageState();
// Stateless 위젯과 다른 점은 createState() 메소드를 통해
// 상태를 담당하는 클래스를 지정할 수 있다.
}
 
// 클래스 이름 앞에 _가 붙어 있으면 private 클래스로 본다.
// 다트에서는 Java와 같이 public, protected, private 같은 접근 제어자 키워드 없음
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0// _를 붙이면 private
 
  @override
  Widget build(BuildContext context) {
    // TabController 위젯으로 감싼다.
    return DefaultTabController(
        initialIndex: 1,
        length: 3// 탭의 수 설정
        child: Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
            // TabBar 구현, 각 content를 호출할 탭들을 등록
            bottom: TabBar(
              tabs: <Widget>[
                Tab(icon: Icon(Icons.directions_car), text: '첫번째'),
                Tab(icon: Icon(Icons.directions_transit), text: "Transit"),
                Tab(
                  icon: Icon(Icons.directions_bike),
                  text: "Bike",
                ),
              ],
            ),
          ),
          body: TabBarView(
            children: [
              Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center, // 중앙정렬
                  children: <Widget>[
                    Text(
                      '당신은 버튼을 눌렀어요 :',
                      softWrap: false// 텍스트가 영역을 넘어갈 경우 줄바꿈 여부
                      style: Theme.of(context).textTheme.headline5,
                    ),
                    Text(
                      '$_counter 번',
                      style: TextStyle(fontSize: 25),
                    ),
                  ],
                ),
              ),
              Center(
                child: Text("It's rainy here"),
              ),
              Icon(Icons.directions_bike),
            ],
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter, // 정의하고 alt + Enter 를 눌러서 메소드 생성
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
        ));
  }
 
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
}
 

 

참고하면 도움될 자료

https://www.woolha.com/tutorials/flutter-using-tabbar-tabbarview-examples

 

Flutter - Using TabBar & TabBarView Examples

A tutorial of how to create tab layout in Flutter using TabBar and TabBarView

www.woolha.com

https://blog.logrocket.com/flutter-tabbar-a-complete-tutorial-with-examples/#customizethetabindicatorintabbar

 

Flutter TabBar: A complete tutorial with examples - LogRocket Blog

TabBar enables you to improve the UX of your Flutter app by organizing content with tabs for users to tap and scroll through.

blog.logrocket.com

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
Flutter Layout  (0) 2021.12.26
Flutter Theme(테마) 변경  (0) 2021.12.24
Flutter BottomNavigationBar 예제  (0) 2021.12.22
블로그 이미지

Link2Me

,