스마트시대

INBOX 10.0 ListTile 10.1 RichText 10.2 Dismissible 10.3 onDismissed 10.4 RotationTransition 10.5 SlideTransition 10.6 AnimatedModalBarrier 10.7 Recap 본문

Programing/Flutter

INBOX 10.0 ListTile 10.1 RichText 10.2 Dismissible 10.3 onDismissed 10.4 RotationTransition 10.5 SlideTransition 10.6 AnimatedModalBarrier 10.7 Recap

스마트시대 2023. 5. 19. 19:04
728x90

10.0 ListTile

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:tiktok_clone/constants/sizes.dart';

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

  //method
  void _onPressed() {}

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 1,
        title: const Text("Inbox"),
        actions: [
          IconButton(
            onPressed: _onPressed,
            icon: const FaIcon(
              FontAwesomeIcons.paperPlane,
            ),
          ),
        ],
      ),
      body: ListView(
        children: [
          // inbox 안쪽의 타이틀 역할
          const ListTile(
            title: Text(
              "Activity",
              style: TextStyle(
                fontWeight: FontWeight.w600,
                fontSize: Sizes.size16,
              ),
            ),
            // 뒤에 오는 아이콘
            trailing: FaIcon(
              FontAwesomeIcons.chevronRight,
              size: Sizes.size14,
              color: Colors.black,
            ),
          ),
          //Activity와 New followers 나누는 경계
          Container(
            height: Sizes.size1,
            color: Colors.grey.shade200,
          ),
          ListTile(
            // 앞에 오는 아이콘
            leading: Container(
              width: Sizes.size48,
              decoration: const BoxDecoration(
                shape: BoxShape.circle,
                color: Colors.blue,
              ),
              child: const Center(
                child: FaIcon(
                  FontAwesomeIcons.users,
                  color: Colors.white,
                ),
              ),
            ),
            title: const Text(
              "New followers",
              style: TextStyle(
                fontWeight: FontWeight.w600,
                fontSize: Sizes.size16,
              ),
            ),
            subtitle: const Text(
              "Messages from followers will appear here",
              style: TextStyle(
                fontSize: Sizes.size14,
              ),
            ),
            trailing: const FaIcon(
              FontAwesomeIcons.chevronRight,
              size: Sizes.size14,
              color: Colors.black,
            ),
          ),
        ],
      ),
    );
  }
}

 

10.1 RichText

inbox_screen.dart

  //method
  void _onPressed() {}

------------------
//_onActivityTap 넘어가기 메소드
  void _onActivityTap(BuildContext context) {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => const ActivityScreen(),
      ),
    );
  }
------------------



      body: ListView(
        children: [
          // inbox 안쪽의 타이틀 역할
          ListTile(
          
          ------------------
            //_onActivityTap 넘어가기 메소드
            onTap: () => _onActivityTap(context),
            ------------------
            
            
            title: const Text(
              "Activity",

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:tiktok_clone/constants/gaps.dart';
import 'package:tiktok_clone/constants/sizes.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("All activity"),
      ),
      body: ListView(
        padding: const EdgeInsets.symmetric(
          horizontal: Sizes.size20,
        ),
        children: [
          Gaps.v14,
          Text(
            "New",
            style: TextStyle(
              fontSize: Sizes.size14,
              color: Colors.grey.shade500,
            ),
          ),
          Gaps.v14,
          ListTile(
            // 위에 패딩 있는 상태에서 이런 식으로 종 아이콘의 패딩 없을 수 있음
            contentPadding: EdgeInsets.zero,
            leading: Container(
              width: Sizes.size52,
              decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: Colors.white,
                  border: Border.all(
                    color: Colors.grey.shade400,
                    width: Sizes.size1,
                  )),
              child: const Center(
                child: FaIcon(
                  FontAwesomeIcons.bell,
                  color: Colors.black,
                ),
              ),
            ),
            //RichText위젯을 사용하여 한 ListTile에 있는 문장을 마음대로 커스터마이즈
            title: RichText(
              text: TextSpan(
                text: "Account updates:",
                style: const TextStyle(
                  fontWeight: FontWeight.w600,
                  color: Colors.black,
                  fontSize: Sizes.size16,
                ),
                children: [
                  const TextSpan(
                    text: "Upload longer videos",
                    style: TextStyle(
                      fontWeight: FontWeight.normal,
                    ),
                  ),
                  TextSpan(
                    text: "1h",
                    style: TextStyle(
                      fontWeight: FontWeight.normal,
                      color: Colors.grey.shade500,
                    ),
                  ),
                ],
              ),
            ),
            trailing: const FaIcon(
              FontAwesomeIcons.chevronRight,
              size: Sizes.size16,
            ),
          ),
        ],
      ),
    );
  }
}

 

