[Flutter] animations의 OpenContainer에서 조금 빠졌습니다.
이 기사는
Flutter의 Package인 animations
경위
비교적 풍부한 애니메이션을 간단하게 구현할 수 있는 animations를 시험해보고 싶다. example
main_screen.dartclass MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF7F7F8),
appBar: AppBar(
title: const Text('猫ちゃん'),
),
body: ListView(
children: <Widget>[
_OpenContainerWrapper(
openPage: const CatPage(),
closedBuilder: (BuildContext _, VoidCallback openContainer) {
return ReusableCard(
imagePath: 'assets/images/cat.jpg',
contentTitle: '猫ちゃん',
onPress: openContainer,
);
},
),
],
),
);
}
}
class _OpenContainerWrapper extends StatelessWidget {
const _OpenContainerWrapper({
this.closedBuilder,
this.openPage,
});
final OpenContainerBuilder closedBuilder;
final Widget openPage;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: OpenContainer(
transitionType: ContainerTransitionType.fade,
openBuilder: (BuildContext context, VoidCallback _) {
return openPage;
},
tappable: false,
closedBuilder: closedBuilder,
),
);
}
}
아이템을 탭하여 애니메이션을 하면서 CatPage()
로 전환한다고 가정합니다.
여기서 나는 "ListView
의 아이에게는 둥근의 Card를 사용하고 싶으니까, ReusableCard
는 Card()
를 사용해야 할 것이다"라고 안직하게 생각해, 이하와 같이 썼습니다.
reusable_card.dartclass ReusableCard extends StatelessWidget {
const ReusableCard({
@required this.imagePath,
@required this.contentTitle,
@required this.onPress,
});
final String imagePath;
final String contentTitle;
final VoidCallback onPress;
@override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: onPress,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Image.asset(
imagePath,
fit: BoxFit.fill,
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 24, 0, 24),
child: Text(
contentTitle,
style: Theme.of(context).textTheme.bodyText2.copyWith(
fontWeight: FontWeight.bold,
),
),
),
],
),
),
);
}
}
그리고 build 해 보면,,,
왜 Card가 이중으로. . .
원인
원인은 OpenContainer
의 closedShape
이었습니다.
open_container.dart const OpenContainer({
Key key,
this.closedColor = Colors.white,
this.openColor = Colors.white,
this.closedElevation = 1.0,
this.openElevation = 4.0,
// ↓これ
this.closedShape = const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
this.openShape = const RoundedRectangleBorder(),
@required this.closedBuilder,
@required this.openBuilder,
this.tappable = true,
this.transitionDuration = const Duration(milliseconds: 300),
this.transitionType = ContainerTransitionType.fade,
}) : assert(closedColor != null),
assert(openColor != null),
assert(closedElevation != null),
assert(openElevation != null),
assert(closedShape != null),
assert(openShape != null),
assert(closedBuilder != null),
assert(openBuilder != null),
assert(tappable != null),
assert(transitionType != null),
super(key: key);
closedShape 는, 탭 애니메이션 전의 형태 (이 경우 List 의 Item 의 형태)를 지정하는 파라미터입니다.
closedShape에는 디폴트로 둥근 4dp의 RoundedRectangleBorder
가 지정되어 있어 그 아이에 Card를 넣고 있었기 때문에, 둥근 것이 이중으로 배치되어 버렸다고 하는 것이었습니다.
이번의 경우는, ReusableCard의 Card 부분을 제거해 주면 해결입니다.
reusable_card.dartclass ReusableCard extends StatelessWidget {
const ReusableCard({
@required this.imagePath,
@required this.contentTitle,
@required this.onPress,
});
final String imagePath;
final String contentTitle;
final VoidCallback onPress;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onPress,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Image.asset(
imagePath,
fit: BoxFit.fill,
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 24, 0, 24),
child: Text(
contentTitle,
style: Theme.of(context).textTheme.bodyText2.copyWith(
fontWeight: FontWeight.bold,
),
),
),
],
),
);
}
}
다른 shape로 할 때는 closedShape에 명시적으로 지정해 봅시다.
끝에
지금 생각하면 왜 이런 단순한 실수를 깨닫지 못했는지 부끄러운 기분입니다만, 똑같이 집착한 분이 있을지도 모르기 때문에, 그 때의 도움이 되면 다행입니다.
Reference
이 문제에 관하여([Flutter] animations의 OpenContainer에서 조금 빠졌습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/hammer0802/items/5651d3334e3b1121ec96
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
비교적 풍부한 애니메이션을 간단하게 구현할 수 있는 animations를 시험해보고 싶다. example
main_screen.dart
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF7F7F8),
appBar: AppBar(
title: const Text('猫ちゃん'),
),
body: ListView(
children: <Widget>[
_OpenContainerWrapper(
openPage: const CatPage(),
closedBuilder: (BuildContext _, VoidCallback openContainer) {
return ReusableCard(
imagePath: 'assets/images/cat.jpg',
contentTitle: '猫ちゃん',
onPress: openContainer,
);
},
),
],
),
);
}
}
class _OpenContainerWrapper extends StatelessWidget {
const _OpenContainerWrapper({
this.closedBuilder,
this.openPage,
});
final OpenContainerBuilder closedBuilder;
final Widget openPage;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: OpenContainer(
transitionType: ContainerTransitionType.fade,
openBuilder: (BuildContext context, VoidCallback _) {
return openPage;
},
tappable: false,
closedBuilder: closedBuilder,
),
);
}
}
아이템을 탭하여 애니메이션을 하면서
CatPage()
로 전환한다고 가정합니다.여기서 나는 "
ListView
의 아이에게는 둥근의 Card를 사용하고 싶으니까, ReusableCard
는 Card()
를 사용해야 할 것이다"라고 안직하게 생각해, 이하와 같이 썼습니다.reusable_card.dart
class ReusableCard extends StatelessWidget {
const ReusableCard({
@required this.imagePath,
@required this.contentTitle,
@required this.onPress,
});
final String imagePath;
final String contentTitle;
final VoidCallback onPress;
@override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: onPress,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Image.asset(
imagePath,
fit: BoxFit.fill,
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 24, 0, 24),
child: Text(
contentTitle,
style: Theme.of(context).textTheme.bodyText2.copyWith(
fontWeight: FontWeight.bold,
),
),
),
],
),
),
);
}
}
그리고 build 해 보면,,,
왜 Card가 이중으로. . .
원인
원인은 OpenContainer
의 closedShape
이었습니다.
open_container.dart const OpenContainer({
Key key,
this.closedColor = Colors.white,
this.openColor = Colors.white,
this.closedElevation = 1.0,
this.openElevation = 4.0,
// ↓これ
this.closedShape = const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
this.openShape = const RoundedRectangleBorder(),
@required this.closedBuilder,
@required this.openBuilder,
this.tappable = true,
this.transitionDuration = const Duration(milliseconds: 300),
this.transitionType = ContainerTransitionType.fade,
}) : assert(closedColor != null),
assert(openColor != null),
assert(closedElevation != null),
assert(openElevation != null),
assert(closedShape != null),
assert(openShape != null),
assert(closedBuilder != null),
assert(openBuilder != null),
assert(tappable != null),
assert(transitionType != null),
super(key: key);
closedShape 는, 탭 애니메이션 전의 형태 (이 경우 List 의 Item 의 형태)를 지정하는 파라미터입니다.
closedShape에는 디폴트로 둥근 4dp의 RoundedRectangleBorder
가 지정되어 있어 그 아이에 Card를 넣고 있었기 때문에, 둥근 것이 이중으로 배치되어 버렸다고 하는 것이었습니다.
이번의 경우는, ReusableCard의 Card 부분을 제거해 주면 해결입니다.
reusable_card.dartclass ReusableCard extends StatelessWidget {
const ReusableCard({
@required this.imagePath,
@required this.contentTitle,
@required this.onPress,
});
final String imagePath;
final String contentTitle;
final VoidCallback onPress;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onPress,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Image.asset(
imagePath,
fit: BoxFit.fill,
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 24, 0, 24),
child: Text(
contentTitle,
style: Theme.of(context).textTheme.bodyText2.copyWith(
fontWeight: FontWeight.bold,
),
),
),
],
),
);
}
}
다른 shape로 할 때는 closedShape에 명시적으로 지정해 봅시다.
끝에
지금 생각하면 왜 이런 단순한 실수를 깨닫지 못했는지 부끄러운 기분입니다만, 똑같이 집착한 분이 있을지도 모르기 때문에, 그 때의 도움이 되면 다행입니다.
Reference
이 문제에 관하여([Flutter] animations의 OpenContainer에서 조금 빠졌습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/hammer0802/items/5651d3334e3b1121ec96
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
const OpenContainer({
Key key,
this.closedColor = Colors.white,
this.openColor = Colors.white,
this.closedElevation = 1.0,
this.openElevation = 4.0,
// ↓これ
this.closedShape = const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
this.openShape = const RoundedRectangleBorder(),
@required this.closedBuilder,
@required this.openBuilder,
this.tappable = true,
this.transitionDuration = const Duration(milliseconds: 300),
this.transitionType = ContainerTransitionType.fade,
}) : assert(closedColor != null),
assert(openColor != null),
assert(closedElevation != null),
assert(openElevation != null),
assert(closedShape != null),
assert(openShape != null),
assert(closedBuilder != null),
assert(openBuilder != null),
assert(tappable != null),
assert(transitionType != null),
super(key: key);
class ReusableCard extends StatelessWidget {
const ReusableCard({
@required this.imagePath,
@required this.contentTitle,
@required this.onPress,
});
final String imagePath;
final String contentTitle;
final VoidCallback onPress;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onPress,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Image.asset(
imagePath,
fit: BoxFit.fill,
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 24, 0, 24),
child: Text(
contentTitle,
style: Theme.of(context).textTheme.bodyText2.copyWith(
fontWeight: FontWeight.bold,
),
),
),
],
),
);
}
}
지금 생각하면 왜 이런 단순한 실수를 깨닫지 못했는지 부끄러운 기분입니다만, 똑같이 집착한 분이 있을지도 모르기 때문에, 그 때의 도움이 되면 다행입니다.
Reference
이 문제에 관하여([Flutter] animations의 OpenContainer에서 조금 빠졌습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/hammer0802/items/5651d3334e3b1121ec96텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)