ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 28일차 딕셔너리 앱 만들기
    카테고리 없음 2023. 3. 5. 20:25
    1. 다음의 공개된 API를 분석하고, 클래스를 활용하여 적용 후 딕셔너리 앱을 다음과 같이 만드시오.

     

    • 반드시 Dict 클래스를 만들고 Serialization을 진행할 수 있도록 하시오.
      • 필요한 요소만을 클래스에 적용하는 것은 허용되지만, 최대한 많은 데이터를 가져올 수 있도록 한다.
    • 이 때, 만약 검색어가 존재하지 않는 단어로 서버에서 정상적인 응답을 못받았을 경우는 아무 것도 출력되지 않도록 한다.
    • 검색어를 입력하고 엔터를 누르면 (TextField의 onSubmitted) 주어진 API를 통해 검색하도록 한다.
      • 이 때, 결과는 아래에 커스텀 위젯을 최대한 활용하여 보여줄 수 있도록한다.
      • 커스텀 위젯은 최대한 분할되어 있을수록 좋다.
        • 예) MeaningCard..
    • 다음의 제공되는 코드를 사용할 수 있다.
      • lib/page/main_page.dart
      •  
    // 추가 코드를 작성할 것. 본 소스는 디자인만 작성되어 있으며
    // 이 기본 틀을 통하여 과제에 필요한 소스코드를 추가적으로 구현할 것.
    import 'package:flutter/material.dart';
    
    class MainPage extends StatefulWidget {
      const MainPage({super.key});
    
      @override
      State<MainPage> createState() => _MainPageState();
    }
    
    class _MainPageState extends State<MainPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Dictionary App'),
            elevation: 0,
            centerTitle: false,
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Row(
                  children: [
                    Expanded(
                      child: Padding(
                        padding: const EdgeInsets.all(16),
                        child: TextField(
                          decoration: const InputDecoration(
                            hintText: "Search",
                            suffixIcon: Icon(Icons.search),
                            enabledBorder: OutlineInputBorder(
                              borderSide: BorderSide(color: Colors.white),
                            ),
                            focusedBorder: OutlineInputBorder(
                              borderSide: BorderSide(color: Colors.white),
                            ),
                          ),
                          onSubmitted: (value) {},
                        ),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        );
      }
    }

     

    lib/model/dict.dart

    import 'package:dictionary_app/model/license.dart';
    import 'package:dictionary_app/model/meaning.dart';
    import 'package:dictionary_app/model/phonetic.dart';
    
    class Dict {
      String word;
      String? phonetic;
      List<Phonetic> phonetics;
      List<Meaning> meanings;
      License license;
      List<String> sourceUrls;
    
      Dict(
          {required this.word,
          required this.phonetic,
          required this.phonetics,
          required this.meanings,
          required this.license,
          required this.sourceUrls});
    
      factory Dict.fromMap(Map<String, dynamic> map) {
        return Dict(
            word: map['word'],
            phonetic: map['phonetic'],
            phonetics: List<Phonetic>.from(
                map['phonetics'].map((e) => Phonetic.fromMap(e))),
            meanings:
                List<Meaning>.from(map['meanings'].map((e) => Meaning.fromMap(e))),
            license: License.fromMap(map['license']),
            sourceUrls: List<String>.from(map['sourceUrls']));
      }
    }

    lib/model/definition.dart

    class Definition {
      String definition;
      List<String> synonyms;
      List<String> antonyms;
      String? example;
    
      Definition(
          {required this.definition,
          required this.synonyms,
          required this.antonyms,
          required this.example});
    
      factory Definition.fromMap(Map<String, dynamic> map) {
        return Definition(
            definition: map['definition'],
            synonyms: List<String>.from(map['synonyms']),
            antonyms: List<String>.from(map['antonyms']),
            example: map['example']);
      }
    }

    lib/model/meaning.dart

    import 'package:dictionary_app/model/definition.dart';
    
    class Meaning {
      String partOfSpeech;
      List<Definition> definitions;
      List<String> synonyms;
      List<String> antonyms;
    
      Meaning(
          {required this.partOfSpeech,
          required this.definitions,
          required this.synonyms,
          required this.antonyms});
    
      factory Meaning.fromMap(Map<String, dynamic> map) {
        return Meaning(
            partOfSpeech: map['partOfSpeech'],
            definitions: List<Definition>.from(
                map['definitions'].map((e) => Definition.fromMap(e))),
            synonyms: List<String>.from(map['synonyms']),
            antonyms: List<String>.from(map['antonyms']));
      }
    }

    lib/model/phonetic.dart

    import 'package:dictionary_app/model/license.dart';
    
    class Phonetic {
      String text;
      String? audio;
      String? sourceUrl;
      License? license;
    
      Phonetic(
          {required this.text,
          required this.audio,
          required this.sourceUrl,
          required this.license});
    
      factory Phonetic.fromMap(Map<String, dynamic> map) {
        return Phonetic(
          text: map['text'],
          audio: map['audio'],
          sourceUrl: map['sourceUrl'],
          license: map['license'] != null ? License.fromMap(map['license']) : null,
        );
      }
    }

    lib/model/license.dart

    class License {
      String name;
      String url;
    
      License({required this.name, required this.url});
    
      factory License.fromMap(Map<String, dynamic> map) {
        return License(name: map['name'], url: map['url']);
      }
    }

    main.dart

    import 'package:dictionary_app/page/mainpage.dart';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData.dark(),
          home: MainPage(),
        );
      }
    }

     

    mainpage.dart

    // ignore_for_file: prefer_const_constructors, unused_local_variable
    
    import 'package:dictionary_app/model/dict.dart';
    import 'package:dictionary_app/widget/dict_card.dart';
    import 'package:dictionary_app/widget/meaningcard.dart';
    import 'package:flutter/material.dart';
    import 'package:dio/dio.dart';
    
    class MainPage extends StatefulWidget {
      const MainPage({super.key});
    
      @override
      State<MainPage> createState() => _MainPageState();
    }
    
    class _MainPageState extends State<MainPage> {
      Dict? dict;
      Dio dio = Dio();
    
      getData(String word) async {
        var url = 'https://api.dictionaryapi.dev/api/v2/entries/en/';
        try {
          var res = await dio.get(url + word);
          var data = res.data.first;
          dict = Dict.fromMap(data);
          setState(() {});
        } catch (e) {
          dict = null;
          setState(() {});
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.white12,
            elevation: 0,
            title: Text('Dictionary App'),
          ),
          body: Center(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Row(
                  children: [
                    Expanded(
                      child: Padding(
                        padding: const EdgeInsets.all(16),
                        child: TextField(
                          decoration: const InputDecoration(
                            hintText: "Search",
                            suffixIcon: Icon(Icons.search),
                            enabledBorder: OutlineInputBorder(
                              borderSide: BorderSide(color: Colors.white),
                            ),
                            focusedBorder: OutlineInputBorder(
                              borderSide: BorderSide(color: Colors.white),
                            ),
                          ),
                          onSubmitted: (value) {
                            getData(value); //네트워크 단어 요청
                          },
                        ),
                      ),
                    ),
                  ],
                ),
                Divider(
                  thickness: 1,
                ),
                if (dict != null)
                  Expanded(
                      child: SingleChildScrollView(
                          physics: BouncingScrollPhysics(),
                          child: DictCard(dict: dict!))),
              ],
            ),
          ),
        );
      }
    }

    dict.card.dart

    import 'package:dictionary_app/model/dict.dart';
    import 'package:dictionary_app/widget/meaningcard.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter/src/widgets/container.dart';
    import 'package:flutter/src/widgets/framework.dart';
    
    class DictCard extends StatelessWidget {
      const DictCard({super.key, required this.dict});
      final Dict dict;
      @override
      Widget build(BuildContext context) {
        return Card(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              children: [
                Text(
                  dict.word,
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24),
                ),
                Divider(),
                ListView.builder(
                    shrinkWrap: true,
                    physics: NeverScrollableScrollPhysics(),
                    itemCount: dict.meanings.length,
                    itemBuilder: ((context, index) {
                      return MeaningCard(meaning: dict.meanings[index]);
                    }))
              ],
            ),
          ),
        );
      }
    }

     

    meaningcard.dart

    import 'package:dictionary_app/model/meaning.dart';
    import 'package:flutter/material.dart';
    
    class MeaningCard extends StatelessWidget {
      const MeaningCard({super.key, required this.meaning});
      final Meaning meaning;
    
      @override
      Widget build(BuildContext context) {
        return Card(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                meaning.partOfSpeech,
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              ListView.builder(
                shrinkWrap: true,
                physics: NeverScrollableScrollPhysics(),
                itemCount: meaning.definitions.length,
                itemBuilder: ((context, index) => ListTile(
                      title: Text(meaning.definitions[index].definition),
                    )),
              ),
            ],
          ),
        );
      }
    }

    클래스만드는거에 오류난 부분이 없는거 확인하고 UI를 만들었는데 결과가 안나와서 헤매다가 강의보고했는데 실수로 빌드안에getdata를 만들었던걸 깨달아버림..

Designed by Tistory.