10.2 Dismissible

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("All activity"),
      ),
      body: ListView(
        children: [
          Gaps.v14,
          Padding(
          
          
                      -----------------
            padding: const EdgeInsets.symmetric(
              horizontal: Sizes.size12,
                          -----------------
                          
                          
            ),
            child: Text(
              "New",
              style: TextStyle(
                fontSize: Sizes.size14,
                color: Colors.grey.shade500,
              ),
            ),
          ),
          Gaps.v14,
          
                      -----------------
          //ListTile위젯을 옆으로 밀어내는 dismiss동작 구현 위젯
          Dismissible(
            key: const Key("x"),
            background: Container(
              // container 안에 있는 아이템들을 정렬해줌
              alignment: Alignment.centerLeft,
              color: Colors.green,
              child: const Padding(
                padding: EdgeInsets.only(
                  left: Sizes.size10,
                ),
                child: FaIcon(
                  FontAwesomeIcons.checkDouble,
                  color: Colors.white,
                  size: Sizes.size32,
                ),
              ),
            ),
            secondaryBackground: Container(
              // container 안에 있는 아이템들을 정렬해줌
              alignment: Alignment.centerRight,
              color: Colors.red,
              child: const Padding(
                padding: EdgeInsets.only(
                  right: Sizes.size10,
                ),
                child: FaIcon(
                  FontAwesomeIcons.trashCan,
                  color: Colors.white,
                  size: Sizes.size32,
                              -----------------
                ),
              ),
            ),
            child: ListTile(
            
            -----------------
              // 위에 패딩 있는 상태에서 이런 식으로 종 아이콘의 패딩 없을 수 있음
              // contentPadding: EdgeInsets.zero,
                          -----------------
              leading: Container(
                width: Sizes.size52,

 

10.3 onDismissed

10.2에서 생성한 위젯을 dismiss했다고 build메소드 안에서 지워지지는 않으니까 이 list 기반으로 rebuild하도록 state를 설정 후 dismiss된 위젯은 위젯트리에서 완전히 지워버리는 걸 구현해야 에러가 생기지 않는다

-------------------
class ActivityScreen extends StatefulWidget {
  const ActivityScreen({super.key});
-------------------
  @override
  State<ActivityScreen> createState() => _ActivityScreenState();
}



-------------------
//위젯을 dismiss했다고 build메소드 안에서 지워지지는 않으니까
//이 list 기반으로 rebuild하도록 state를 설정 후 dismiss된 위젯은 위젯트리에서 완전히 지워버리는 클래스
class _ActivityScreenState extends State<ActivityScreen> {
  final List<String> _notifications = List.generate(20, (index) => "${index}h");

  //위젯트리에서 완전히 지워버리는 메소드
  void _onDismissed(String notification) {
    _notifications.remove(notification);
    setState(() {});
  }
-------------------




  @override
  Widget build(BuildContext context) {
  
  -------------------
    print(_notifications);
    -------------------
    
    
    return Scaffold(
      appBar: AppBar(
        title: const Text("All activity"),
      ),
      
      
      
      
                     color: Colors.grey.shade500,
              ),
            ),
          ),
          Gaps.v14,
          
          
          
          -----------
          //위젯을 dismiss했다고 build메소드 안에서 지워지지는 않으니까
          //이 list 기반으로 rebuild하도록 state를 설정 후 dismiss된 위젯은 위젯트리에서 완전히 지워버리는 for구문
          for (var notification in _notifications)
          -----------
          
          
          
            //ListTile위젯을 옆으로 밀어내는 dismiss동작 구현 위젯
            Dismissible(
              key: Key(notification),
              
              
                        -----------
              //1h,2h..별로 방향이 어쨋든 위젯트리에서 완전히 지워버리는 메소드
              onDismissed: (direction) => _onDismissed(notification),
                        -----------
                        
                        
                        
                        
              background: Container(
                // container 안에 있는 아이템들을 정렬해줌
                alignment: Alignment.centerLeft,
                color: Colors.green,
                child: const Padding(
                
                
                
                           child: ListTile(
                           -----------------
                // 위젯 간의 간격 띄우기
                minVerticalPadding: Sizes.size16,
-----------------


                // 위에 패딩 있는 상태에서 이런 식으로 종 아이콘의 패딩 없을 수 있음
                // contentPadding: EdgeInsets.zero,
                leading: Container(

 

10.4 RotationTransition

class _ActivityScreenState extends State<ActivityScreen>

-------------------
    with SingleTickerProviderStateMixin {
    -------------------
    
  //위젯을 dismiss했다고 build메소드 안에서 지워지지는 않으니까
//이 list 기반으로 rebuild하도록 state를 설정 후 dismiss된 위젯은 위젯트리에서 완전히 지워버리는 클래스
  final List<String> _notifications = List.generate(20, (index) => "${index}h");
  
  -------------------
    //initState(animation builder,event listener,setstate등) 없이도 이런식으로 구현 할 수 있다. 이떄는 무조건 late써야함
  late final AnimationController _animationController = AnimationController(
    vsync: this,
    duration: const Duration(milliseconds: 200),
  );

//initState(animation builder,event listener,setstat 등) 없이도 이런식으로 구현 할 수 있다. 이떄는 무조건 late써야함
  late final Animation<double> _animation =
      //화살표 180도로 돌려주는 거
      Tween(begin: 0.0, end: 0.5).animate(_animationController);
        -------------------
        
        
         @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      
      
      -------------------
        title: GestureDetector(
          onTap: _onTitleTap,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text("All activity"),
              Gaps.h2,
              RotationTransition(
                turns: _animation,
                child: const FaIcon(
                  FontAwesomeIcons.chevronDown,
                  size: Sizes.size14,
           -------------------
           
           
                ),
              )
            ],
          ),
        ),
      ),
      body: ListView(

 

10.5 SlideTransition

  final List<String> _notifications = List.generate(20, (index) => "${index}h");


-----------------
  //All activity아이콘 리스트화
  final List<Map<String, dynamic>> _tabs = [
    {
      "title": "All activity",
      "icon": FontAwesomeIcons.solidMessage,
    },
    {
      "title": "Likes",
      "icon": FontAwesomeIcons.solidHeart,
    },
    {
      "title": "Comments",
      "icon": FontAwesomeIcons.solidComments,
    },
    {
      "title": "Mentions",
      "icon": FontAwesomeIcons.at,
    },
    {
      "title": "Followers",
      "icon": FontAwesomeIcons.solidUser,
    },
    {
      "title": "From TikTok",
      "icon": FontAwesomeIcons.tiktok,
    }
  ];
  -----------------
  
  
        Tween(begin: 0.0, end: 0.5).animate(_animationController);


  -----------------
//아이콘 리스트 감추기 함수
  late final Animation<Offset> _panelAnimation = Tween(
    // 수직축으로 50% 위로 올리도록 함(비율,픽셀X)
    begin: const Offset(0, -1),
    end: Offset.zero,
  ).animate(_animationController);
  -----------------
  
  
  //위젯트리에서 완전히 지워버리는 메소드
  
  
  
  
  
                      trailing: const FaIcon(
                      FontAwesomeIcons.chevronRight,
                      size: Sizes.size16,
                    ),
                  ),
                ),
            ],
          ),
          
            -----------------
          SlideTransition(
            position: _panelAnimation,
            child: Container(
              decoration: const BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.only(
                  bottomLeft: Radius.circular(
                    Sizes.size5,
                  ),
                  bottomRight: Radius.circular(
                    Sizes.size5,
                  ),
                ),
              ),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  for (var tab in _tabs)
                    ListTile(
                      title: Row(
                        children: [
                          FaIcon(
                            tab["icon"],
                            color: Colors.black,
                            size: Sizes.size16,
                          ),
                          Gaps.h20,
                          Text(
                            tab["title"],
                            style: const TextStyle(
                              fontWeight: FontWeight.bold,
                                -----------------
                                
                            ),
                          ),
                        ],
                      ),
                    ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

 

10.6 AnimatedModalBarrier


---------------
//위젯 트리에서 barrier를 보여주고 숨기는 역할을 하는 flag
  bool _showBarrier = false;
---------------


  //initState(animation builder,event listener,setstate등) 없이도 이런식으로 구현 할 수 있다. 이떄는 무조건 late써야함
  late final AnimationController _animationController = AnimationController(
  
  
  
    ).animate(_animationController);
    
    
    
---------------
  //overlay(패널 뒤에 숨어서 어두워지기,모든이벤트 비활성화)
  late final Animation<Color?> _barrierAnimation = ColorTween(
    begin: Colors.transparent,
    end: Colors.black38,
  ).animate(_animationController);
---------------



  //위젯트리에서 완전히 지워버리는 메소드
  void _onDismissed(String notification) {
  
  
  
  
  ---------------
  //barrier 동작을 원할하게 하기 위해 future구문 써야 함
  void _toggleAnimations() async {
    if (_animationController.isCompleted) {
      await _animationController.reverse();
    } else {
      _animationController.forward();
    }
    //위젯 트리에서 barrier를 보여주고 숨기는 역할을 하는 flag
    setState(() {
      _showBarrier = !_showBarrier;
    });
  }
---------------


trailing: const FaIcon(
                      FontAwesomeIcons.chevronRight,
                      size: Sizes.size16,
                    ),
                  ),
                ),
            ],
          ),


---------------
          //위젯 트리에서 barrier를 보여주고 숨기는 역할을 하는 flag
          if (_showBarrier)
            //overlay(패널 뒤에 숨어서 어두워지기,모든이벤트 비활성화), 위치는 SlideTransition앞에 와야 함
            AnimatedModalBarrier(
              color: _barrierAnimation,
              //이 설정으로 베리어 쪽 눌러도 아이콘 리스트(modal)가 최소화 됨
              dismissible: true,
              onDismiss: _toggleAnimations,
              ---------------
              
              
            ),
          SlideTransition(
            position: _panelAnimation,
  @override
  Widget build(BuildContext context) {

 

 

728x90
반응형
Comments