첫번째는 scrollController를 사용했다.
ScrollController _scrollController = ScrollController();
GestureDetector(
onTap: () {
},
child: Container(
color: menuBar,
height: 45,
key: indexKey,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: () {
final double scrollPosition =
_scrollController.position.pixels;
// 상태 변경 및 리렌더링
setState(() {
index = 0;
});
// 스크롤 위치 복원
_scrollController.jumpTo(scrollPosition);
},
child: Text("상세정보",
style: index == 0
? TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallMainColor,
)
: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallArrowColor,
)),
),
VerticalDivider(
thickness: 1,
indent: 15, //Spacing at the top of divider.
endIndent:
15, //Spacing at the bottom of divider.
),
GestureDetector(
onTap: () {
final double scrollPosition =
_scrollController.position.pixels;
// 상태 변경 및 리렌더링
setState(() {
index = 1;
});
// 스크롤 위치 복원
_scrollController.jumpTo(scrollPosition);
},
child: Text(
"리뷰 ${detail.reviewCount}",
style: index == 1
? TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallMainColor,
)
: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallArrowColor,
),
),
),
VerticalDivider(
thickness: 1,
indent: 15, //Spacing at the top of divider.
endIndent:
15, //Spacing at the bottom of divider.
),
GestureDetector(
onTap: () {
final double scrollPosition =
_scrollController.position.pixels;
// 상태 변경 및 리렌더링
setState(() {
index = 2;
});
// 스크롤 위치 복원
_scrollController.jumpTo(scrollPosition);
},
child: Text(
"문의하기 ${detail.inquireCount}",
style: index == 2
? TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallMainColor,
)
: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallArrowColor,
),
),
),
],
),
),
)
스크롤 위치를 저장하고 다시 그 위치로 돌아가는 방법이다.
근데 안됐다. 위젯이 꼬여있어서 그런가..
글로버키도 사용했다. 이는 탭바를 누를 경우 탭바를 맨 상단으로 이동시키는 방법이다.
final GlobalKey indexKey = GlobalKey();
GestureDetector(
onTap: () {
Scrollable.ensureVisible(
indexKey
.currentContext!,
duration: Duration(seconds: 1),
curve: Curves.easeInOut,
alignment: 0);
},
child: Container(
color: menuBar,
height: 45,
key: indexKey,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: () {
setState(() {
index = 0;
});
},
child: Text("상세정보",
style: index == 0
? TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallMainColor,
)
: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallArrowColor,
)),
),
VerticalDivider(
thickness: 1,
indent: 15, //Spacing at the top of divider.
endIndent:
15, //Spacing at the bottom of divider.
),
GestureDetector(
onTap: () {
setState(() {
index = 1;
});
},
child: Text(
"리뷰 ${detail.reviewCount}",
style: index == 1
? TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallMainColor,
)
: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallArrowColor,
),
),
),
VerticalDivider(
thickness: 1,
indent: 15, //Spacing at the top of divider.
endIndent:
15, //Spacing at the bottom of divider.
),
GestureDetector(
onTap: () {
setState(() {
index = 2;
});
},
child: Text(
"문의하기 ${detail.inquireCount}",
style: index == 2
? TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallMainColor,
)
: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: mallArrowColor,
),
),
),
],
),
),
)
사용법은 이렇다. 글로벌키를 통해 원하는 위젯의 위치를 기억한 다음, 이벤트가 발생하면 그 위치를 찾아가는 방법이다.
duration은 거기까지 가는 시간을 결정한다. 이를 통해 얼마나 빠른 속도로 스크롤해서 이동할지 결정한다.
alignment: 0은 이 위젯을 화면 맨 위에 맞춘다는 의미이다. 1이라면 맨 아래에 맞도록 맞춘다.
해결한 방법은 그 부분은 건들지 않고 리렌더링되는 위젯을 stackindex로 감싸줘서 해결했다.
before
if (index == 0) DetailInfo(detail: _productDetail),
if (index == 1)
ReviewInfo(
rating: _rating,
product_img: "assets/icons/product_default.png",
product_code: widget.productCode,
),
if (index == 2)
InqueryInfo(
widget: widget,
)
after
IndexedStack(
index: index,
children: [
DetailInfo(detail: _productDetail),
ReviewInfo(
rating: _rating,
product_img: "assets/icons/product_default.png",
product_code: widget.productCode,
),
InqueryInfo(
widget: widget,
),
],
),
],
구조는 아래와 같다. 필요했던 이유는 리뷰를 선택하거나 문의하기를 선택할 때 index가 바뀌면서 아래 정보를 위한 위젯이 리렌더링되고 바뀌는데 그에 따라 화면이 자꾸 처음 상태로 움직여서 화면 전체가 새로고침되는 느낌이었기 때문이다. 바뀜으로써, 같은 화면에서 하단 위젯만 바뀌는 것처럼 잘 해결되었다. 다음으로는 상세정보, 리뷰, 문의하기가 있는 바가 화면 밖으로 벗어난다면 상단에 고정하는 방법을 알아볼 것이다. index가 바뀔 때 하위 위젯만 리렌더링되기 때문에 가능하다.
'flutter' 카테고리의 다른 글
[flutter] 위젯에 함수 전달하기 - 무한반복 벗어나기 (0) | 2023.07.22 |
---|---|
[flutter] gridview 사이즈에 맞게 높이 조절하기 -item의 수에 따라 높이 조절(사진 접었다가 펴기) (0) | 2023.07.15 |
[flutter] 이미지 슬라이드 - CarouselSlider (0) | 2023.07.11 |
[flutter] 새로운 페이지를 열 때는 단순한 인자 (0) | 2023.07.09 |
[flutter] 페이지네이션(무한스크롤) 커스터마이징 - error 상황 -infinite_scroll_pagination (0) | 2023.07.07 |