Notice
Recent Posts
Recent Comments
Link
250x250
«   2025/01   »
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 more
Archives
Today
Total
관리 메뉴

혼자서 앱 만드는 개발자 함께하는 AI 세상

[펫버틀러] 반려 동물 고민 상담 앱 - 개발 5 일차 (강아지 프로필 등록) 본문

펫버틀러

[펫버틀러] 반려 동물 고민 상담 앱 - 개발 5 일차 (강아지 프로필 등록)

혼앱사 2022. 12. 24. 21:56
반응형
  • 이전 구글로그인 작업 후 이번 차수에서 프로필 등록 작업을 진행 해보겠다.
  • 프로필은 간단한 소개글 함께 아이콘 이미지를 추가 할 수 있도록 개발해 본다.

  • 위에서 첫 번째 페이지를 먼저 디자인 하기로 했다.

프로필 등록화면 작업

  • 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
반응형
Comments