코딩하는 제리

[Flutter/Project](Instagram Clone) Table, TableRow 본문

Flutter/Project_InstaClone(완)

[Flutter/Project](Instagram Clone) Table, TableRow

JerryCho 2021. 1. 22. 13:11



소스코드

// profile_body.dart

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_project_IJ/constants/common_size.dart';
import 'package:flutter_project_IJ/constants/screen_size.dart';
import 'package:flutter_project_IJ/widgets/rounded_avatar.dart';

// 가독성을 위해서 사용.
enum SelectedTab { left, right }

class ProfileBody extends StatefulWidget {
  @override
  _ProfileBodyState createState() => _ProfileBodyState();
}

class _ProfileBodyState extends State<ProfileBody> {
  // bool selectedLeft = true;
  SelectedTab _selectedTab = SelectedTab.left;

  double _leftImagesPageMargin = 0;
  double _rightImagesPageMargin = size.width;

  @override
  Widget build(BuildContext context) {
    return Expanded(
      // Expanded()로 CustomScrollView()가 빈공간을 차지하도록 해야 표시됨.
      child: CustomScrollView(
        // CustomScrollView() 스크롤 가능한 뷰들을 섞어서 사용할 때.
        slivers: <Widget>[
          SliverList(
            delegate: SliverChildListDelegate([
              Row(
                children: [
                  Padding(
                    padding: const EdgeInsets.all(common_gap),
                    child: RoundedAvatar(
                      size: 80,
                    ),
                  ),
                  Expanded(
                    child: Padding(
                      padding: const EdgeInsets.only(right: common_gap),
                      child: Table(
                        children: [
                          TableRow(children: [
                            _valueText('123'),
                            _valueText('456'),
                            _valueText('789'),
                          ]),
                          TableRow(children: [
                            _labelText('Post'),
                            _labelText('Followers'),
                            _labelText('Following'),
                          ])
                        ],
                      ),
                    ),
                  ),
                ],
              ),
              _username(),
              _userBio(),
              _editProfileBtn(),
              _tabButtons(),
              _selectedIndicator(),
            ]),
          ),
          _imagesPager(),
        ],
      ),
    );
  }

  Text _valueText(String value) => Text(
        value,
        style: TextStyle(fontWeight: FontWeight.bold),
        textAlign: TextAlign.center,
      );

  Text _labelText(String label) => Text(
        label,
        style: TextStyle(fontWeight: FontWeight.w300, fontSize: 12),
        textAlign: TextAlign.center,
      );

  SliverToBoxAdapter _imagesPager() {
    return SliverToBoxAdapter(
      // SliverToBoxAdapter() 일반적인 뷰를 Sliver 뷰로 변환.
      child: Stack(
        children: <Widget>[
          AnimatedContainer(
            // 애니메이션 길이 0.3초
            duration: Duration(milliseconds: 300),
            //transform: Matrix4.translationValues(x, y, z),
            transform: Matrix4.translationValues(_leftImagesPageMargin, 0, 0),
            curve: Curves.fastOutSlowIn,
            child: _images(),
          ),
          AnimatedContainer(
            // 애니메이션 길이 0.3초
            duration: Duration(milliseconds: 300),
            //transform: Matrix4.translationValues(x, y, z),
            transform: Matrix4.translationValues(_rightImagesPageMargin, 0, 0),
            curve: Curves.fastOutSlowIn,
            child: _images(),
          ),
        ],
      ),
    );
  }

  GridView _images() {
    return GridView.count(
      crossAxisCount: 3,
      physics: NeverScrollableScrollPhysics() /* GridView의 스크롤을 사용하지 않음 */,
      shrinkWrap: true /* 데이터의 양 만큼만 공간을 차지하게함 */,
      childAspectRatio: 1 /* 이미지 비율 */,
      children: List.generate(
        // List.generate() 리스트 생성
        30 /* 30개의 아이템 */,
        (index) => CachedNetworkImage(
          fit: BoxFit.cover,
          imageUrl: "https://picsum.photos/id/$index/100/100",
        ),
      ),
    );
  }

  Widget _selectedIndicator() {
    return AnimatedContainer(
      duration: Duration(milliseconds: 300),
      alignment: _selectedTab == SelectedTab.left
          ? Alignment.centerLeft
          : Alignment.centerRight,
      curve: Curves.fastOutSlowIn,
      child: Container(
        height: 5,
        width: size.width / 2,
        color: Colors.black87,
      ),
    );
  }

  Row _tabButtons() {
    return Row(
      children: [
        Expanded(
          child: IconButton(
            color: _selectedTab == SelectedTab.left
                ? Colors.black
                : Colors.black38,
            icon: ImageIcon(AssetImage('assets/images/grid.png')),
            onPressed: () {
              setState(() {
                // StatefulWidget의 상태변화 적용.
                _tabSelected(SelectedTab.left);
              });
            },
          ),
        ),
        Expanded(
          child: IconButton(
            color: _selectedTab == SelectedTab.left
                ? Colors.black38
                : Colors.black,
            icon: ImageIcon(AssetImage('assets/images/saved.png')),
            onPressed: () {
              setState(() {
                // StatefulWidget의 상태변화 적용.
                _tabSelected(SelectedTab.right);
              });
            },
          ),
        ),
      ],
    );
  }

  _tabSelected(SelectedTab selectedTab) {
    switch (selectedTab) {
      case SelectedTab.left:
        _selectedTab = SelectedTab.left;
        _leftImagesPageMargin = 0;
        _rightImagesPageMargin = size.width;
        break;
      case SelectedTab.right:
        _selectedTab = SelectedTab.right;
        _leftImagesPageMargin = -size.width;
        _rightImagesPageMargin = 0;
        break;
    }
  }

  Widget _editProfileBtn() {
    return Padding(
      padding: const EdgeInsets.symmetric(
        horizontal: common_gap,
        vertical: common_xxs_gap,
      ),
      child: SizedBox(
        height: 24,
        child: OutlineButton(
          onPressed: () {},
          borderSide: BorderSide(color: Colors.black45),
          shape: RoundedRectangleBorder(
            // RoundedRectangleBorder() 둥근 모서리 직사각형.
            borderRadius: BorderRadius.circular(6),
          ),
          child: Text(
            'Edit Profile',
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
        ),
      ),
    );
  }

  Widget _username() {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: common_gap),
      child: Text(
        'username',
        style: TextStyle(fontWeight: FontWeight.bold),
      ),
    );
  }

  Widget _userBio() {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: common_gap),
      child: Text(
        'username',
        style: TextStyle(fontWeight: FontWeight.w400),
      ),
    );
  }
}
Comments