프로젝트하면서 배운거(1)

wjdguseya_0880·2024년 8월 4일
0

프로젝트 하면서 새롭게 배운거나 알고는 있었지만 제대로는 알지 못했던거 정리

1. SizedBox.shrink(),

처음에는 공간에 높이가 없다가


이렇게 내용이 있을때 높이를 따로 줘야하는데 이거를 구현할때 처음해보는거라
고민을 많이했다.

 Container(
            width: 340.w,
            height: addDiseaseType.isNotEmpty ? 36.h : 0,
            margin: const EdgeInsets.fromLTRB(12, 0, 12, 0),
            child: addDiseaseType.isNotEmpty
                ? ListView.builder(
                    scrollDirection: Axis.horizontal,
                    itemCount: addDiseaseType.length,
                    itemBuilder: (context, index) {
                      return Padding(
                        padding: const EdgeInsets.fromLTRB(0, 0, 8, 0),
                        child: Chip(
                          labelStyle: Black(12.sp, FontWeight.w500),
                          side: const BorderSide(color: Colors.transparent),
                          backgroundColor: Colors.white,
                          label: Text(addDiseaseType[index]),
                          onDeleted: () {
                            _removeDisease(index);
                          },
                          deleteIcon:
                              Image.asset('assets/image_asset/edit/close.png'),
                        ),
                      );
                    },
                  )
                : const SizedBox.shrink(),
          ),

그러던 중 SizedBox.shrink()를 알게 됐는데 이것은 빈 위젯이다
처음에는 빈 위젯을 보여주고 나중에 높이를 36이 나오도록 했다.




2. custom위젯 만들기


class CircleContainer extends StatelessWidget {
  final double width;
  final double height;
  const CircleContainer(
      {super.key, this.width = double.infinity, this.height = double.infinity});

  @override
  Widget build(BuildContext context) {
    return GlassContainer(
      width: width,
      height: height,
      color: Colors.white.withOpacity(0.8),
      gradient: LinearGradient(
        colors: [
          Colors.white.withOpacity(0.8),
          Colors.white,
        ],
        begin: Alignment.topLeft,
        end: Alignment.bottomRight,
      ),
      borderGradient: LinearGradient(
        colors: [
          Colors.white.withOpacity(0.5),
          Colors.white.withOpacity(0.2),
          Colors.white.withOpacity(0.2),
          Colors.white.withOpacity(0.2),
        ],
        begin: Alignment.topLeft,
        end: Alignment.bottomRight,
        stops: [0.10, 0.30, 0.40, 0.0],
      ),
      blur: 20,
      borderRadius: BorderRadius.circular(100),
      borderWidth: 1.0,
      elevation: 10.0,
      boxShadow: [
        BoxShadow(
          color: Color(0x26000000),
          blurRadius: 4,
          offset: Offset(0, 4),
          spreadRadius: 0,
        )
      ],
    );
  }
}

final double width ,final double height
이런식으로 해주면 높이와 넓이만 바꿀 수 있는 공통 위젯으로 만들 수 있다.

[탭바]

class CustomTabbar extends StatefulWidget {
  final TabController tabController;
  final List<Widget> tabView;
  final String? bannerImage;

  const CustomTabbar({
    super.key,
    required this.tabController,
    required this.tabView,
    this.bannerImage,
  });

  @override
  State<CustomTabbar> createState() => _CustomTabbarState();
}

class _CustomTabbarState extends State<CustomTabbar> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TabBar(
          dividerHeight: 0,
          unselectedLabelStyle: whiteOpacity(14.sp, FontWeight.w600),
          indicatorColor: Colors.white,
          indicatorSize: TabBarIndicatorSize.values.first,
          indicatorPadding: EdgeInsets.symmetric(horizontal: 8),
          indicatorWeight: 2,
          labelStyle: const TextStyle(
              fontSize: 14,
              fontWeight: FontWeight.w600,
              color: Colors.white,
              fontFamily: 'Pretendard'),
          labelColor: Colors.white,
          controller: widget.tabController,
          tabs: [
            Container(
              height: 48.h,
              alignment: Alignment.center,
              child: Text(
                '정보',
              ),
            ),
            Container(
              height: 48.h,
              alignment: Alignment.center,
              child: Text(
                '거래',
              ),
            ),
            Container(
              height: 48.h,
              alignment: Alignment.center,
              child: Text(
                '모임',
              ),
            ),
          ],
        ),
        if (widget.bannerImage != null)
          Image.asset(
            widget.bannerImage!,
          ),
        Expanded(
            child: TabBarView(
                controller: widget.tabController, children: widget.tabView))
      ],
    );
  }
}



