Instagram Clone Clean Architecture Flutter – Part 3

In the last article we’ve designed credential pages of our instagram app, and with this we’ve learned how can we keep our UI code clean by creating our custom widgets in the separate directories, and also we’ve modified our android settings in order to prevent couple of build exceptions.

Create a directory in your lib > presentation > pages > main_screen in the main screen create file main_screen.dart.

main_screen.dart

				
					import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:instagram_clone_app/features/presentation/page/activity/activity_page.dart';
import 'package:instagram_clone_app/features/presentation/page/post/upload_post_page.dart';
import 'package:instagram_clone_app/features/presentation/page/profile/profile_page.dart';
import 'package:instagram_clone_app/features/presentation/page/search/search_page.dart';
import '../../../../consts.dart';
import '../home/home_page.dart';

class MainScreen extends StatefulWidget {
  const MainScreen({Key? key}) : super(key: key);

  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {

  int _currentIndex = 0;

  late PageController pageController;

  @override
  void initState() {
    pageController = PageController();
    super.initState();
  }

  @override
  void dispose() {
    pageController.dispose();
    super.dispose();
  }

  void navigationTapped(int index) {
    pageController.jumpToPage(index);
  }

  void onPageChanged(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: backGroundColor,
      bottomNavigationBar: CupertinoTabBar(
        backgroundColor: backGroundColor,
        items: [
          BottomNavigationBarItem(icon: Icon(MaterialCommunityIcons.home_variant, color: primaryColor), label: ""),
          BottomNavigationBarItem(icon: Icon(Ionicons.md_search, color: primaryColor), label: ""),
          BottomNavigationBarItem(icon: Icon(Ionicons.md_add_circle, color: primaryColor), label: ""),
          BottomNavigationBarItem(icon: Icon(Icons.favorite, color: primaryColor), label: ""),
          BottomNavigationBarItem(icon: Icon(Icons.account_circle_outlined, color: primaryColor), label: ""),

        ],
        onTap: navigationTapped,
      ),
      body: PageView(
        controller: pageController,
        children: [
          HomePage(),
          SearchPage(),
          UploadPostPage(),
          ActivityPage(),
          ProfilePage()
        ],
        onPageChanged: onPageChanged,
      ),
    );
  }
}
				
			

That’s how our instagram main screen will looks like in the bottom navigation bar you can see all the pages are connected.

main_screen

Now create Directories in your pages directory according to the names below.

  • Home
  • Search
  • Post
  • Activity
  • Profile

After this create .dart files in them.

home_page.dart

				
					import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:instagram_clone_app/consts.dart';

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: backGroundColor,
      appBar: AppBar(
        backgroundColor: backGroundColor,
        title: SvgPicture.asset("assets/ic_instagram.svg", color: primaryColor, height: 32,),
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 10.0),
            child: Icon(MaterialCommunityIcons.facebook_messenger, color: primaryColor,),
          )
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Row(
                  children: [
                    Container(
                      width: 30,
                      height: 30,
                      decoration: BoxDecoration(
                        color: secondaryColor,
                        shape: BoxShape.circle
                      ),
                    ),
                    sizeHor(10),
                    Text("Username", style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),)
                  ],
                ),
                Icon(Icons.more_vert, color: primaryColor,)
              ],
            ),
            sizeVer(10),
            Container(
              width: double.infinity,
              height: MediaQuery.of(context).size.height * 0.30,
              color: secondaryColor,
            ),
            sizeVer(10),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Row(
                  children: [
                    Icon(Icons.favorite, color: primaryColor,),
                    sizeHor(10),
                    Icon(Feather.message_circle, color: primaryColor,),
                    sizeHor(10),
                    Icon(Feather.send, color: primaryColor,),
                  ],
                ),
                Icon(Icons.bookmark_border, color: primaryColor,)

              ],
            ),
            sizeVer(10),
            Row(
              children: [
                Text("Username", style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),),
                sizeHor(10),
                Text("some description", style: TextStyle(color: primaryColor),),
              ],
            ),
            sizeVer(10),
            Text("View all 10 comments", style: TextStyle(color: darkGreyColor),),
            sizeVer(10),
            Text("08/5/2022", style: TextStyle(color: darkGreyColor),),

          ],
        ),
      ),
    );
  }
}
				
			

search_page.dart

				
					import 'package:flutter/material.dart';
import 'package:instagram_clone_app/consts.dart';
import 'package:instagram_clone_app/features/presentation/page/search/widget/search_widget.dart';

class SearchPage extends StatefulWidget {
  const SearchPage({Key? key}) : super(key: key);

  @override
  State<SearchPage> createState() => _SearchPageState();
}

