요약 : GestureDetector, InkWell, Hero, AnimatedContainer, SliverAppBar/SliverFillRemaining/SliverList
GestureDetector, InkWell
- 텍스트나 이미지 등 이벤트효과 없는 위젯을 감싸서 onTap 등의 이벤트를 줄 수 있다.
Hero
- 화면 전환시 자연스럽게 연결되게 하는 애니메이션 위젯 (이미지 클릭하면 상세화면 보여줄 때 사용)
- 두 페이지를 Hero위젯으로 연결
- tag를 동일하게 사용해서 연결시켜줌
class _MyHomePageState extends State<MyHomePage> {
var _selectedTime;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: GestureDetector( // 해당 위젯을 이용해
onTap: () { // 탭하면
Navigator.push( // DetailPage로 화면 전환시켜줌
context,
MaterialPageRoute(builder: (context) => DetailPage()),
);
},
child: Hero(
tag: 'imageTag',
child: Image.asset(
'assets/sample.png',
width: 200,
height: 200
)
)
)
),
);
}
}
class DetailPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar : AppBar(
title: Text('Detail Page'),
),
body: Hero(
tag: 'imageTag',
child: Image.asset('assets/sample.png'),
),
);
}
}
AnimatedContainer
Hero위젯은 화면 전환이었다면 AnimatedContainer위젯은 한 화면 내에서 setState함수를 이용해 애니메이션 효과를 주는 위젯
- duration : 애니메이션 되는 시간 Duration(시간)
- curve : 애니메이션 효과 Curves.xxx(각종효과)
class _MyHomePageState extends State<MyHomePage> {
var _size = 200.0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: GestureDetector(
child: AnimatedContainer(
duration: Duration(seconds: 1), // 애니메이션 효과 1초
curve: Curves.fastOutSlowIn, // 애니메이션 효과
child: Image.asset(
'assets/sample.png',
width: _size,
height: _size
)
),
onTap: () { // 클릭시 이벤트 발생
final random = Random();
setState(() { // _size 상태 변경
_size = random.nextInt(500).toDouble() + 200; // 200.0 ~ 700.0
});
},
)
),
);
}
}
SliverAppBar/SliverFillRemaining
화면 헤더부분을 움직이게 하는 위젯
헤더를 제일 위로 올리면 AppBar 형태로 애니메이션됨 (Sliver 효과)
- Sliver 애니메이션을 사용하려면 Scaffold의 appBar를 지정하지 않고 body에 CustomScrollView를 지정해준다
그 후에 CustomScrollView 안에 SliverAppBar와 SliverFillRemaining을 지정해주면 된다.
- pinned(상단헤더 고정여부), expandedHeight(헤더 최대 높이), flexibleSpace(상단 늘어났을 때 UI) 값들은 필수값이다.
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar( // 헤더 영역
pinned: true, // 축소시 상단에 AppBar가 고정되는지 여부
expandedHeight: 200.0, // 늘어나는 최대 높이
flexibleSpace: FlexibleSpaceBar( // 늘어나는 영역부분
title: Text(
'Sliver App Bar',
style: TextStyle(
fontSize: 30,
color: Colors.pinkAccent,
fontStyle: FontStyle.italic
),
),
background: Image.asset(
'assets/spring-5093894__480.jpg',
fit: BoxFit.cover
),
),
),
SliverFillRemaining( // 스크롤 영역에 표시될 화면
child: Center(
child: Text('contents~~~',
style: TextStyle(
fontSize: 40
),
),
),
),
],
),
);
SliverAppBar/SliverList
위의 SliverFillRemaining은 고정된 화면이지만 SliverList를 사용하면 하단부 화면을 List 형태로 사용이 가능하다.
- delegate 프로퍼티가 필수이며 SliverChildListDelegate를 지정해야 함 (ListTile 목록)
class _MyHomePageState extends State<MyHomePage> {
final _list = List.generate(100, (i) => ListTile(title: Text('#$i')));
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar( // 헤더 영역
pinned: true, // 축소시 상단에 AppBar가 고정되는지 여부
expandedHeight: 200.0, // 늘어나는 최대 높이
flexibleSpace: FlexibleSpaceBar( // 늘어나는 영역부분
title: Text(
'Sliver App Bar',
style: TextStyle(
fontSize: 30,
color: Colors.pinkAccent,
fontStyle: FontStyle.italic
),
),
background: Image.asset(
'assets/spring-5093894__480.jpg',
fit: BoxFit.cover
),
),
),
SliverList( // 스크롤 영역에 표시될 화면
delegate: SliverChildListDelegate(_list),
),
],
),
);
}
}
댓글