플러터2

김지원·2023년 9월 27일
0
import 'package:flutter/material.dart';

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

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: StorePage(),
    );
  }
}

class StorePage extends StatelessWidget {
  StorePage({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(

    );
  }
}

일반적인 앱은
return Scaffold();
부터 시작한다


Row 가로

Column 세로

Listview 세로인데 스크롤가능해서 많이 넣게

Container = html,css의 div같은거
자식이 없으면 최대한 크게 잡히고
자식이 있으면 자식 크기에 맞게 조정됨


무조건 부모 제약조건에 따라서 자식 따라감

부모의 Constrain
constraints: BoxConstraints(
minWidth: double.infinity,
maxWidth: double.infinity,,
minHeight: double.infinity,
maxHeight: double.infinity,
)

때문에 자식 크기 변경이 안되면
자식을 다른 걸로 감싸자 (Align이 좋음 배치하는 위치도 정할 수 있고)

https://wikidocs.net/168663

Constraints go down. Sizes go up. Parent sets position.

제약사항(constraints) 범위를 결정하는 것은 부모 위젯
크기를 결정하는 것은 자식 위젯
자식의 위치를 결정하는 것은 부모 위젯
위 내용을 알아야 플러터의 레이아웃 컨셉을 이해할 수 있으며 더 자세히 설명하면 아래와 같다.

모든 위젯은 부모로부터 자신의 제약사항을 내려 받는다. 이 때 제약사항은 네 개의 실수(double)이며 최소 너비, 최대 너비, 최소 높이, 최대 높이이다.
부모 위젯은 자식 위젯들에게 자신들의 제약사항을 알려준다. 이 때 제약사항이 자식마다 다를 수 있다. 부모 위젯은 각각의 자식 위젯이 필요로 하는 크기를 구한다.
부모 위젯은 각각의 자식 위젯의 위치를 결정한다.
부모 위젯은 자신의 크기를 결정하고 또 위로 자신의 부모 위젯에 자신의 크기를 알려준다. (물론 자신의 제약사항을 벗어날 수는 없다.)


const로 만들면 상태가 똑같음
상태가 다르면 const로 만들면 안된다


모든 위젯은 SizedBox로 감싸서 width, height를 주면 크기를 지정할 수 있다


tabbar
SingleTickerProviderStateMixin 를 with한다(컴퍼지션)
initState 오버라이드 (처음 실행때만 1번 실행됨. 초기화역할)
클래스 필드로 TabController? _tabController; 추가하고 인잇스테이트때 만들어지게

import 'package:flutter/material.dart';

class ProfileTab extends StatefulWidget {
  
  _ProfileTabState createState() => _ProfileTabState();
}

class _ProfileTabState extends State<ProfileTab>
    with SingleTickerProviderStateMixin {
  TabController? _tabController; // 탭바와 탭바뷰를 연결함

  
  void initState() {
    // 처음에 오브젝트 초기화 메서드
    super.initState();
    _tabController = TabController(length: 3, vsync: this);
    print("initState초기화됨");
  }

  
  Widget build(BuildContext context) {
    print("빌드다시됨");
    return Column(
      children: [
        TabBar(
          controller: _tabController,
          tabs: [
            Tab(icon: Icon(Icons.directions_car)),
            Tab(icon: Icon(Icons.directions_transit)),
            Tab(icon: Icon(Icons.directions_bike)),
          ],
        ),
        Expanded(
          child: TabBarView(
            controller: _tabController,
            children: [
              GridView.builder(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    mainAxisSpacing: 5, crossAxisSpacing: 5, crossAxisCount: 3),
                itemCount: 50,
                itemBuilder: (context, index) => Image.network(
                    "https://picsum.photos/id/${index + 50}/200/200"),
              ),
              GridView(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3, crossAxisSpacing: 5, mainAxisSpacing: 5),
                children: [
                  Container(color: Colors.green),
                ],
              ),
              GridView(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3, crossAxisSpacing: 5, mainAxisSpacing: 5),
                children: [
                  Container(color: Colors.red),
                ],
              ),
            ],
          ),
        ),
      ],
    );
  }
}

GridView

              GridView.builder(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3, mainAxisSpacing: 1, crossAxisSpacing: 1),
                itemCount: 22,
                itemBuilder: (context, index) => Image.network(
                    "https://picsum.photos/id/${index+1}/200/200"),
              )

네이스티스크롤뷰
전체가 리스트인데 그 안에 리스트가 또 있을때 사용

NestedScrollView

      body: NestedScrollView(
        headerSliverBuilder: (context, innerBoxIsScrolled) {
          return [
            SliverList(
                delegate: SliverChildListDelegate([
              ProfileHeader(),
              ProfileCountInfo(),
              ProfileButtons(),
            ]))
          ];
        },
        body: Expanded(child: ProfileTab()), // 리스트(스크롤있는거) 바디에 넣기
      )

자주 쓰는 거나 앱 기본 디자인은 테마


context=위치 정보


화면 이동
https://jong99.tistory.com/167

Navigator 스택에 새 페이지를 push하면 해당 페이지로 이동이 되고, pop하면 이전 페이지로 이동하는 형태이다. Pop하다가 더이상 뺄 페이지가 없으면 앱이 종료된다.

      initialRoute: "/login", // 앱 처음 시작화면
      routes: {
        "/login": (context) => LoginPage(),
        "/home": (context) => HomePage(),
      },

MyApp에 routes 해두고

            Form(
              child: Column(
                children: [
                  CustomTextFormField(text: "Email"),
                  CustomTextFormField(text: "Password", isPassword: true),
                  SizedBox(height: large_gap),
                  TextButton(
                    onPressed: () {
                      Navigator.pushNamed(context, "/home"); // 푸쉬네임하면 화면 두장이 겹침
                    },
                    child: Text("Login"),
                  )
                ],
              ),
            )

https://velog.io/@merci/Flutter-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%9C%A0%ED%9A%A8%EC%84%B1%EA%B2%80%EC%82%AC

profile
https://github.com/k7850

0개의 댓글

관련 채용 정보