Flutter

[Flutter] GridView, CustomScrollView 프로필 페이지 만들기

hminor 2023. 8. 14. 16:09
반응형

GridView, CustomScrollView 프로필 페이지 만들기

    • GridView
      • 그리드를 구현하고 싶을 때 사용하면 편리한 위젯으로
    • 몇 개를 보일지 확실하지 않은 상태라면 GridView.builder() 위젯을 사용하기
      • gridDelegate: 가로로 몇 개가 보일지를 체크
      • itemBuilder: return할 위젯
      • itemCount: 총 몇 개의 요소를 보일지
GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), 
  itemBuilder: (c,i){return Container(color: Colors.grey);},
  itemCount: 5,
)

  • 다만 GridView에서 return 한 요소들만 스크롤이 되기에
  • 상단 유저 프로필은 그대로 상단에 있고 아래 그리드 요소만 스크롤이 되기에
  • 인스타그램처럼 구현을 할 수 가 없다.
  • CustomScrollView
    • 이럴 때 CustomScrollView를 사용하는데
    • CustomScrollView에선 children이 slivers 가 되어
      • 배열 안에 보여줄 요소들을 넣어주면 되는데
      • 기존에 사용하는 위젯을 넣을 수는 없고
        • sliver위젯 과 같은 형식으로 넣을 수 있다.
      • Grid를 넣고자 한다면
        • SliverGrid()
      • ListView를 넣고자 한다면
        • SliverList()
      • 일반적인 위젯을 넣고 싶다면
        • SliverToBoxAdapter()
      • 헤더 영역은
        • SliverAppBar()

 

숙제

사진가져오기 버튼을 클릭하면 사진을 격자로 보여도록 하기

  • 아래처럼 작성하니 CustomScrollView로 인해 스크롤 하면 상단AppBar와 그리드 구간이 함께 스크롤되며 내려가게 된다.
class Store1 extends ChangeNotifier {
  var follow = 0;
  var check = false;
  isClick() async{
    if (check == false) {
      follow++;
      check = true;
    } else {
      follow--;
      check = false;
    }
    notifyListeners();
  }
}

class Store2 extends ChangeNotifier{
  var getImage = [];
  getData() async{
    var result = await http.get(Uri.parse('경로'));
    getImage = await jsonDecode(result.body);
    print(getImage);
    notifyListeners();
  }
}

// Profile
class Profile extends StatelessWidget {
  const Profile({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Instagram'),
        ),
      body: CustomScrollView(
        slivers: [
          SliverToBoxAdapter(
            child: ProfileHeader(),
          ),
          SliverGrid(
            delegate: SliverChildBuilderDelegate(
              (c,i)=> Image.network(context.watch<Store2>().getImage[i]),
              childCount: context.watch<Store2>().getImage.length
            ),
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 1),
          )
        ],
      )
    );
  }
}

class ProfileHeader extends StatelessWidget {
  const ProfileHeader({super.key});

  @override
  Widget build(BuildContext context) {
    return Row (
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        CircleAvatar(
          radius: 30,
          backgroundColor: Colors.grey,
        ),
        Text("팔로워 ${context.watch<Store1>().follow}"),
        ElevatedButton(onPressed: (){
          context.read<Store1>().isClick();
        }, child: Text(context.watch<Store1>().check == false?'팔로우':'팔로워')),
        ElevatedButton(onPressed: ()async{
          await context.read<Store2>().getData();
        }, child: Text('사진가져오기')),
      ],
    );
  }
}