스마트시대

COMMENTS SECTION 8.0 showModalBottomSheet 8.1 Comments 8.2 Add Comment 8.3 Text Input Actions 8.4 Conclusions 본문

Programing/Flutter

COMMENTS SECTION 8.0 showModalBottomSheet 8.1 Comments 8.2 Add Comment 8.3 Text Input Actions 8.4 Conclusions

스마트시대 2023. 5. 16. 16:22
728x90

8.0 showModalBottomSheet 

새로 고침하면 영상이 자동재생되어 버린다.

그래서 밑부분의     !_isPaused &&(일시정지상태가 아니다)를 추가해준다.

// 비디오가 보여지는 영역을 계산하고 한쪽에서만 영상 재생되도록 해주는 파라메터
  void _onVisibilityChanged(VisibilityInfo info) {
    if (info.visibleFraction == 1 && 
    !_isPaused &&
    !_videoPlayerController.value.isPlaying) {
      _videoPlayerController.play();
    }
  }
      _isPaused = !_isPaused;
    });
  }
  
-------------
  //댓글버튼 눌렀을 때 댓글창 뜨는 함수
  void _onCommentsTap(BuildContext context) {
    showModalBottomSheet(
      context: context,
      builder: (context) => Container(),
    );
  }
-------------

  @override
  Widget build(BuildContext context) {
  
  
  
  
                  Gaps.v24,
                  
                  -------------
                GestureDetector(
                  //댓글버튼 눌렀을 때 댓글창 뜨는 메소드
                  onTap: () => _onCommentsTap(context),
---------------------------------------

                  child: const VideoButton(
                    icon: FontAwesomeIcons.solidComment,
                    text: "33K",

 

  //댓글버튼 눌렀을 때 댓글창 뜨는 함수
  void _onCommentsTap(BuildContext context) async {
    if (_videoPlayerController.value.isPlaying) {
      _onTogglePause();
    }
    //이 future는 유저가 댓글 창 닫으면 resolve되니까 await씀
    await showModalBottomSheet(
      context: context,
      builder: (context) => const VideoComments(),
    );
    _onTogglePause();
  }

 

  @override
  State<VideoComments> createState() => _VideoCommentsState();
}

class _VideoCommentsState extends State<VideoComments> {
  void _onClosePressed() {
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        //AppBar에서 디폴트로 생기는 백버튼 없애기
        automaticallyImplyLeading: false,
        title: const Text("22796 comments"),
        //사용자가 창 닫을 수 있는 기능
        actions: [
          IconButton(
            onPressed: _onClosePressed,
            icon: const FaIcon(FontAwesomeIcons.xmark),
          ),
        ],
      ),
    );
  }
}

 

      _onTogglePause();
    }
    //이 future는 유저가 댓글 창 닫으면 resolve되니까 await씀
    await showModalBottomSheet(
      context: context,
      
      
      -------------
      //댓글창 띄울때 색깔을 이걸로 표현 가능
      backgroundColor: Colors.red,
            -------------
            
      builder: (context) => const VideoComments(),
    );
    _onTogglePause();
  }
  @override
  Widget build(BuildContext context) {
  
  -------------------
    return Container(
      clipBehavior: Clip.hardEdge,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(
          Sizes.size10,
        ),
      ),
     -------------------
     
      child: Scaffold(
        appBar: AppBar(

      child: Scaffold(
        backgroundColor: Colors.grey.shade50,
        appBar: AppBar(
          backgroundColor: Colors.grey.shade50,
          //AppBar에서 디폴트로 생기는 백버튼 없애기
          automaticallyImplyLeading: false,
          title: const Text("22796 comments"),
          //사용자가 창 닫을 수 있는 기능
          actions: [
            IconButton(
              onPressed: _onClosePressed,
              icon: const FaIcon(FontAwesomeIcons.xmark),
            ),
          ],
        ),
        body: ListView.builder(
          itemCount: 10,
          itemBuilder: (context, index) => Container(
            child: const Text(
              "Im a comment",
            ),
          ),
        ),
      ),
    );
  }
}

Scaffold AppBar 둘 다 희미한 회색으로

 

8.1 Comments 

