내 첫 모바일 앱 만들기
29278 단어 mobileprogrammingflutterfirebase
앱이 어떤 모습일지 확신할 수 없었기 때문에 Flutter에서 UI를 구축하는 것부터 시작했습니다. 그래서 https://fireship.io:에 대한 자습서의 도움을 받아 초기 페이지를 만들기 시작했습니다.
로그인 페이지부터 시작하겠습니다.
현재로서는 특별한 것이 없습니다. 게스트로 로그인하거나 Google을 사용하여 로그인할 수 있습니다. 이메일과 비밀번호(Google과 연결되지 않음)를 사용하여 로그인하는 기능을 추가할 계획입니다.
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:barbellplus/services/auth.dart';
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/login-background.jpg'),
fit: BoxFit.cover,
),
),
padding: const EdgeInsets.all(30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
FontAwesomeIcons.dumbbell,
size: 150,
color: Color.fromARGB(255, 209, 5, 5),
),
const Text(
'Barbell Plus',
textAlign: TextAlign.center,
style: TextStyle(
color: Color.fromARGB(255, 209, 5, 5),
fontSize: 40,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 120),
Flexible(
child: LoginButton(
icon: FontAwesomeIcons.userNinja,
text: 'Continue as Guest',
loginMethod: AuthService().anonLogin,
color: Colors.deepPurple,
),
),
LoginButton(
text: 'Sign in with Google',
icon: FontAwesomeIcons.google,
color: Colors.blue,
loginMethod: AuthService().googleLogin,
),
],
),
),
);
}
}
class LoginButton extends StatelessWidget {
final Color color;
final IconData icon;
final String text;
final Function loginMethod;
const LoginButton(
{super.key,
required this.text,
required this.icon,
required this.color,
required this.loginMethod});
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(bottom: 10),
child: ElevatedButton.icon(
icon: Icon(
icon,
color: Colors.white,
size: 20,
),
style: TextButton.styleFrom(
padding: const EdgeInsets.all(24),
backgroundColor: color,
),
onPressed: () => loginMethod(),
label: Text(text, textAlign: TextAlign.center),
),
);
}
}
나는 이전에 flutter나 dart를 사용한 적이 없지만 이전에 react.js를 사용하여 일부 웹 애플리케이션을 만들었습니다. Flutter에서 작업이 수행되는 방식의 차이를 보는 것은 매우 흥미로웠습니다. 예를 들어 화면의 특정 지점에 위젯을 배치하는 것과 같이 일부 위젯에는 원하는 작업을 수행하기 위해 특정 작업이 필요하다는 사실이 때때로 짜증납니다.
이제 나머지 페이지로 이동합니다.
이 페이지는 응용 프로그램에서 사용할 수 있는 모든 연습 목록입니다. 원래는 UI를 제대로 만들기 위해 샘플 데이터를 사용했습니다.
데이터베이스와 통합하기 시작하면서 실제 데이터 세트가 필요했습니다. 내 요구 사항에 맞는 것을 찾을 수 없습니다. 그래서 당분간은 필요한 데이터를 웹 스크랩하기로 결정했습니다. 이와 관련된 법적인 문제는 잘 모르겠지만 이 앱을 사용할 사람은 소수에 불과합니다. 위험을 감수해도 괜찮을 것 같아요. 그러나 만족스러운 데이터 세트를 찾으면 대신 사용할 것입니다.
import 'package:barbellplus/exercises/exercise_dialog.dart';
import 'package:barbellplus/services/firestore.dart';
import 'package:barbellplus/services/models.dart';
import 'package:flutter/material.dart';
class ExerciseList extends StatelessWidget {
const ExerciseList({super.key});
@override
Widget build(BuildContext context) {
return Expanded(
child: DecoratedBox(
decoration: const BoxDecoration(
color: Colors.white,
),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: FutureBuilder<List<Exercise>>(
future: FirestoreService().getExercises(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(
color: Color.fromARGB(255, 209, 5, 5)),
);
}
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) => ExerciseItem(
exercise: snapshot.data![index],
),
);
},
),
),
],
),
),
),
);
}
}
class ExerciseItem extends StatelessWidget {
final Exercise exercise;
// ignore: prefer_const_constructors_in_immutables
ExerciseItem({super.key, required this.exercise});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ExerciseDialog(exercise: exercise),
),
);
},
child: Container(
margin: const EdgeInsets.symmetric(vertical: 5),
height: 65,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.black12,
borderRadius: BorderRadius.circular(10),
),
child: Row(
children: [
const SizedBox(width: 10),
Stack(
children: [
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: Colors.black12,
borderRadius: BorderRadius.circular(10),
),
),
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: const DecorationImage(
image:
AssetImage('assets/images/image-unavailable.png'),
fit: BoxFit.cover,
),
),
),
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: NetworkImage(exercise.image),
fit: BoxFit.cover,
),
),
),
],
),
const SizedBox(width: 20),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 10),
Text(exercise.name,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
style: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 14,
)),
const SizedBox(height: 5),
Text(
'${exercise.muscle} • ${(exercise.equipment)} • ${exercise.difficulty}',
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
style: const TextStyle(
color: Colors.red,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
fontSize: 12,
)),
],
),
),
const SizedBox(width: 10),
],
)),
);
}
}
프로필 페이지로 이동: 이 페이지는 아직 완료되지 않았습니다. 약간의 개인 정보, 개인 진행 상황 이미지의 캐러셀 및 아직 결정되지 않은 다른 기능을 제공하는 다른 버튼이 있습니다.
나머지 페이지, 운동 및 네트워크는 아직 완료되지 않았습니다. 운동 페이지는 운동 프로그램을 선택하고 운동 데이터를 입력하는 곳입니다. 현재 클라우드 Firestore와 통합하는 과정에 있지만 약간의 어려움이 있습니다.
네트워크 페이지는 친구와 운동 진행 상황을 공유할 수 있는 앱의 사회적 측면이어야 하는지 잘 모르겠습니다. 어떻게 작동하고 싶은지 잘 모르겠습니다.
Reference
이 문제에 관하여(내 첫 모바일 앱 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/lmarshallafzal/building-my-first-mobile-app-38a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)