여러개의 목록을 n개의 목록으로 쪼개 슬라이드 하면 다음 장으로 넘어가는 컨테이너를 만들어보도록 하겠습니다.
final PageController _pageController = PageController();
int _currentPageIndex = 0;
먼저 페이지 컨트롤러와 현재 페이지를 알 수 있는 변수가 필요합니다.
@override
void initState() {
super.initState();
_pageController.addListener(() {
setState(() {
_currentPageIndex = _pageController.page!.round();
});
});
}
초기화 해주세요
Widget _buildPageIndicator() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(5, (index) {
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: index == _currentPageIndex ? Colors.black : Colors.white,
),
);
}),
);
}
전체 페이지 수와 현재 페이지를 알려주는 인디케이터입니다.
이렇게 생겼습니다
PageView.builder(
controller: _pageController,
itemCount: 5,
itemBuilder: (context, pageIndex) {
return ListView.builder(
itemCount: 5,
itemBuilder: (context, itemIndex) {
final index = pageIndex * 5 + itemIndex;
if (index <10) {
return GestureDetector(
onTap: () {},
child: Container(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.fromLTRB(15, 10, 3, 0),
child:
Text(
'제목',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
SizedBox(height: 4),
Container(
padding: EdgeInsets.symmetric(
horizontal: 10),
child: Divider(
color: Colors.grey,
height: 1,
),
),
Container(
width: double.infinity,
height: 37.5,
padding: EdgeInsets.fromLTRB(
17, 5, 10, 0),
child: Text(
'내용',
style: TextStyle(fontSize: 13),
overflow: TextOverflow.ellipsis,
),
),
Container(
padding: EdgeInsets.symmetric(
horizontal: 8),
child: Divider(
color: Colors.white,
height: 2,
),
),
],
),
),
);
} else {
return SizedBox(); // 아이템이 부족한 경우 빈 SizedBox 반환
}
},
);
},
),
GestureDetector는 사용자 동작을 감지하는 위젯입니다.
저는 itemCount를 5로 하여 한페이지에 5개씩 보이도록 해주었습니다.
제목과 내용 부분은 divider을 이용하여 ui를 만들어주었습니다.
![]() | ![]() |
---|
최종ui입니다. 안에 내용은 통신하시거나 배열 인덱스 값으로 구분해주시면 다른 제목과 내용이 들어갈 것입니다.
import 'package:flutter/material.dart';
void main() async {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(),
home: myApp(),
);
}
}
class myApp extends StatefulWidget {
@override
State<myApp> createState() => _myAppState();
}
class _myAppState extends State<myApp> {
final PageController _pageController = PageController();
int _currentPageIndex = 0;
@override
void initState() {
super.initState();
_pageController.addListener(() {
setState(() {
_currentPageIndex = _pageController.page!.round();
});
});
}
Widget _buildPageIndicator() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(5, (index) {
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: index == _currentPageIndex ? Colors.black : Colors.white,
),
);
}),
);
}
@override
Widget build(BuildContext context) {
final sizeX = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: Text("MyApp"),
),
body: Container(
width: sizeX * 0.8,
height: 450,
padding: const EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 20,
),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Color(0xFFE8E8E8),
borderRadius: BorderRadius.circular(7),
boxShadow: [
BoxShadow(
color: Colors.black12,
spreadRadius: 2,
offset: Offset(3, 3),
),
],
),
child: PageView.builder(
controller: _pageController,
itemCount: 5,
itemBuilder: (context, pageIndex) {
return ListView.builder(
itemCount: 5,
itemBuilder: (context, itemIndex) {
final index = pageIndex * 5 + itemIndex;
if (index <10) {
return GestureDetector(
onTap: () {},
child: Container(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.fromLTRB(15, 10, 3, 0),
child:
Text(
'제목',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
SizedBox(height: 4),
Container(
padding: EdgeInsets.symmetric(
horizontal: 10),
child: Divider(
color: Colors.grey,
height: 1,
),
),
Container(
width: double.infinity,
height: 37.5,
padding: EdgeInsets.fromLTRB(
17, 5, 10, 0),
child: Text(
'내용',
style: TextStyle(fontSize: 13),
overflow: TextOverflow.ellipsis,
),
),
Container(
padding: EdgeInsets.symmetric(
horizontal: 8),
child: Divider(
color: Colors.white,
height: 2,
),
),
],
),
),
);
} else {
return SizedBox(); // 아이템이 부족한 경우 빈 SizedBox 반환
}
},
);
},
),
),
),
SizedBox(
height: 10,
),
_buildPageIndicator(),
],
),
),
);
}
}