3. 파이어 스토어 데이터 불러오기, 삭제

 Future<List<Map<String, dynamic>>> getMemos() async {
    try {
      QuerySnapshot snapshot = await firestore
          .collection('Memo')
          .orderBy('timestamp', descending: true)
          .get();
      List<Map<String, dynamic>> memos = snapshot.docs.map((doc) {
        Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
        print('Fetched memo: $data');
        return {
          'id': doc.id,
          'content': data['content'],
          'timestamp': (data['timestamp'] as Timestamp).toDate(),
        };
      }).toList();
      print('Fetched memos: $memos');
      return memos;
    } catch (e) {
      // print('Error fetching memos: $e');
      return [];
    }
  }

데이터 형식을 불러와서 데이터 내용과 타임스탬프를 가져와서
데이터의 내용이 작성한 순서대로 업데이트 되도록 orderBy를 사용했다.

 Future<void> deletedMemo(String docId) async {
    if (docId.isEmpty) {
      Get.snackbar('삭제 실패', '문서 ID가 비어 있습니다.');
      return;
    }
    try {
      await firestore.collection('Memo').doc(docId).delete();
      Get.back();
      Get.snackbar('삭제 성공', '메모가 삭제되었습니다.');
    } catch (e) {
      print('Error deleting memo: $e');
      Get.snackbar('삭제 실패', '메모를 삭제하는 중 오류가 발생했습니다.');
    }
  }

파이어스토어에 문서를 삭제하려면 고유id값이 필요한데 자동으로 생기는 고유id값 이것을 입력해주면 삭제가 된다.

하지만 어플을 사용하면서 이것을 사용자가 할수 없으니 방법을 찾아야한다.




4. 파이어 스토어에 이미지 저장하기

  File? _image; //선택한 이미지 파일 저장
  final ImagePicker picker = ImagePicker();//이미지 선택 처리
  String _PetProfileImag = 
      'assets/image_asset/pet_upload/animal_profile (2).png';  //프로필의 기본이미지
 Future<void> _pickImage(ImageSource source) async {
    final pickedFile = await picker.pickImage(source: source);
    if (pickedFile != null) {
      setState(() {
        _image = File(pickedFile.path);
      });
      //스토리지에 먼저 사진 업로드 하는 부분
      final storageRef = FirebaseStorage.instance
          .ref() //시작점
          .child('pet_images/${DateTime.now().toIso8601String()}');
      final uploadTask = storageRef.putFile(_image!);

      uploadTask.whenComplete(() async {
        try {
          final imageUrl = await storageRef.getDownloadURL();
          // 이미지 저장!
          await FirebaseFirestore.instance.collection('pet_profiles').add({
            'image_url': imageUrl,
          });
          widget.onChanged(imageUrl); // 새로운 URL로 호출
        } catch (e) {
          print('Error uploading image: $e');
        }
      });
    }
  }

_pickImage는 지정된 카메라나 갤러이에서 이미지를 선택해준다.

 final storageRef = FirebaseStorage.instance
          .ref() //시작점
          .child('pet_images/${DateTime.now().toIso8601String()}');
      final uploadTask = storageRef.putFile(_image!);

이미지 URL을 파이어베이스 파이어스토어에 저장을 해준다.

GestureDetector(
                    onTap: () {
                      setState(() {
                        _PetProfileImag =
                            'assets/image_asset/pet_upload/animal_profile (4).png';
                        widget.onChanged(_PetProfileImag);
                      });
                    },
                    child: ProfileCard(
                      petName: '물고기',
                      imgUrl:
                          'assets/image_asset/pet_upload/animal_select (6).png',
                    ),
                  ),

새 이미지경로로 _PetProfileImag 호출되게 함

profile
플러터 공부 기록일지

0개의 댓글