class _SearchPageState extends State<SearchPage> {
  TextEditingController _searchController = TextEditingController();

  @override
  void dispose() {
    _searchController.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        backgroundColor: backGroundColor,

        body: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10),
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                SearchWidget(controller: _searchController,),
                sizeVer(10),
                GridView.builder(itemCount: 32, physics: ScrollPhysics(), shrinkWrap: true,gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, crossAxisSpacing: 5, mainAxisSpacing: 5), itemBuilder: (context, index) {
                  return Container(
                    width: 100,
                    height: 100,
                    color: secondaryColor,
                  );
                })
              ],
            ),
          ),
        ),
      ),
    );
  }
				
			

search_widget.dart

				
					import 'package:flutter/material.dart';

import '../../../../../consts.dart';


class SearchWidget extends StatelessWidget {
  final TextEditingController controller;
  const SearchWidget({Key? key, required this.controller}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: 45,
      decoration: BoxDecoration(
        color: secondaryColor.withOpacity(.3),
        borderRadius: BorderRadius.circular(15),
      ),
      child: TextFormField(
        controller: controller,
        style: TextStyle(color: primaryColor),
        decoration: InputDecoration(
            border: InputBorder.none,
            prefixIcon: Icon(Icons.search, color: primaryColor,),
            hintText: "Search",
            hintStyle: TextStyle(color: secondaryColor, fontSize: 15)
        ),
      ),
    )
    ;
  }
}
				
			

upload_post_page.dart

				
					import 'package:flutter/material.dart';
import 'package:instagram_clone_app/consts.dart';

class UploadPostPage extends StatelessWidget {
  const UploadPostPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: backGroundColor,

      body: Center(
        child: Container(
          width: 150,
          height: 150,
          decoration: BoxDecoration(
              color: secondaryColor.withOpacity(.3),
              shape: BoxShape.circle
          ),
          child: Center(
            child: Icon(Icons.upload, color: primaryColor, size: 40,),
          ),
        ),
      )
    );
  }
}
				
			

activity_page.dart

				
					import 'package:flutter/material.dart';
import 'package:instagram_clone_app/consts.dart';

class ActivityPage extends StatelessWidget {
  const ActivityPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: backGroundColor,
      appBar: AppBar(
        backgroundColor: backGroundColor,
        title: Text("Activity", style: TextStyle(color: primaryColor),),
      ),
    );
  }
}
				
			

profile_page.dart

				
					import 'package:flutter/material.dart';
import 'package:instagram_clone_app/consts.dart';

class ProfilePage extends StatelessWidget {
  const ProfilePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: backGroundColor,
      appBar: AppBar(
        backgroundColor: backGroundColor,
        title: Text("Username", style: TextStyle(color: primaryColor),),
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 10.0),
            child: Icon(Icons.menu, color: primaryColor,),
          )
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10),
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Container(
                    width: 80,
                    height: 80,
                    decoration: BoxDecoration(
                      color: secondaryColor,
                      shape: BoxShape.circle
                    ),
                  ),
                  Row(
                    children: [
                      Column(
                        children: [
                          Text("0", style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),),
                          sizeVer(8),
                         Text("Posts", style: TextStyle(color: primaryColor),)
                        ],
                      ),
                      sizeHor(25),
                      Column(
                        children: [
                          Text("54", style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),),
                          sizeVer(8),
                          Text("Followers", style: TextStyle(color: primaryColor),)
                        ],
                      ),
                      sizeHor(25),
                      Column(
                        children: [
                          Text("123", style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),),
                          sizeVer(8),
                          Text("Following", style: TextStyle(color: primaryColor),)
                        ],
                      )
                    ],
                  )
                ],
              ),
              sizeVer(10),
              Text("Name", style: TextStyle(color: primaryColor,fontWeight: FontWeight.bold),),
              sizeVer(10),
              Text("The bio of user", style: TextStyle(color: primaryColor),),
              sizeVer(10),
              GridView.builder(itemCount: 32, physics: ScrollPhysics(), shrinkWrap: true,gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, crossAxisSpacing: 5, mainAxisSpacing: 5), itemBuilder: (context, index) {
                return Container(
                  width: 100,
                  height: 100,
                  color: secondaryColor,
                );
              })
            ],
          ),
        ),
      )
    );
  }
}
				
			

Conclusion

In this 3rd article we’ve designed the our main screen and all the pages, Now only the pages in which navigation is required like comment page, edit post page etc will be designed in the next article. And if you didn’t watch the YouTube video hit the link below to check the video out and be sure to subscribe and hit the bell icon to make sure you get notified whenever the next video is uploaded.

Website:
Have any Questions? Find me on

Leave a Reply

You may like