Flutter로 반응형 개발자 포트폴리오 웹사이트(앱) 구축
그리고 자신만의 개발자 포트폴리오를 구축해야 한다면 직접 구축하지 않겠습니까!
이 튜토리얼에서는 Flutter로 반응형 개발자 포트폴리오 웹사이트/앱을 구축하는 방법을 단계별로 알려 드리겠습니다. 이 튜토리얼을 따르면 배우게 될 것입니다 -
ScrollController을 사용하고 프로그래밍 방식으로 스크롤하는 방법. 내용의 테이블
우리가 만들 것
We are going to build a portfolio app with mainly 4 sections about , skills , projects and contact . For making our app responsive we'll use media query.
라이브 데모
If you are so excited to see what we'll build like me, you can see the live demo of app Here . 이 웹 버전 데모는 html 렌더러를 사용하여 배포됩니다.Live Demo
비디오 설명
At the time of writing this post. It was getting too long so I added this video explanation section.
If you want to watch video tutorial of this post you can watch it from here.
프로젝트 생성
Supposing flutter is installed and initial setup is done in your system.If you have't installed then you can get it from here
VS Code 또는 Android Studio에서 명령 팔레트를 사용하거나 터미널에 다음 명령을 입력하여 새 플러터 프로젝트를 만듭니다.
flutter create <YOUR PROJECT NAME> 초기 설정
Now careate a new folder in your project assets
Inside the assets folder create a subfolder images
Add an image that you want to show on your portfolio, in your images folder.
Your image should be placed like this
assets/images/
Now load images in pubspec.yaml file
assets:
- assets/images/
Clear everything from main.dart file and write the following code.
import 'package:flutter/material.dart';
import 'package:portfolio_app/pages/home_page.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner:false,
home: HomePage(),
);
}
}
디렉토리 설정
Inside the lib folder create 3 new directory named components , models , pages .
-lib
- components
- models
- pages
홈페이지 만들기
As you can see in the above code we have used HomePage in the home of MaterialApp lets create it.
Inside the pages directory create a new file homepage.dart .
Create a stateless widget HomePage in it like below.
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
//Add Key
appBar: AppBar(
title: const Text(
'JANE DOE',
style: TextStyle(
fontSize: 22,
color: Color(0xFF4756DF),
fontWeight: FontWeight.bold,
),
),
backgroundColor: Colors.white,
elevation: 2,
),
body: SafeArea(
child: Stack(
children: [
SingleChildScrollView(
//Add Scroll Controller
child: Column(
children: const [
],
),
),
],
),
),
);
}
}
Now we need to create a GlobalKey and a ScrollController .
GlobalKey - for opening and closing the end drawer that we'll use later.
ScrollController - for scrolling to a specific section of page.
final ScrollController myScrollController = ScrollController();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
add the _scaffoldKey in the Scaffold widget and myScrollController in the SingleChildScrollView.
Navbar 섹션 만들기
Because we have to create a responsive UI we'll show the navbar inside the endDrawer of Scaffold on small screen and inside the actions of AppBar on large screen.
Inside the components directory caret a new file home_page_actions.dart and write the following code.
import 'package:flutter/material.dart';
import 'package:portfolio_app/utils.dart';
class HomePageActions extends StatelessWidget {
final ScrollController sc;
const HomePageActions({Key? key, required this.sc}) : super(key: key);
@override
Widget build(BuildContext context) {
bool isMobile = Utils.isMobile(context);
return isMobile
? Column(
children: getWidgets(sc, context, isMobile: true),
)
: Row(
children: getWidgets(sc, context),
);
}
List<Widget> getWidgets(ScrollController sc, BuildContext context,
{bool isMobile = false}) {
int scrollDur = isMobile ? 800 : 500;
return [
Padding(
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: isMobile ? 20 : 0),
child: TextButton(
onPressed: () {
if (isMobile) Navigator.pop(context);
sc.animateTo(
200,
duration: Duration(milliseconds: scrollDur),
curve: Curves.easeIn,
);
},
child: const Text(
'About',
style: TextStyle(
fontSize: 17,
color: Color(0xFf4756DF),
fontWeight: FontWeight.w600,
),
),
),
),
Padding(
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: isMobile ? 20 : 0),
child: TextButton(
onPressed: () {
if (isMobile) Navigator.pop(context);
sc.animateTo(
isMobile ? 1100 : 800,
duration: Duration(milliseconds: scrollDur),
curve: Curves.easeIn,
);
},
child: const Text(
'Skills',
style: TextStyle(
fontSize: 17,
color: Color(0xFf4756DF),
fontWeight: FontWeight.w600,
),
),
),
),
Padding(
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: isMobile ? 20 : 0),
child: TextButton(
onPressed: () {
if (isMobile) Navigator.pop(context);
sc.animateTo(
1400,
duration: Duration(milliseconds: scrollDur),
curve: Curves.easeIn,
);
},
child: const Text(
'Projects',
style: TextStyle(
fontSize: 17,
color: Color(0xFf4756DF),
fontWeight: FontWeight.w600,
),
),
),
),
Padding(
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: isMobile ? 20 : 0),
child: TextButton(
onPressed: () {
if (isMobile) Navigator.pop(context);
sc.animateTo(
isMobile ? 2600 : 1900,
duration: Duration(milliseconds: scrollDur),
curve: Curves.easeIn,
);
},
child: const Text(
'Contact',
style: TextStyle(
fontSize: 17,
color: Color(0xFf4756DF),
fontWeight: FontWeight.w600,
),
),
),
)
];
}
}
There are lots of things in the above code but we'll see only the important one.
As you can see we have used Utils class so lets create it.
Inside the lib create a new directory called utils.dart and write the following code.
import 'package:flutter/cupertino.dart';
class Utils {
static bool isMobile(BuildContext context) {
return MediaQuery.of(context).size.width <= 600;
}
static double mdqh(BuildContext context) {
return MediaQuery.of(context).size.height;
}
static double mdqw(BuildContext context) {
return MediaQuery.of(context).size.width;
}
}
the isMobile method returns true if the screen width of device is less than or equal to 600 pixel, you can decide your own logic for that.
mdqh method returns the height of screen
mdqw method return the width of screen
These utilities will help us to make UI responsive.
Now go to HomePage and inside the AppBar of Scaffold add the following code.
actions: [
Utils.isMobile(context)
? Padding(
padding: const EdgeInsets.only(right: 10),
child: IconButton(
icon: const Icon(
Icons.menu,
color: Color(0xFf4756DF),
size: 30,
),
onPressed: () {
_scaffoldKey.currentState!.openEndDrawer();
},
),
)
: HomePageActions(
sc: myScrollController,
),
],
and in the Scaffold of HomePage add the endDrawer
endDrawer: Utils.isMobile(context)
? MyDrawer(
sc: myScrollController,
)
: null,
now lets create our MyDrawer widget
endDrawer 만들기
Inside the components create a new file my_drawer.dart and write the following code
import 'package:flutter/material.dart';
import 'package:portfolio_app/components/home_page_actions.dart';
class MyDrawer extends StatelessWidget {
final ScrollController sc;
const MyDrawer({Key? key, required this.sc}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: const Icon(
Icons.close,
color: Color(0xFF4756DF),
),
),
),
body: Center(child: HomePageActions(sc: sc)),
);
}
}
You can see we are reusing the HomePageActions again here and it will be visible only on the small screen, remember the code that we wrote in it.
Now inside the HomePage Scaffold add the floating action button that will help to scroll at top.
floatingActionButton: FloatingActionButton(
mini: Utils.isMobile(context) ? true : false,
onPressed: () {
myScrollController.animateTo(
0,
duration: const Duration(milliseconds: 800),
curve: Curves.easeIn,
);
},
child: Image.network(
'https://eager-williams-af0d00.netlify.app/assets/icons/icons8-upward-arrow.gif',
),
),
animateTo method of ScrollController will scroll the page to the specified position will nice animation you can define the duration and curve for the animation.
The same method we are using in the HomePageActions buttons to scroll at a specific section using a calculated height.
If I write the complete code the article will be too long and boring. So lets quickly complete our project. You can find the source code in the last section
홈페이지 구성요소 생성
Now in the HomePage inside the children of column add the remaining components.
children: const [
Header1(),
MoreAboutMe(),
SizedBox(height: 50),
TopSkills(),
SizedBox(height: 50),
RecentProjects(),
SizedBox(height: 50),
ContactForm(),
SizedBox(height: 50),
Footer(),
SizedBox(height: 20),
],
이제 HomePage에서 사용한
children 중 Stack의 맨 아래에 마지막으로 다음 컴포넌트를 추가합니다.const SocialIconsBar(),
프로젝트 모델 생성
In the RecentProjects() component we need Projectmodel so
in the models directory create a new file called project_model.dart and write the following code.
lass ProjectModel {
final String imgURL;
final String projectName;
final String? shortDescription;
final String actionLink;
ProjectModel(
{required this.imgURL, required this.projectName, this.shortDescription, required this.actionLink});
}
Create a new file inside the lib called constants.dart and create some ProjectModels/Demo Projects.
import 'package:portfolio_app/models/project_model.dart';
class Constants {
static final List<ProjectModel> projects = [
ProjectModel(
actionLink: '#',
imgURL:
'https://eager-williams-af0d00.netlify.app/assets/images/expenseTracker.png',
projectName: 'Expense Tracker',
),
ProjectModel(
actionLink: '#',
imgURL:
'https://eager-williams-af0d00.netlify.app/assets/images/netflixClone.png',
projectName: 'Netflix Clone',
),
ProjectModel(
actionLink: '#',
imgURL:
'https://eager-williams-af0d00.netlify.app/assets/images/greenyEarth.png',
projectName: 'Greeny Earth',
),
And we have successfully created our responsive developer portfolio with flutter 🎉
소스 코드
You can see/download the source code from github.Repo Link
감사!
Reference
이 문제에 관하여(Flutter로 반응형 개발자 포트폴리오 웹사이트(앱) 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/pktintali/build-your-own-responsive-developer-portfolio-website-app-with-flutter-k70텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)