[Flutter] Bottom fixed footer를 갖는 scrollable widget 만들기

이 글에서는 vertical direction scroll을 가정한다. Overview Scrollable widget은 전체 content 높이가 화면 높이보다 작다면 scroll이 활성화되지 않고 content들이 상단 정렬된다. 아래는 SingleChildScrollView에 Column을 사용해서 content widget과 footer widget을 배치하는 예시이다. Code Demo Footer widget을 화면 하단에 배치하기 위해 content와 footer widget 사이에 Spacer, Expanded와 같은 flexible widget을 사용하면 unbounded height error가 발생한다. Scrollable widget은 child widget에게 unbounded height constraint를 제안하는데, Spacer나 Expanded도 unbounded size를 갖기 때문이다. Fixed Footer 구현 위 error를 해결하려면 아래와 같은 조건이 필요하다....

August 16, 2024 · 2 min

[Flutter] 🇰🇷 광복절 기념 태극기 그리기 🇰🇷

Overview 광복절을 기념해서 Flutter로 태극기를 그려봤다. (Repository) 태극기 도면을 참고했고, CustomPaint를 사용했다. 깃면 그리기 태극기 깃면의 가로:세로 비율은 3:2이므로, AspectRatio로 3:2 비율의 widget을 만든다. DecoratedBox를 사용해서 border를 그려준다. AspectRatio의 child에 LayoutBuilder를 사용해서 CustomPaint의 size를 깃면 size로 설정한다. CustomPaint는 이 수치를 기반으로 태극 문양과 괘의 layout을 계산한다. 태극 문양 그리기 태극 문양은 아래 두 단계에 걸쳐 그릴 수 있다. 빨간색과 파란색 반으로 나뉜 원을 그린다. 반지름을 지름으로 하는 빨간색, 파란색 원을 왼쪽, 오른쪽에 덮어서 그린다....

August 15, 2024 · 2 min

[Dart] List.from, List.of, toList() 비교

Summary 셋 모두 Iterable object를 동일한 element를 가진 새 List로 copy할 때 사용할 수 있다. toList()는 List.of의 short-hand method로 서로 같다. List.from은 original Iterable의 element들을 runtime에 result type으로 casting하고, casting에 실패하면 runtime error를 발생시킨다. List.of는 original Iterable의 element들이 result type과 같거나 하위 type인지 compile-time에 check하고, type이 호환되지 않으면 compile-time error를 발생시킨다. List.from은 original Iterable을 down casting할 때 사용할 수 있고, List.of는 up casting할 때 사용할 수 있다. Copy 할 때 original type을 지켜야 한다면 toList() 또는 List....

August 4, 2024 · 3 min

Nomadcoders Flutter 10주 스터디 후기

나는 iOS 개발자로 일하다가 지난 해 퇴사 후 안식년을 갖고 있다. 쉬는 동안 개발자라는 직업에 대한 고민을 많이 하고 있는데, 나는 어떤 개발자가 되고 싶은지 방향성을 잃어가고 있다는 생각이 들었기 때문이다. 개발하는 것 자체는 즐거운 일이지만 개발자라는 직업이 정말 나와 맞는지, 개발자를 오래 할 수 있을지 확신이 들지 않았다. 그래서, 쉬는 동안 다양한 개발 분야를 넓게 경험해보면서 생각을 정리해보고 있다. Flutter 10주 스터디 전에도 노마드코더에서 웹 기초 10주 스터디에 참여했던 적이 있다....

July 31, 2024 · 3 min

GitHub Pages와 Hugo PaperMod 테마로 블로그 만들기

GitHub Pages 블로그를 Hugo PaperMod 테마를 사용해서 블로그를 만든 방법을 기록해 둔다. [PaperMod WiKi - Installation] 문서와 블로그를 참고했다. Installation Hugo 설치 및 site 생성 (작성일 기준 최신 버전 테마는 Hugo 버전 v0.112.4 이상 필요) $ brew install hugo $ hugo new site MyFreshWebsite --format yaml Theme 설치 (권장 방식인 git submodule 사용) # Initialize git repository $ git init && git commit -am "initial commit" # Install theme $ git submodule add --depth=1 https://github....

