Flutter (13) Chat Screen Layout

Huisu·2023년 3월 11일
0

Flutter

목록 보기
13/21
post-thumbnail
post-custom-banner

Custom App Bar

  • app bar 위젯을 implement preferredsizewidget 으로 생성하기

    import 'package:flutter/material.dart';
    import 'package:calling/utils/universal_variables.dart';
    
    class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
    
      final Widget title;
      final List<Widget> actions;
      final Widget leading;
      final bool centerTitle;
    
      const CustomAppBar({
        Key? key,
        required this.title,
        required this.actions,
        required this.leading,
        required this.centerTitle
      }) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Container(
          padding: const EdgeInsets.all(10.0),
          decoration: BoxDecoration(
            color: UniversalVariables.blackColor,
            border: Border(
              bottom: BorderSide(
                color: UniversalVariables.separatorColor,
                width: 1.4,
                style: BorderStyle.solid,
              ),
            ),
          ),
          child: AppBar(
            backgroundColor: UniversalVariables.blackColor,
            elevation: 0,
            leading: leading,
            actions: actions,
            centerTitle: centerTitle,
            title: title,
          ),
        );
      }
      final Size preferredSize = const Size.fromHeight(kToolbarHeight);
    }

Chat List Screen

  • home_screen 페이지에 container로 chat list 생성

  • chat_list_screen.dart 파일 만들고 firebase에서 사용자 가져와 초기화하는 파일 작성

  • utils 파일에 이니셜 반환하는 함수 작성

  • User의 프로필을 받아서 앱 바를 그리는 코드 작성

    import 'package:calling/resources/firebase_repository.dart';
    import 'package:calling/utils/universal_variables.dart';
    import 'package:calling/widgets/appbar.dart';
    import 'package:flutter/material.dart';
    import 'package:calling/utils/utilities.dart';
    
    class ChatListScreen extends StatefulWidget {
      const ChatListScreen({Key? key}) : super(key: key);
    
      
      State<ChatListScreen> createState() => _ChatListScreenState();
    }
    
    final FirebaseRepository _repository = FirebaseRepository();
    
    class _ChatListScreenState extends State<ChatListScreen> {
      late String currentUserId;
      late String initials ="";
    
      
      void initState() {
        super.initState();
        _repository.getCurrentUser().then((user) {
          setState(() {
            currentUserId = user.uid;
            initials = Utils.getInitials(user.displayName!);
          });
        });
      }
    
      CustomAppBar customAppBar(BuildContext context) {
        return CustomAppBar(
            title: UserCircle(initials),
            actions: <Widget> [
              IconButton(
                icon: Icon(
                  Icons.search,
                  color: Colors.white,
                ),
                onPressed: () {
                  Navigator.pushNamed(context, "/search_screen");
                },
              ),
              IconButton(
                icon: Icon(
                  Icons.more_vert,
                  color: Colors.white,
                ),
                onPressed: () {},
              ),
            ],
            leading: IconButton(
              icon: Icon(
                Icons.notifications,
                color: Colors.white,
              ),
              onPressed: () {},
            ),
            centerTitle: true
        );
      }
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: UniversalVariables.blackColor,
          appBar: customAppBar(context),
        );
      }
    }
    
    class UserCircle extends StatelessWidget {
      final String text;
      const UserCircle(this.text);
      
      Widget build(BuildContext context) {
        return Container(
          height: 40,
          width: 40,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(50),
            color: UniversalVariables.separatorColor,
          ),
          child: Stack(
            children: <Widget>[
              Align(
                alignment: Alignment.center,
                child: Text(
                  text,
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    color: UniversalVariables.lightBlueColor,
                    fontSize: 13,
                  ),
                ),
              ),
              Align(
                alignment: Alignment.bottomRight,
                child: Container(
                  height: 12,
                  width: 12,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    border: Border.all(
                      color: UniversalVariables.blackColor,
                      width: 2
                    ),
                    color: UniversalVariables.onlineDotColor,
                  ),
                ),
              )
            ],
          ),
        );
      }
    }
  • app bar 구동 화면

  • new chat button 위젯 만들어서 chat list 에 띄우기

  • new chat button 위젯 코드 작성

    	class NewChatButton extends StatelessWidget {
      
      Widget build(BuildContext context) {
        return Container(
          decoration: BoxDecoration(
              gradient: UniversalVariables.fabGradient,
              borderRadius: BorderRadius.circular(50)),
          child: Icon(
            Icons.edit,
            color: Colors.white,
            size: 25,
          ),
          padding: EdgeInsets.all(15),
        );
      }
    }
  • new chat button 생성

  • 채팅 목록을 보여 주는 chatlistcontainer 바디에 위치시키기

  • custom tile 을 만들기 위한 변수들 선언하기

  • custom tile 그리는 코드 작성

  • custom tile 전체 코드

    import 'package:flutter/material.dart';
    import 'package:calling/utils/universal_variables.dart';
    
    class CustomTile extends StatelessWidget {
      final Widget leading;
      final Widget title;
      final Widget? icon;
      final Widget subtitle;
      final Widget? trailing;
      final EdgeInsets margin;
      final bool mini;
      final GestureTapCallback? onTap;
      final GestureLongPressCallback? onLongPress;
    
      const CustomTile({
        required this.leading,
        required this.title,
        this.icon,
        required this.subtitle,
        this.trailing,
        this.margin = const EdgeInsets.all(0),
        this.onTap,
        this.onLongPress,
        this.mini = true,
    });
    
      
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: onTap,
          onLongPress: onLongPress,
          child: Container(
            padding: EdgeInsets.symmetric(horizontal: mini ? 10 : 0),
            margin: margin,
            child: Row(
              children: <Widget>[
                leading,
                Expanded(
                  child: Container(
                    margin: EdgeInsets.only(left: mini ? 10 : 15),
                    padding: EdgeInsets.symmetric(vertical: mini ? 3 : 20),
                    decoration: BoxDecoration(
                        border: Border(
                            bottom: BorderSide(
                                width: 1,
                                color: UniversalVariables.separatorColor))),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            title,
                            SizedBox(height: 5),
                            Row(
                              children: <Widget>[
                                icon ?? Container(),
                                subtitle,
                              ],
                            )
                          ],
                        ),
                        trailing ?? Container(),
                      ],
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      }
    }
  • custom tile 이 적용된 chat list 화면

  • 전체 코드

    import 'package:calling/resources/firebase_repository.dart';
    import 'package:calling/utils/universal_variables.dart';
    import 'package:calling/widgets/appbar.dart';
    import 'package:flutter/material.dart';
    import 'package:calling/utils/utilities.dart';
    import '../../widgets/custom_tile.dart';
    
    class ChatListScreen extends StatefulWidget {
      const ChatListScreen({Key? key}) : super(key: key);
    
      
      State<ChatListScreen> createState() => _ChatListScreenState();
    }
    
    final FirebaseRepository _repository = FirebaseRepository();
    
    class _ChatListScreenState extends State<ChatListScreen> {
      late String currentUserId;
      late String initials ="";
    
      
      void initState() {
        super.initState();
        _repository.getCurrentUser().then((user) {
          setState(() {
            currentUserId = user.uid;
            initials = Utils.getInitials(user.displayName!);
          });
        });
      }
    
      CustomAppBar customAppBar(BuildContext context) {
        return CustomAppBar(
            title: UserCircle(initials),
            actions: <Widget> [
              IconButton(
                icon: Icon(
                  Icons.search,
                  color: Colors.white,
                ),
                onPressed: () {
                  Navigator.pushNamed(context, "/search_screen");
                },
              ),
              IconButton(
                icon: Icon(
                  Icons.more_vert,
                  color: Colors.white,
                ),
                onPressed: () {},
              ),
            ],
            leading: IconButton(
              icon: Icon(
                Icons.notifications,
                color: Colors.white,
              ),
              onPressed: () {},
            ),
            centerTitle: true
        );
      }
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: UniversalVariables.blackColor,
          appBar: customAppBar(context),
          floatingActionButton: NewChatButton(),
          body: ChatListContainer(currentUserId),
        );
      }
    }
    
    class UserCircle extends StatelessWidget {
      final String text;
      const UserCircle(this.text);
      
      Widget build(BuildContext context) {
        return Container(
          height: 40,
          width: 40,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(50),
            color: UniversalVariables.separatorColor,
          ),
          child: Stack(
            children: <Widget>[
              Align(
                alignment: Alignment.center,
                child: Text(
                  text,
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    color: UniversalVariables.lightBlueColor,
                    fontSize: 13,
                  ),
                ),
              ),
              Align(
                alignment: Alignment.bottomRight,
                child: Container(
                  height: 12,
                  width: 12,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    border: Border.all(
                      color: UniversalVariables.blackColor,
                      width: 2
                    ),
                    color: UniversalVariables.onlineDotColor,
                  ),
                ),
              )
            ],
          ),
        );
      }
    }
    
    class NewChatButton extends StatelessWidget {
      
      Widget build(BuildContext context) {
        return Container(
          decoration: BoxDecoration(
              gradient: UniversalVariables.fabGradient,
              borderRadius: BorderRadius.circular(50)),
          child: Icon(
            Icons.edit,
            color: Colors.white,
            size: 25,
          ),
          padding: EdgeInsets.all(15),
        );
      }
    }
    
    class ChatListContainer extends StatefulWidget {
      final String currentUserId;
    
      ChatListContainer(this.currentUserId);
    
      
      _ChatListContainerState createState() => _ChatListContainerState();
    }
    
    class _ChatListContainerState extends State<ChatListContainer> {
      
      Widget build(BuildContext context) {
        return Container(
          child: ListView.builder(
            padding: EdgeInsets.all(10),
            itemCount: 2,
            itemBuilder: (context, index) {
              return CustomTile(
                mini: false,
                onTap: () {},
                title: Text(
                  "LIFLOW",
                  style: TextStyle(
                      color: Colors.white, fontFamily: "Arial", fontSize: 19),
                ),
                subtitle: Text(
                  "Hello. Example",
                  style: TextStyle(
                    color: UniversalVariables.greyColor,
                    fontSize: 14,
                  ),
                ),
                leading: Container(
                  constraints: BoxConstraints(maxHeight: 60, maxWidth: 60),
                  child: Stack(
                    children: <Widget>[
                      CircleAvatar(
                        maxRadius: 30,
                        backgroundColor: Colors.grey,
                        backgroundImage: NetworkImage(
                            "https://yt3.ggpht.com/a/AGF-l7_zT8BuWwHTymaQaBptCy7WrsOD72gYGp-puw=s900-c-k-c0xffffffff-no-rj-mo"),
                      ),
                      Align(
                        alignment: Alignment.bottomRight,
                        child: Container(
                          height: 13,
                          width: 13,
                          decoration: BoxDecoration(
                              shape: BoxShape.circle,
                              color: UniversalVariables.onlineDotColor,
                              border: Border.all(
                                  color: UniversalVariables.blackColor, width: 2)),
                        ),
                      )
                    ],
                  ),
                ),
              );
            },
          ),
        );
      }
    }
post-custom-banner

0개의 댓글