전체코드
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
HeroSample createState() => HeroSample();
}
class HeroSample extends State<MyHomePage>{
@override
Widget build(BuildContext context){
double appBarHeight = 50.0;
return MaterialApp(
home: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(appBarHeight),
child:AppBar(
title: Text('Hero Demo'),
backgroundColor: Colors.cyan,
),
),
body: GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => HeroBlue()));
},
child: Blue()
),
),
);
}
}
class HeroBlue extends StatelessWidget {
double appBarHeight = 40.0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(appBarHeight),
child: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context); //이전 페이지로 이동.
},
),
backgroundColor: Colors.cyan,
),
),
body: DoubleBlue(),
)
);
}
}
class Blue extends StatelessWidget {
@override
Widget build(BuildContext context){
return new LayoutBuilder(builder: (context, constraint) {
double min = (constraint.biggest.width < constraint.biggest.height)
? constraint.biggest.width : constraint.biggest.height;
return Container(
width: constraint.biggest.width,
height: constraint.biggest.height,
color: Colors.blue,
child: Hero(
tag: "b",
child: Icon(Icons.access_alarms, size: min / 2, color: Colors.white),
)
);
});
}
}
class DoubleBlue extends StatelessWidget {
@override
Widget build(BuildContext context){
return new LayoutBuilder(builder: (context, constraint) {
double min = (constraint.biggest.width < constraint.biggest.height)
? constraint.biggest.width : constraint.biggest.height;
return Column(
children: [
Container(
width: constraint.biggest.width,
height: constraint.biggest.height / 2,
color: Colors.blue,
child: Hero(
tag: "b",
child: Icon(Icons.access_alarms, size: min / 2, color: Colors.white),
)
),
Container(
width: constraint.biggest.width,
height: constraint.biggest.height / 2,
color: Colors.blue,
child: Icon(Icons.access_alarms, size: min / 2, color: Colors.white),
),
]
);
});
}
}
실행순서 : void main() > class MyApp (Widgt build) > class MyHomePage (_MyHomePageState createState) > class HeroSample > body : blue(), body에 해당하는 부분 click 시 class HeroBlue, 이전버튼 click 시 class HeroSample
GestureDetector
class HeroSample extends State<MyHomePage>{
...
body: GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => HeroBlue()));
},
child: Blue()
),
...
}
사용자의 터치제스처를 감지한다. "onTap: " 은 한번 터치했을때 실행되는 함수이다. "child: " 에 할당된 Blue() Widget이 처음 화면에 출력되고 Blue()가 출력되는 공간을 한번 터치하면 Navigator.push와 MeterialPageRoute를 통해 다음 Page인 HeroBlue()를 출력한다.
Navigator : Stack 규칙을 사용하여 하위 Widget들을 관리하는 Widget. push, pop을 통해 Widget을 삽입하고 삭제할 수 있다.(LIFO)
MeterialPageRoute : 사용하는 플랫폼에 맞게 화면이 전환되는 Widget. (Android 는 아래위로 전환되고 IOS는 좌우로 전환된다.)
Hero(1)
class Blue extends StatelessWidget {
...
child: Hero(
tag: "b",
child: Icon(Icons.access_alarms, size: min / 2, color: Colors.white),
)
...
}
기존 Blue() Widget에서 Icon 부분을 Hero로 감쌌다. Hero Widget은 Page가 변화할때 "tag : "가 같은 것 끼리 자연스러운 애니메이션을 형성해 준다. 이번 sample에서는 DoubleBlue와 Blue 에서 공통적으로 들어가는 Icon 한개에 적용하여 Page가 이동할 때 자연스럽게 전환되는 것을 구현하였다. (Hero Widget은 "tag: " 요소와 "child: " 요소를 반드시 할당하여야 한다.)
HeroBlue
class HeroBlue extends StatelessWidget {
double appBarHeight = 40.0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(appBarHeight),
child: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context); //이전 페이지로 이동.
},
),
backgroundColor: Colors.cyan,
),
),
body: DoubleBlue(),
)
);
}
}
상단에 IconButton을 통해 뒤로가기 버튼을 만들고 "Onpressed: " 에 Navigator.pop을 할당하여 Icon클릭 시 이전Page로 돌아가게 구현하였다. "body: " 에 할당되는 DoubleBlue() 와 Blue() 에서 Hero를 통해 전환애니메이션이 실행된다.
Hero(2)
class DoubleBlue extends StatelessWidget {
@override
Widget build(BuildContext context){
return new LayoutBuilder(builder: (context, constraint) {
double min = (constraint.biggest.width < constraint.biggest.height)
? constraint.biggest.width : constraint.biggest.height;
return Column(
children: [
Container(
width: constraint.biggest.width,
height: constraint.biggest.height / 2,
color: Colors.blue,
child: Hero(
tag: "b",
child: Icon(Icons.access_alarms, size: min / 2, color: Colors.white),
)
),
Container(
width: constraint.biggest.width,
height: constraint.biggest.height / 2,
color: Colors.blue,
child: Icon(Icons.access_alarms, size: min / 2, color: Colors.white),
),
]
);
});
}
}
Blue() Widget을 위아래로 2등분하여 2개 출력하는 Widget이다. Hero로 묶인 Icon이 Blue()의 Icon과 "tag: " 가 같기 때문에 화면이 전환될 때 해당 Icon에 애니메이션 효과가 나타난다.
'Flutter' 카테고리의 다른 글
Flutter Column, Row _ Expanded, Stack (0) | 2020.07.24 |
---|---|
Flutter 해상도별 Image (0) | 2020.07.24 |
Flutter TabBar (0) | 2020.07.21 |
Flutter Swiper (0) | 2020.07.21 |
Flutter 기본 Widget 구현 (0) | 2020.07.17 |