Notice
Recent Posts
Recent Comments
Link
250x250
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 플러터#
- 임대사업자#리걸테크#legaltech#마이봇#챗봇#법률챗봇#임대사업자챗봇#chatgpt#
- postgres#vector
- 쇼핑몰관리시스템#매입관리#시트메타#매입채널#엑셀업로드
- flutterfire configure#파이어베이스#플러터
- PDF검색#PDF검색챗봇#NEXTJS#스터디#스타트업#랭체이#langchain#prisma#sqlite#
- 마이봇#핸드폰대체#
- 펫버틀러#서버연동#프로필등록#로그인서버연동#이미지#동영상#업로드용 화면#앱개발#플러터#반려생활#로딩바#loading bar#
- 플러터#sms#mms#문자보내기
- 마이봇#아이폰#아이폰심사#IT고시#
- mediasaop#webrtc#미디어서버#
- flutter#sqlite#chatGPT#
- fcm#메세지전송#안드로이드메세지#플러터메세지전송
- figma#flutter#dhwise#피그마#플러터#피그마 to 플러터 #figma to flutter
- PDF#챗봇검색#서비스#GPT4#PGT3.5#GPT#랭체인#챗봇#CHATBOT#LLM#문서검색
- flutter#채팅창@메모창#url링크#날짜추가
- 마이봇#pdf챗봇#상담챗봇#faq챗봇#chatgpt#랭체인#llm
- 마이봇#챗봇
- ax5#tree#grid#단계별 펼치기# depth #시트메타
- 로우코드#lowcode#erp#관리시스템#시트메이트#시트메타#엑셀업로드#엑셀다운로드#그리드#데이터관리#생산관리시스템#로그관리#히스토리#입력체크
- firebase#message#메세지#플러터#안드로이드
- 광동온더그린#프랜즈#가상CC#스크린골프#
- 로우코드#ERP#관리시스템#상품관리#선택박스#자동화프로그램
- 마이봇#API 설정
- 마이봇#chatgpt#ai#인공지능
- 시트메타#관리시스템#테이블연동#품목관리
- #창작#SNS#스포츠#반려동물#연애#과제#레시피#활동#건강#운세#글쓰기#비즈니스 #AI비서#챗GPT#CHATGPT
- 마이봇#문서챗봇#PDF#TEXT#유투브#챗봇만들기#랭체인# langchain#벡터데이터#자료검색#챗GPT#GPT4#챗지피티
- 커피#그라인더#통돌이 오픈 #로스팅#드립커피#생두#원두
- flutter#ios#앱개발#마이봇#
Archives
- Today
- Total
혼자서 앱 만드는 개발자 함께하는 AI 세상
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 5 일차 (강아지 프로필 등록) 본문
반응형
- 이전 구글로그인 작업 후 이번 차수에서 프로필 등록 작업을 진행 해보겠다.
- 프로필은 간단한 소개글 함께 아이콘 이미지를 추가 할 수 있도록 개발해 본다.
- 위에서 첫 번째 페이지를 먼저 디자인 하기로 했다.
- 1번 항목 작업은 별도의 위젯으로 처리했다. 입력폼은 컨트롤러 아이콘 필드명을 변수로 입력 받아 처리한다.
- 글쓰기 항목 위젯 소스 Container 위젯으로 padding 처리하고 TextFormField 를 이용해서 입력폼을 작성해서 위젯으로만들놓고 다음 페이지 처럼 처리한다.
Widget itemTextField(IconData icon, TextEditingController ctr, String name) {
return Container(
// A fixed-height child.
color: Colors.white, // Yellow
// height: 50.0,
alignment: Alignment.center,
padding: const EdgeInsets.fromLTRB(50, 0, 50, 0),
child: TextFormField(
controller: ctr,
decoration: InputDecoration(
prefixIcon: Icon(
icon,
color: primaryTextColor,
),
// labelText: '이름',
hintText: name),
));
}
- 새로 만든 itemTextField 위젯에 필요한 항목을 넣고 나열한다.
- 별도 컨트롤로를 class 상단에 선언한다.
TextEditingController pet_name = TextEditingController();
TextEditingController pet_birthday = TextEditingController();
TextEditingController pet_gender = TextEditingController();
TextEditingController pet_breed = TextEditingController();
TextEditingController pet_chip = TextEditingController();
- 만들어진 최종 소스
import 'dart:ffi';
import 'package:petbutler/pages/memo_page.dart';
import 'package:petbutler/utils/database_helper.dart';
import 'package:petbutler/views/htmlView.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class PetProfile extends StatefulWidget {
const PetProfile({Key? key}) : super(key: key);
@override
State<PetProfile> createState() => _HomeState();
}
class _HomeState extends State<PetProfile> with SingleTickerProviderStateMixin {
late AnimationController controller;
@override
void initState() {
controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 5),
)..addListener(() {
setState(() {});
});
// controller.repeat(reverse: true);
users = this.getUsersLIst();
super.initState();
}
Future<List<Auction3>> getUsersLIst() async {
return await DatabaseHandler().getAllUsers();
}
late Future<List<Auction3>> users;
int _count = 0;
final descTextStyle = TextStyle(
color: Colors.black,
fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 18,
height: 2,
);
var _visable = false;
var secondaryTextColor = Colors.white;
var primaryTextColor = Colors.black;
late PickedFile _imageFile;
File? avatarImageFile;
bool isLoading = false;
TextEditingController pet_name = TextEditingController();
TextEditingController pet_birthday = TextEditingController();
TextEditingController pet_gender = TextEditingController();
TextEditingController pet_breed = TextEditingController();
TextEditingController pet_chip = TextEditingController();
// 카메라/갤러리에서 사진 가져올 때 사용함 (image_picker)
final ImagePicker _picker = ImagePicker();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
bottomOpacity: 0.0,
elevation: 0.0,
//title: const Text('경매수익률분석'),
leading: IconButton(
icon: const Icon(Icons.add_a_photo),
tooltip: '사진등록',
onPressed: () => {},
),
actions: <Widget>[
Center(
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 8, 0),
child: InkWell(
onTap: () {},
child: TextButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
return Color.fromARGB(255, 33, 31,
31); // Defer to the widget's default.
}),
),
onPressed: () async {},
child: const Text(
'등록',
style: TextStyle(
color: Color.fromARGB(255, 248, 246, 246),
),
)),
),
),
),
],
),
// We're using a Builder here so we have a context that is below the Scaffold
// to allow calling Scaffold.of(context) so we can show a snackbar.
body: Builder(builder: (BuildContext context) {
const labelTextStyle =
TextStyle(fontSize: 10, fontStyle: FontStyle.italic);
DatabaseHandler dbHandler = DatabaseHandler();
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder:
(BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.minHeight,
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
const SizedBox(height: 20),
profileImage(),
const SizedBox(height: 20),
const Text('우리집 반려견 사진을 등록해주세요',
style: TextStyle(
color: Colors.black54,
fontWeight: FontWeight.normal,
fontFamily: 'S-Core',
fontSize: 20.0)),
itemTextField(Icons.border_color, pet_name, "이름"),
itemTextField(Icons.hub, pet_gender, "성별"),
itemTextField(Icons.cake, pet_birthday, "생일"),
itemTextField(Icons.share, pet_breed, "견종"),
itemTextField(Icons.local_offer, pet_chip, "외장칩"),
Container(
// A fixed-height child.
color: Color.fromARGB(255, 251, 92, 92), // Yellow
height: 30.0,
alignment: Alignment.center,
padding: const EdgeInsets.all(5),
child: const Text(' 펫 리스트 ',
style: TextStyle(
color: Colors.white,
)),
),
SizedBox(
height: 400,
child: FutureBuilder(
future: users,
builder: (context, snapshot) {
if (snapshot.hasData) {
var usersList =
snapshot.data as List<Auction3>;
return ListView.builder(
itemCount: usersList.length,
itemBuilder:
(BuildContext context, int index) {
Auction3 user = usersList[index];
return ListTile(
title: TextButton(
onPressed: () {},
child: Align(
alignment:
Alignment.centerLeft,
child: Text(
textAlign: TextAlign.left,
user.sbjt.toString() +
" (" +
user.aucM1.toString() +
")",
style: TextStyle(
color: Colors.black54),
))),
trailing: IconButton(
onPressed: () {
_delete(context, dbHandler, user);
},
icon: const Icon(Icons.delete),
),
);
});
} else {
return CircularProgressIndicator(
value: controller.lowerBound,
semanticsLabel:
'Circular progress indicator',
);
}
}),
),
],
),
),
);
},
),
);
}));
}
bool _isShown = true;
void _delete(BuildContext context, dbHandler, user) {
showCupertinoDialog(
context: context,
builder: (BuildContext ctx) {
return CupertinoAlertDialog(
title: const Text('삭제하기'),
content: const Text('해당물건을 삭제하시겠습니까?'),
actions: [
// The "Yes" button
CupertinoDialogAction(
onPressed: () {
dbHandler.deleteUser(user.aucNo);
Navigator.of(context).pop();
initState();
setState(() {});
},
child: const Text('삭제'),
isDefaultAction: true,
isDestructiveAction: true,
),
// The "No" button
CupertinoDialogAction(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('취소'),
isDefaultAction: false,
isDestructiveAction: false,
)
],
);
});
}
Widget profileImage() {
ImageProvider aa;
return Center(
child: Stack(
children: <Widget>[
avatarImageFile == null
? CircleAvatar(
radius: 80,
backgroundImage:
AssetImage('images/pet/intro/intro_login2.png'))
: CircleAvatar(
radius: 80,
backgroundImage: FileImage(avatarImageFile!),
),
Positioned(
bottom: 20,
right: 20,
child: InkWell(
onTap: () async {
final pickedFile =
await _picker.getImage(source: ImageSource.camera);
File? image;
if (pickedFile != null) {
image = File(pickedFile.path);
}
if (image != null) {
setState(() {
avatarImageFile = image;
isLoading = true;
});
// uploadFile();
}
/*showModalBottomSheet(
context: context, builder: ((builder) => bottomSheet()));
*/
},
child: Icon(
Icons.photo_camera,
color: secondaryTextColor,
size: 40,
),
))
],
),
);
}
Widget itemTextField(IconData icon, TextEditingController ctr, String name) {
return Container(
// A fixed-height child.
color: Colors.white, // Yellow
// height: 50.0,
alignment: Alignment.center,
padding: const EdgeInsets.fromLTRB(50, 0, 50, 0),
child: TextFormField(
controller: ctr,
decoration: InputDecoration(
prefixIcon: Icon(
icon,
color: primaryTextColor,
),
// labelText: '이름',
hintText: name),
));
}
Widget bottomSheet() {
return Container(
height: 100,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child: Column(
children: <Widget>[
Text(
'Choose Profile photo',
style: TextStyle(
fontSize: 20,
),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.camera,
size: 50,
),
onPressed: () {
takePhoto(ImageSource.camera);
},
),
IconButton(
icon: Icon(
Icons.photo_library,
size: 50,
),
onPressed: () {
takePhoto(ImageSource.gallery);
})
],
)
],
));
}
takePhoto(ImageSource source) async {
final pickedFile = await _picker.getImage(source: source);
setState(() {});
}
double nullChangeValue(String editText) {
try {
return double.parse(editText);
} on Exception {
return 0.0;
}
}
String doubleToString(double d) {
return chage000(d);
}
String doubleNotIntToString(double d) {
// d=Math.round(d*100/11)/100;
return (d.toString());
}
double nullChangeDoubleValue(String editText) {
return double.parse(editText);
}
String chage000(double str) {
// Thousand-separator
var f = NumberFormat('###,###,###,###.##');
return f.format(str);
}
}
Widget perNumber(String str, labelTextStyle, TextEditingController value) =>
Row(
children: <Widget>[
Container(
margin: EdgeInsets.all(5),
//padding: EdgeInsets.fromLTRB(10, 20, 30, 40),
child: SizedBox(height: 30, width: 100, child: Text(str)),
),
const SizedBox(
height: 20,
width: 10,
//child: Container(color: Colors.blue),
), //container
SizedBox(
height: 30,
width: 150,
child: TextField(
//obscureText: true,
controller: value,
keyboardType: TextInputType.number,
// inputFormatters: [FilteringTextInputFormatter.],
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: '금액',
labelStyle: labelTextStyle,
),
),
),
//container
], //widget
);
- 다음은 서버에 데이터를 올리는 작업을 해보겠다...
728x90
반응형
'펫버틀러' 카테고리의 다른 글
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 7 일차 (강아지 프로필 carousel_slider 페이지적용) (2) | 2022.12.26 |
---|---|
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 6 일차 (강아지 프로필 등록2 서버연동) (2) | 2022.12.25 |
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 4 일차 (구글 로그인 등록) (6) | 2022.12.24 |
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 3 일차 (FIREBASE 등록) (0) | 2022.12.23 |
[펫버틀러] 반려동물 고민상담 앱 - 개발 2일차 (인트로페이지INTRO page) (0) | 2022.12.23 |
Comments