댓글창 유저 아이콘 만들기

              icon: const FaIcon(FontAwesomeIcons.xmark),
            ),
          ],
        ),
        
        
        --------------
        body: ListView.separated(
          padding: const EdgeInsets.symmetric(
            vertical: Sizes.size10,
            horizontal: Sizes.size16,
          ),
          separatorBuilder: (context, index) => Gaps.v20,
          itemCount: 10,
          itemBuilder: (context, index) => Row(
            children: const [
              CircleAvatar(
                radius: 18,
                child: Text("joon"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

        body: ListView.separated(
          padding: const EdgeInsets.symmetric(
            vertical: Sizes.size10,
            horizontal: Sizes.size16,
          ),
          separatorBuilder: (context, index) => Gaps.v20,
          itemCount: 10,
          
          --------------------
          itemBuilder: (context, index) => Row(

            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const CircleAvatar(
                radius: 18,
                child: Text("joon"),
              ),
              Gaps.h10,
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      "joon",
                      style: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: Sizes.size14,
                        color: Colors.grey.shade500,
                      ),
                    ),
                    Gaps.v3,
                    const Text(
                        "That's not it l've seen the same thing but also in a cave")
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

                    const Text(
                        "That's not it l've seen the same thing but also in a cave")
                  ],
                ),
              ),
              
              -------------------------
              Gaps.h10,
              Column(
                children: [
                  FaIcon(
                    FontAwesomeIcons.heart,
                    size: Sizes.size20,
                    color: Colors.grey.shade500,
                  ),
                  Gaps.v2,
                  Text(
                    "52.2K",
                    style: TextStyle(
                      color: Colors.grey.shade500,
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
        
        
        bottomNavigationBar: BottomAppBar(
          color: Colors.white,
          child: Row(
            children: [
              CircleAvatar(
                radius: 18,
                backgroundColor: Colors.grey.shade500,
                foregroundColor: Colors.white,
                child: const Text("joon"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

8.2 Add Comment

이 코드로 입력창은 구현되는데

        bottomNavigationBar: BottomAppBar(
          color: Colors.white,
          child: Row(
            children: [
              CircleAvatar(
                radius: 18,
                backgroundColor: Colors.grey.shade500,
                foregroundColor: Colors.white,
                child: const Text("joon"),
              ),
              
              --------------
              Gaps.h10,
              const Expanded(child: TextField())
                            --------------
            ],
          ),
        ),
      ),
    );
  }
}

 

하지만 

1.입력창의 키보드등이 열리면 플러터는 디폴트로 화면을 자동 조정해줌

이거는 여기서 고치고

2.키보드에 입력창이 가려짐 

이걸 고치기 위해

BottomAppBar를 ListView.separated를 stack위젯으로 감싸고(children으로 convert하기) positioned위젯으로 옮긴다.

 

 

              icon: const FaIcon(FontAwesomeIcons.xmark),
            ),
          ],
        ),
        
        
        -------------------------
        body: Stack(
          children: [
            ListView.separated(
                    -------------------------
                    
                    
              padding: const EdgeInsets.symmetric(
                vertical: Sizes.size10,
                horizontal: Sizes.size16,
              ),
              separatorBuilder: (context, index) => Gaps.v20,
              itemCount: 10,
              itemBuilder: (context, index) => Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const CircleAvatar(
                    radius: 18,
                    child: Text("joon"),
                  ),
                  Gaps.h10,
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          "joon",
                          style: TextStyle(
                            fontWeight: FontWeight.bold,
                            fontSize: Sizes.size14,
                            color: Colors.grey.shade500,
                          ),
                        ),
                        Gaps.v3,
                        const Text(
                            "That's not it l've seen the same thing but also in a cave")
                      ],
                    ),
                  ),
                  Gaps.h10,
                  Column(
                    children: [
                      FaIcon(
                        FontAwesomeIcons.heart,
                        size: Sizes.size20,
                        color: Colors.grey.shade500,
                      ),
                      Gaps.v2,
                      Text(
                        "52.2K",
                        style: TextStyle(
                          color: Colors.grey.shade500,
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
            
                 -------------------------   
            Positioned(
                    -------------------------
              //BottomAppBar를 0으로 고정, width값도 줘야함
              bottom: 0,
              //플러터가 유저의 화면 크기를 알아와서 Positioned의 width로 자동 설정해주기
              width: MediaQuery.of(context).size.width,
                      -------------------------
              child: BottomAppBar(
                color: Colors.white,
                child: Row(
                  children: [
                    CircleAvatar(
                      radius: 18,
                      backgroundColor: Colors.grey.shade500,
                      foregroundColor: Colors.white,
                      child: const Text("joon"),
                    ),
                    Gaps.h10,
                    const Expanded(child: TextField())
                            -------------------------
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

 

댓글창의 사이즈를 커스터마이즈하기

 

            Positioned(
              //BottomAppBar를 0으로 고정, width값도 줘야함
              bottom: 0,
              //플러터가 유저의 화면 크기를 알아와서 Positioned의 width로 자동 설정해주기
              width: size.width,
              child: BottomAppBar(
                color: Colors.white,




--------------------
                // comment창 위치 조정
                child: Padding(
                  padding: const EdgeInsets.only(
                    left: Sizes.size16,
                    right: Sizes.size16,
                    bottom: Sizes.size10,
                    top: Sizes.size8,
                  ),
                  --------------------
                  
                  
                  child: Row(
                    children: [
                      CircleAvatar(
                        radius: 18,
                        backgroundColor: Colors.grey.shade500,
                        foregroundColor: Colors.white,
                        child: const Text("joon"),
                      ),
                      Gaps.h10,
                      
                      
                      --------------------
                      // comment창 UI꾸미기
                      Expanded(
                        child: TextField(
                          cursorColor: Theme.of(context).primaryColor,
                          decoration: InputDecoration(
                            hintText: "Write a comment...",
                            border: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(
                                  Sizes.size12,
                                ),
                                borderSide: BorderSide.none),
                            filled: true,
                            fillColor: Colors.grey.shade200,
                            contentPadding: const EdgeInsets.symmetric(
                              vertical: Sizes.size12,
                              horizontal: Sizes.size10,
                              --------------------
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

 

8.3 Text Input Actions

                color: Colors.white,

                // comment창 위치 조정
                child: Padding(
                
                ------------------------
                  //여기서의 사이즈 크기는 큰 단위로만 조정 가능
                  padding: const EdgeInsets.symmetric(
                    vertical: Sizes.size10,
                    horizontal: Sizes.size16,
   ------------------------
                  ),
                  child: Row(
                    children: [
                      CircleAvatar(
                        radius: 18,
                        backgroundColor: Colors.grey.shade500,
                        foregroundColor: Colors.white,
                        child: const Text("joon"),
                      ),
                      Gaps.h10,
                      // comment창 UI꾸미기
                      Expanded(
                      
                      
                                      ------------------------
                        //여기서의 사이즈 크기는 작은 단위로도 조정 가능
                        child: SizedBox(
                          height: Sizes.size44,
                                          ------------------------
                                          
                                          
                          child: TextField(
                          
                                          ------------------------
                            //done을 return으로 바꿔주기 위한 설정
                            expands: true,
                            minLines: null,
                            maxLines: null,
                                            ------------------------
                                            
                                            
                            
                            textInputAction: TextInputAction.newline,
                            cursorColor: Theme.of(context).primaryColor,
                            decoration: InputDecoration(
                              hintText: "Write a comment...",
                              border: OutlineInputBorder(
                                  borderRadius: BorderRadius.circular(
                                    Sizes.size12,
                                  ),
                                  borderSide: BorderSide.none),
                              filled: true,
                              fillColor: Colors.grey.shade200,
                              
                                              ------------------------
                              contentPadding: const EdgeInsets.symmetric(
                                //done을 return으로 바꿔주기 위한 설정하기 위해 vertical 빼주기
                                // vertical: Sizes.size12,
                                                ------------------------
                                                
                                                
                                horizontal: Sizes.size10,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

 

 

//사용자가 창 닫을 수 있는 기능
class _VideoCommentsState extends State<VideoComments> {
  void _onClosePressed() {
    Navigator.of(context).pop();
  }


-----------------
  //댓글창 누르면 키보드 사라지게 하는 함수
  void _onBodyTap() {
    FocusScope.of(context).unfocus();
  }
-----------------


              icon: const FaIcon(FontAwesomeIcons.xmark),
            ),
          ],
        ),
        
        
        
        ------------------
        body: GestureDetector(
          //댓글창 누르면 키보드 사라지게 하는 파라메터
          onTap: _onBodyTap,
                  ------------------
                  
                  
          child: Stack(
            children: [
              ListView.separated(
                padding: const EdgeInsets.symmetric(

 

 

//사용자가 창 닫을 수 있는 기능
class _VideoCommentsState extends State<VideoComments> {

------------------
  //유저가 커멘트 적을 때 확인할 flag용
  bool _isWriting = false;
------------------
  void _onClosePressed() {
    Navigator.of(context).pop();
  }





  //댓글창 누르면 키보드 사라지게 하는 함수
  void _stopWriting() {
    FocusScope.of(context).unfocus();


------------------
    //유저가 커멘트 적을 때 확인할 flag용
    setState(() {
      _isWriting = false;
    });
  }

  //유저가 커멘트 적을 때 확인할 flag용
  void _onStartWriting() {
    setState(() {
      _isWriting = true;
    });
  }
------------------

fillColor: Colors.grey.shade200,
                                contentPadding: const EdgeInsets.symmetric(
                                  //done을 return으로 바꿔주기 위한 설정하기 위해 vertical 빼주기
                                  // vertical: Sizes.size12,
                                  horizontal: Sizes.size12,
                                ),
                                
                                
                                
                                                        Gaps.h10,
                        // comment창 UI꾸미기
                        Expanded(
                          //여기서의 사이즈 크기는 작은 단위로도 조정 가능
                          child: SizedBox(
                            height: Sizes.size44,
                            child: TextField(
                            
                            
                            
                           ------------------ 
                              //유저가 커멘트 적을 때 확인할 flag용
                              onTap: _onStartWriting,
                              ------------------
                              
                              
                              //done을 return으로 바꿔주기 위한 설정
                              expands: true,
                              minLines: null,
                              maxLines: null,
                                
                                ----------------------
                                // 댓글 쓰는 곳에 아이콘 넣기
                                suffixIcon: Padding(
                                  padding: const EdgeInsets.only(
                                    right: Sizes.size14,
                                  ),
                                  child: Row(
                                    // row는 최대 공간 차지하니까 min
                                    mainAxisSize: MainAxisSize.min,
                                    children: [
                                      FaIcon(
                                        FontAwesomeIcons.at,
                                        color: Colors.grey.shade900,
                                      ),
                                      Gaps.h14,
                                      FaIcon(
                                        FontAwesomeIcons.gift,
                                        color: Colors.grey.shade900,
                                      ),
                                      Gaps.h14,
                                      FaIcon(
                                        FontAwesomeIcons.faceSmile,
                                        color: Colors.grey.shade900,
                                      ),
                                      Gaps.h14,
                                      if (_isWriting)
                                        GestureDetector(
                                          onTap: _stopWriting,
                                          child: FaIcon(
                                            FontAwesomeIcons.circleArrowUp,
                                            color:
                                                Theme.of(context).primaryColor,
                                          ),
                                        ),
                                    ],
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

 

 

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 VideoComments extends StatefulWidget {
  const VideoComments({super.key});

  @override
  State<VideoComments> createState() => _VideoCommentsState();
}

//사용자가 창 닫을 수 있는 기능
class _VideoCommentsState extends State<VideoComments> {
  //유저가 커멘트 적을 때 확인할 flag용
  bool _isWriting = false;

  void _onClosePressed() {
    Navigator.of(context).pop();
  }

  //댓글창 누르면 키보드 사라지게 하는 함수
  void _stopWriting() {
    FocusScope.of(context).unfocus();

    //유저가 커멘트 적을 때 확인할 flag용
    setState(() {
      _isWriting = false;
    });
  }

  //유저가 커멘트 적을 때 확인할 flag용
  void _onStartWriting() {
    setState(() {
      _isWriting = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    //플러터가 유저의 화면 크기를 알아와서 Positioned의 width로 자동 설정해주기 parameter
    final size = MediaQuery.of(context).size;

    return Container(
      //댓글창의 사이즈를 커스터마이즈하기 위한 설정
      height: size.height * 0.8,

      clipBehavior: Clip.hardEdge,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(
          Sizes.size10,
        ),
      ),
      child: Scaffold(
        backgroundColor: Colors.grey.shade50,
        appBar: AppBar(
          backgroundColor: Colors.grey.shade50,
          //AppBar에서 디폴트로 생기는 백버튼 없애기
          automaticallyImplyLeading: false,
          title: const Text("22796 comments"),
          //사용자가 창 닫을 수 있는 기능
          actions: [
            IconButton(
              onPressed: _onClosePressed,
              icon: const FaIcon(FontAwesomeIcons.xmark),
            ),
          ],
        ),
        body: GestureDetector(
          //댓글창 누르면 키보드 사라지게 하는 파라메터
          onTap: _stopWriting,
          child: Stack(
            children: [
              ListView.separated(
                padding: const EdgeInsets.symmetric(
                  vertical: Sizes.size10,
                  horizontal: Sizes.size16,
                ),
                separatorBuilder: (context, index) => Gaps.v20,
                itemCount: 10,
                itemBuilder: (context, index) => Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const CircleAvatar(
                      radius: 18,
                      child: Text("joon"),
                    ),
                    Gaps.h10,
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            "joon",
                            style: TextStyle(
                              fontWeight: FontWeight.bold,
                              fontSize: Sizes.size14,
                              color: Colors.grey.shade500,
                            ),
                          ),
                          Gaps.v3,
                          const Text(
                              "That's not it l've seen the same thing but also in a cave")
                        ],
                      ),
                    ),
                    Gaps.h10,
                    Column(
                      children: [
                        FaIcon(
                          FontAwesomeIcons.heart,
                          size: Sizes.size20,
                          color: Colors.grey.shade500,
                        ),
                        Gaps.v2,
                        Text(
                          "52.2K",
                          style: TextStyle(
                            color: Colors.grey.shade500,
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
              Positioned(
                //BottomAppBar를 0으로 고정, width값도 줘야함
                bottom: 0,
                //플러터가 유저의 화면 크기를 알아와서 Positioned의 width로 자동 설정해주기
                width: size.width,
                child: BottomAppBar(
                  color: Colors.white,

                  // comment창 위치 조정
                  child: Padding(
                    //여기서의 사이즈 크기는 큰 단위로만 조정 가능
                    padding: const EdgeInsets.symmetric(
                      vertical: Sizes.size10,
                      horizontal: Sizes.size16,
                    ),
                    child: Row(
                      children: [
                        CircleAvatar(
                          radius: 18,
                          backgroundColor: Colors.grey.shade500,
                          foregroundColor: Colors.white,
                          child: const Text("joon"),
                        ),
                        Gaps.h10,
                        // comment창 UI꾸미기
                        Expanded(
                          //여기서의 사이즈 크기는 작은 단위로도 조정 가능
                          child: SizedBox(
                            height: Sizes.size44,
                            child: TextField(
                              //유저가 커멘트 적을 때 확인할 flag용
                              onTap: _onStartWriting,
                              //done을 return으로 바꿔주기 위한 설정
                              expands: true,
                              minLines: null,
                              maxLines: null,
                              textInputAction: TextInputAction.newline,
                              cursorColor: Theme.of(context).primaryColor,
                              decoration: InputDecoration(
                                hintText: "Write a comment...",
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(
                                      Sizes.size12,
                                    ),
                                    borderSide: BorderSide.none),
                                filled: true,
                                fillColor: Colors.grey.shade200,
                                contentPadding: const EdgeInsets.symmetric(
                                  //done을 return으로 바꿔주기 위한 설정하기 위해 vertical 빼주기
                                  // vertical: Sizes.size12,
                                  horizontal: Sizes.size12,
                                ),
                                // 댓글 쓰는 곳에 아이콘 넣기
                                suffixIcon: Padding(
                                  padding: const EdgeInsets.only(
                                    right: Sizes.size14,
                                  ),
                                  child: Row(
                                    // row는 최대 공간 차지하니까 min
                                    mainAxisSize: MainAxisSize.min,
                                    children: [
                                      FaIcon(
                                        FontAwesomeIcons.at,
                                        color: Colors.grey.shade900,
                                      ),
                                      Gaps.h14,
                                      FaIcon(
                                        FontAwesomeIcons.gift,
                                        color: Colors.grey.shade900,
                                      ),
                                      Gaps.h14,
                                      FaIcon(
                                        FontAwesomeIcons.faceSmile,
                                        color: Colors.grey.shade900,
                                      ),
                                      Gaps.h14,
                                      if (_isWriting)
                                        GestureDetector(
                                          onTap: _stopWriting,
                                          child: FaIcon(
                                            FontAwesomeIcons.circleArrowUp,
                                            color:
                                                Theme.of(context).primaryColor,
                                          ),
                                        ),
                                    ],
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

8.4 Conclusions

1.bug + 스크롤러 만들기

//사용자가 창 닫을 수 있는 기능
class _VideoCommentsState extends State<VideoComments> {
  //유저가 커멘트 적을 때 확인할 flag용
  bool _isWriting = false;
  
  
                        ---------------
  //스크롤러 만들기
  final ScrollController _scrollController = ScrollController();
                        ---------------
                        
                        
  void _onClosePressed() {
    Navigator.of(context).pop();

child: Stack(
                        ---------------
            children: [
            //스크롤러 만들기
              Scrollbar(
                controller: _scrollController,
                child: ListView.separated(
                  controller: _scrollController,
              ---------------
              
              ---------------
                // 밑부분 댓글창 확실히 보이게 하기 위해 여유공간 마련하기
                padding: const EdgeInsets.only(
                  top: Sizes.size10,
                  bottom: Sizes.size96 + Sizes.size20,
                  left: Sizes.size16,
                  right: Sizes.size16,
                ),
                              ---------------
                              
                              
                separatorBuilder: (context, index) => Gaps.v20,
                itemCount: 10,
                itemBuilder: (context, index) => Row(

 

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 VideoComments extends StatefulWidget {
  const VideoComments({super.key});

  @override
  State<VideoComments> createState() => _VideoCommentsState();
}

//사용자가 창 닫을 수 있는 기능
class _VideoCommentsState extends State<VideoComments> {
  //유저가 커멘트 적을 때 확인할 flag용
  bool _isWriting = false;

  //스크롤러 만들기
  final ScrollController _scrollController = ScrollController();

  void _onClosePressed() {
    Navigator.of(context).pop();
  }

  //댓글창 누르면 키보드 사라지게 하는 함수
  void _stopWriting() {
    FocusScope.of(context).unfocus();

    //유저가 커멘트 적을 때 확인할 flag용
    setState(() {
      _isWriting = false;
    });
  }

  //유저가 커멘트 적을 때 확인할 flag용
  void _onStartWriting() {
    setState(() {
      _isWriting = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    //플러터가 유저의 화면 크기를 알아와서 Positioned의 width로 자동 설정해주기 parameter
    final size = MediaQuery.of(context).size;

    return Container(
      //댓글창의 사이즈를 커스터마이즈하기 위한 설정
      height: size.height * 0.8,

      clipBehavior: Clip.hardEdge,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(
          Sizes.size10,
        ),
      ),
      child: Scaffold(
        backgroundColor: Colors.grey.shade50,
        appBar: AppBar(
          backgroundColor: Colors.grey.shade50,
          //AppBar에서 디폴트로 생기는 백버튼 없애기
          automaticallyImplyLeading: false,
          title: const Text("22796 comments"),
          //사용자가 창 닫을 수 있는 기능
          actions: [
            IconButton(
              onPressed: _onClosePressed,
              icon: const FaIcon(FontAwesomeIcons.xmark),
            ),
          ],
        ),
        body: GestureDetector(
          //댓글창 누르면 키보드 사라지게 하는 파라메터
          onTap: _stopWriting,
          child: Stack(
            children: [
              //스크롤러 만들기
              Scrollbar(
                controller: _scrollController,
                child: ListView.separated(
                  controller: _scrollController,
                  // 밑부분 댓글창 확실히 보이게 하기 위해 여유공간 마련하기
                  padding: const EdgeInsets.only(
                    top: Sizes.size10,
                    bottom: Sizes.size96 + Sizes.size20,
                    left: Sizes.size16,
                    right: Sizes.size16,
                  ),
                  separatorBuilder: (context, index) => Gaps.v20,
                  itemCount: 10,
                  itemBuilder: (context, index) => Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const CircleAvatar(
                        radius: 18,
                        child: Text("joon"),
                      ),
                      Gaps.h10,
                      Expanded(
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              "joon",
                              style: TextStyle(
                                fontWeight: FontWeight.bold,
                                fontSize: Sizes.size14,
                                color: Colors.grey.shade500,
                              ),
                            ),
                            Gaps.v3,
                            const Text(
                                "That's not it l've seen the same thing but also in a cave")
                          ],
                        ),
                      ),
                      Gaps.h10,
                      Column(
                        children: [
                          FaIcon(
                            FontAwesomeIcons.heart,
                            size: Sizes.size20,
                            color: Colors.grey.shade500,
                          ),
                          Gaps.v2,
                          Text(
                            "52.2K",
                            style: TextStyle(
                              color: Colors.grey.shade500,
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
              Positioned(
                //BottomAppBar를 0으로 고정, width값도 줘야함
                bottom: 0,
                //플러터가 유저의 화면 크기를 알아와서 Positioned의 width로 자동 설정해주기
                width: size.width,
                child: BottomAppBar(
                  color: Colors.white,

                  // comment창 위치 조정
                  child: Padding(
                    //여기서의 사이즈 크기는 큰 단위로만 조정 가능
                    padding: const EdgeInsets.symmetric(
                      vertical: Sizes.size10,
                      horizontal: Sizes.size16,
                    ),
                    child: Row(
                      children: [
                        CircleAvatar(
                          radius: 18,
                          backgroundColor: Colors.grey.shade500,
                          foregroundColor: Colors.white,
                          child: const Text("joon"),
                        ),
                        Gaps.h10,
                        // comment창 UI꾸미기
                        Expanded(
                          //여기서의 사이즈 크기는 작은 단위로도 조정 가능
                          child: SizedBox(
                            height: Sizes.size44,
                            child: TextField(
                              //유저가 커멘트 적을 때 확인할 flag용
                              onTap: _onStartWriting,
                              //done을 return으로 바꿔주기 위한 설정
                              expands: true,
                              minLines: null,
                              maxLines: null,
                              textInputAction: TextInputAction.newline,
                              cursorColor: Theme.of(context).primaryColor,
                              decoration: InputDecoration(
                                hintText: "Write a comment...",
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(
                                      Sizes.size12,
                                    ),
                                    borderSide: BorderSide.none),
                                filled: true,
                                fillColor: Colors.grey.shade200,
                                contentPadding: const EdgeInsets.symmetric(
                                  //done을 return으로 바꿔주기 위한 설정하기 위해 vertical 빼주기
                                  // vertical: Sizes.size12,
                                  horizontal: Sizes.size12,
                                ),
                                // 댓글 쓰는 곳에 아이콘 넣기
                                suffixIcon: Padding(
                                  padding: const EdgeInsets.only(
                                    right: Sizes.size14,
                                  ),
                                  child: Row(
                                    // row는 최대 공간 차지하니까 min
                                    mainAxisSize: MainAxisSize.min,
                                    children: [
                                      FaIcon(
                                        FontAwesomeIcons.at,
                                        color: Colors.grey.shade900,
                                      ),
                                      Gaps.h14,
                                      FaIcon(
                                        FontAwesomeIcons.gift,
                                        color: Colors.grey.shade900,
                                      ),
                                      Gaps.h14,
                                      FaIcon(
                                        FontAwesomeIcons.faceSmile,
                                        color: Colors.grey.shade900,
                                      ),
                                      Gaps.h14,
                                      if (_isWriting)
                                        GestureDetector(
                                          onTap: _stopWriting,
                                          child: FaIcon(
                                            FontAwesomeIcons.circleArrowUp,
                                            color:
                                                Theme.of(context).primaryColor,
                                          ),
                                        ),
                                    ],
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

 

2. 버그 수정

영상이 재생되고 있는 상태에서 다른 탭으로 넘어가면 리소스 폐기(dispose, 영상정지)해주는 설정

// 비디오가 보여지는 영역을 계산하고 한쪽에서만 영상 재생되도록 해주는 파라메터
  void _onVisibilityChanged(VisibilityInfo info) {
    if (info.visibleFraction == 1 &&
        !_isPaused &&
        !_videoPlayerController.value.isPlaying) {
      _videoPlayerController.play();
    }
---------------------
    //영상이 재생되고 있는 상태에서 다른 탭으로 넘어가면 리소스 폐기(dispose, 영상정지)해주는 설정
    if (_videoPlayerController.value.isPlaying && info.visibleFraction == 0) {
      _onTogglePause();
    }
  }
  ---------------------

728x90
반응형
Comments