유저가 작성한 인사이트 카드를 여러사람에게 맞춰 보여주는 건 쉽지 않은 일이겠지? ㅋㅋ 아마 Query가 마이 복잡해 질거야. 앱에서 firestore에 다이렉트로 못 할 수도 있고.. 이럴 경우에는 Backend에서 해야겠지. 그렇다고 손놓고 있으면 등신이고. 걍 일단 시간순으로 정렬해서 listview로 보여주자고..
Insight card는 단순하게 header, body, bottom 이렇게 3부분으로 나뉘는데 header에는 chart의 요약 정보가 들어갈거고 body에는 유저, 카드 내용이, 그리고 bottom에는 스크랩, 댓글 달기, 외부 공유를 할 수 있는 버튼이 있어. header와 bottom은 구현해야할 게 엄청 많으니까 일단 body만 읽어와서 뿌려줄건데 처음에는 귀엽게 10개를 고정으로 읽어보자 ㅋ
우선 컨트롤러의 onInit에서 순서대로 정렬한 insightcard 10개를 읽도록 해놓고. 👇
class ScreenHomeController extends GetxController {
var userInsightCardColRef =
firestore.collection("userInsightCard").withConverter(
fromFirestore: (snapshot, options) =>
InsightCardModel.fromJson(snapshot.data()!),
toFirestore: (value, options) => value.toJson(),
);
var _insightCards = Rx<List<QueryDocumentSnapshot<InsightCardModel>>>([]);
List<QueryDocumentSnapshot<InsightCardModel>> get insightCards =>
_insightCards.value;
@override
void onInit() {
// TODO: implement onInit
super.onInit();
userInsightCardColRef.orderBy("createdAt").limit(10).get().then(
(value) {
_insightCards.value = value.docs;//읽어왓!
},
);
}
그리고 Obx로 감싼 ListView.builder에 item으로 InsightCard위젯을 넣어주면 끝.
class ScreenHome extends GetView<ScreenHomeController> {
const ScreenHome({super.key, this.navKey});
final NavKeys? navKey;
static const routeName = '/ScreenHome';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MainAppBar(appBar: AppBar(), title: "Social Chart"),
body: Container(
color: Colors.black12,
child: Obx(
() => ListView.builder(
itemCount: controller.insightCards.length,
itemBuilder: (context, index) {
return InsightCard(
navKey: navKey,
cardInfo: controller.insightCards[index].data(),// 데이터로 카드 그렷!
);
},
),
),
),
);
}
}
그럼 아래처럼 보이게 되는데 ㅎㅎㅎ 못났네 ㅋㅋ
여기에 이제 linkPreview도 보여주고, Text 위젯도 정렬하고 ㅎㅎ 개발하는 도중이지만 이쁜게 좋잖아?👇
사실 이와중에 AnyLinkPreivew가 맘에 안들어서 새로 만들었어. 로드한 이미지 사이즈에 따라서 배치를 변경하고 싶었는데 AnyLinkPreview는 안되더라고;;;
새로 만든 LinkPreview는 CachedNetworkImage 위젯의 imagebuilder를 통해서 구현했어.👇 이렇게 하면 로드할 이미지 사이즈도 알고 image cache도 하고! 개이득!!
...
...
CachedNetworkImage(
imageUrl: imageUrl,
width: 50,
imageBuilder: (context, imageProvider) {
Completer<ui.Image> completer = Completer<ui.Image>();
imageProvider
.resolve(const ImageConfiguration())
.addListener(ImageStreamListener((ImageInfo info, bool _) {
completer.complete(info.image);
}));
return FutureBuilder<ui.Image>(
future: completer.future,
builder: (context, snapshot) {
if (snapshot.hasData) {
ui.Image image = snapshot.data!;
if (image.width > 800) {
...
...
이제 좀 봐줄만 하니까 pagination을 해보자. 계속 listview를 쓰려고 했었는데 음.. 뭔가 더 좋은 옵션들이 있는 거 같더라구.👇 이런거 말이지... Flutter Favorite 딱지에다가 좋아요도 2k가 넘고 ㅎㅎ 이런 건 써야지ㅎㅎ
https://pub.dev/packages/infinite_scroll_pagination/example
컨트롤러는 아래와 같이 구성. firestore부분만 추가되었을 뿐 infinite scroll pagination에서 제공한 예제와 다를바 없어.
class ScreenHomeController extends GetxController {
PagingController<DocumentSnapshot<Object?>?,
QueryDocumentSnapshot<InsightCardModel>> pageController =
PagingController(firstPageKey: null);
final _pageSize = 10;
var userInsightCardColRef =
firestore.collection("userInsightCard").withConverter(
fromFirestore: (snapshot, options) =>
InsightCardModel.fromJson(snapshot.data()!),
toFirestore: (value, options) => value.toJson(),
);
final _insightCards = Rx<List<QueryDocumentSnapshot<InsightCardModel>>>([]);
List<QueryDocumentSnapshot<InsightCardModel>> get insightCards =>
_insightCards.value;
void fetchInsightCard(DocumentSnapshot<Object?>? pageKey) async {
QuerySnapshot<InsightCardModel> loadedInsightCard;
if (pageKey != null) {
loadedInsightCard = await userInsightCardColRef
.orderBy("createdAt", descending: true)
.startAfterDocument(pageKey)
.limit(_pageSize)
.get();
} else {
loadedInsightCard = await userInsightCardColRef
.orderBy("createdAt", descending: true)
.limit(_pageSize)
.get();
}
final isLastPage = loadedInsightCard.docs.length < _pageSize;
if (isLastPage) {
pageController.appendLastPage(loadedInsightCard.docs);
} else {
final nextPageKey = loadedInsightCard.docs.last;
pageController.appendPage(loadedInsightCard.docs, nextPageKey);
}
}
@override
void onInit() async {
// TODO: implement onInit
super.onInit();
pageController.addPageRequestListener((pageKey) {
fetchInsightCard(pageKey);
});
}
그리고 View에서는 👇👇 아래와 같이 PagedListView를 사용했지. 마찬가지로 infinite scroll pagination에서 제공한 예제와 크게 다르지 않지.
class ScreenHome extends GetView<ScreenHomeController> {
const ScreenHome({super.key, this.navKey});
final NavKeys? navKey;
static const routeName = '/ScreenHome';
@override
// TODO: implement tag
String? get tag => navKey?.name;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MainAppBar(appBar: AppBar(), title: "Social Chart"),
body: PagedListView(
pagingController: controller.pageController,
builderDelegate: PagedChildBuilderDelegate<
QueryDocumentSnapshot<InsightCardModel>>(
itemBuilder: ((context, item, index) {
return InsightCard(navKey: navKey, cardInfo: item.data());
}))),
);
}
}
테스트를 해보면 👇👇 잘 동작해! 넘나 스무스하게 잘 동작하는 군!
infinite_scroll_pagination에는 이거 말고도 기능이 엄청 많은 거 같은데 미리 다 공부하고 시작할 수는 없으니 더 자세하게 기능을 구현해가면서 공부해봐야지 ㅎㅎㅎ 우선 이렇게 무한 스크롤을 하나의 위젯으로 정리해두고 여기 저기에 사용하면 될 것 같아. 휴~ 직장을 다니던 사업을 하던 월요일은 힘드네 ㅎㅎ! 다들 화이팅!!
'Flutter > Flutter Project' 카테고리의 다른 글
[소셜차트] 앱 제작기 #11. 운수 좋은 날.. (1) | 2022.11.09 |
---|---|
[소셜차트] 앱 제작기 #10. Tap to scroll top (0) | 2022.11.08 |
[소셜차트] 앱 제작기 #8. 글쓰는 페이지 (0) | 2022.11.05 |
[소셜차트] 앱 제작기 #6. Profile & Notice Screen Layout (1) | 2022.10.26 |
[소셜차트] 앱 제작기 #5. Model and Firestore 1% (0) | 2022.10.24 |