July 29, 2024 · 2 min

[Dart] Dart에서 type casting을 안전하게 하는 방법

Swift에서는 as?로 안전하게 type casting을 할 수 있었다. class A {} class B: A {} class C {} let a = A() let b = B() b as? C// nil Dart는 as keyword로 type casting을 할 수 있지만, incompatible type으로 casting을 시도하면 type error가 발생한다. Dart에는 optional casting 연산자가 따로 없으므로, error 없이 type casting을 하려면 type check를 먼저 해야 한다. class A {} class B extends A {} class C {} final a = A(); final b = B(); a as C // ❗️ type error if (a is C) { a as C // Never executed } if (a is B) { a as B // ✅ OK } 매번 type check를 하려면 번거로우므로, 아래와 같은 extension을 만들어서 사용하면 편리하다....

July 20, 2024 · 1 min

[Flutter] 'customizable_text' package 개발 기록

개발 동기 노마드코더 챌린지 과제 중 아래와 같은 text UI를 구현하는 부분이 있었다. 회원가입 중 이용 약관이나 개인 정보 처리 방침 등을 사용자에게 안내하고 관련 외부 문서로 이동하여 확인할 수 있게 만드는 보편적인 UI 이다. Flutter에서 text에 다양한 style을 적용할 때 RichText 또는 Text.rich를 사용하므로, 이 UI를 구현하기 위해 아래와 같이 코드를 작성했다. 이렇게 코드를 작성하면 몇 가지 문제가 있다. 다른 style을 사용할 text를 직접 분류해서 나누어 작성해야 하므로 실수할 가능성이 있다....

June 26, 2024 · 4 min

[Flutter] Flutter Constraint 이해하기

Flutter Constraint와 Layout Flutter는 3단계를 거쳐 widget의 layout을 결정한다. Constraints go down : Parent widget이 child widget에 constraint를 제안한다. Sizes go up : Child widget은 constraint 범위 내의 size를 parent widget에 알려준다. Parent sets position : Parent widget은 자신의 alignment 정보와 child widget size를 사용해서 child widget의 position을 결정한다. 여기서 “constraint“란 size의 최대 ~ 최소값의 범위를 말한다. Flutter에서는 BoxConstraints class를 주로 사용하여 minWidth, minHeight, maxWidth, maxHeight을 정의한다. const BoxConstraints({ this.minWidth = 0....

June 25, 2024 · 2 min

[Flutter] Scrollable TabBar의 왼쪽 여백 제거하기

TabBar의 isScrollable을 true로 설정하면 왼쪽에 default padding이 잡힘 Flutter 3.16.0 버전부터 Material 3 디자인이 적용되면서, isScrollable이 true일 때 tabAlignment 속성의 기본값이 TabAlignment.startOffset이 됨 Material3 에서 TabBar의 기본 alignment Material2 에서 TabBar의 기본 alignment TabAlignment.startOffset은 왼쪽에 52px offset을 추가하기 때문에 왼쪽에 여백이 생기는 것 따라서, 아래 세 가지 방법으로 left offset을 제거할 수 있다. Material 3를 사용하지 않도록 설정 TabBar.tabAlignment를 TabAlignment.start로 설정 TabBar.padding에 EdgeInsets.only(left: 10)처럼 원하는 offset으로 override Reference Scrollable Tabs have a gap on the left | GitHub Issue Customizing tabs alignment using the new TabBar....

June 23, 2024 · 1 min

[Flutter] ListView에 Clip.none 설정 시 item이 사라지는 문제

문제 상황 ListView를 Clip.none으로 설정하면 item들이 scroll될 때 ListView의 실제 영역을 벗어나서 화면 밖으로 사라질 때 까지 화면에 유지될 것이라고 예상 하지만 실제로는 item이 화면 밖으로 나가기 전에 먼저 화면에서 사라짐 이 ListView는 Padding 및 다른 widget들의 하위 widget 원인 분석 Flutter GitHub에 이미 같은 문제로 issue가 올라왔었다. 이 repo의 contributor에 따르면, 이것은 의도된 동작이라고 한다. it looks like this is working as intended.. The Padding around the ListView is what is causing this effect....

June 22, 2024 · 2 min