본문 바로가기

Flutter/12 Clone 'Used Goods app'

[Flutter] Clone - 당근마켓11(Address - ListView)

이번에 검색결과(도로명 주소)를 ListView 형식으로 화면에 표시해보겠습니다.

개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1

 

 

 

화면은 아래와 같습니다. 검색창에 단어를 입력하고 엔터 클릭시 검색결과 반환.

현재는 최대 100건만 표시하였다.

 

 

 

./src/screens/start/address_service.dart - 함수의 리턴 타입을 모델링 타입으로 변경함

 

Future<AddressModel> searchAddressByStr(String text) async {
  final formData = {
    'confmKey': jusoKey,
    'currentPage': '1',
    'countPerPage': '100',
    'keyword': text,
    'resultType': 'json',
  };

  var resp = await Dio()
      .get('http://www.juso.go.kr/addrlink/addrLinkApi.do',
          queryParameters: formData)
      .catchError((e) {
    logger.e(e.message);
  });

  AddressModel addressModel = AddressModel.fromJson(resp.data);

  debugPrint(addressModel.results.common.toString());
  debugPrint(addressModel.results.juso[0].toString());
  // logger.d(resp.data is Map);

  return addressModel;
}

 

 

./src/screens/start/address_page.dart - 함수의 리턴 타입을 모델링 타입으로 변경함

 

import 'package:extended_image/extended_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import '../../constants/common_size.dart';
import '../../models/address_model.dart';
import 'address_service.dart';

class AddressPage extends StatefulWidget {
  const AddressPage({Key? key}) : super(key: key);

  @override
  State<AddressPage> createState() => _AddressPageState();
}

class _AddressPageState extends State<AddressPage> {
  final TextEditingController _addressController = TextEditingController();

// 주소모델 객체 생성
  AddressModel? _addressModel;

  final _isGettingLocation = false;

  @override
  void dispose() {
    _addressController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    debugPrint(">>> build from AddressPage");

    return SafeArea(
      // padding 대신에 minimum 으로 설정 가능, 위/아래 글씨가 잘리는것도 방지하자
      minimum: const EdgeInsets.symmetric(horizontal: padding_16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          TextFormField(
            controller: _addressController,
// 키보드 입력후 엔터 버튼 클릭시 검색 시작
            onFieldSubmitted: onClickTextField,
            decoration: InputDecoration(
              prefixIcon: const Icon(
                Icons.search,
                color: Colors.grey,
              ),
              // 아이콘 주변 공간을 조절 가능
              prefixIconConstraints:
                  const BoxConstraints(minWidth: 24, maxHeight: 24),
              // 문자 입력후 밑줄이 생기게 설정
              border: const UnderlineInputBorder(
                  borderSide: BorderSide(color: Colors.grey)),
              // focusedBorder: const UnderlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
              hintText: '도로명으로 검색...',
              hintStyle: TextStyle(color: Theme.of(context).hintColor),
            ),
          ),
          const SizedBox(height: padding_08),
          TextButton.icon(
            label: Text(
              _isGettingLocation ? '위치 찾는중 ~~' : '현재위치 찾기',
              style: Theme.of(context).textTheme.button,
            ),
            onPressed: () {},
            icon: _isGettingLocation
                ? const SizedBox(
                    height: 20,
                    width: 20,
                    child: CircularProgressIndicator(color: Colors.white))
                : const Icon(CupertinoIcons.compass,
                    color: Colors.white, size: 20),
          ),
          Expanded(
            child: ListView.builder(
              padding: const EdgeInsets.symmetric(vertical: padding_16),
// 아이템 개수 설정
              itemCount: (_addressModel == null)
                  ? 0
                  : _addressModel!.results.juso.length,
              itemBuilder: (context, index) {

                if (_addressModel == null) {
                  return Container();
                }
                var subAddress = _addressModel!.results.juso[index].jibunAddr.split(' ');
                debugPrint('[$index]  ${subAddress.toString()}');
                return ListTile(
// 도로명 주소 표시
                  title: Text(_addressModel!.results.juso[index].roadAddrPart1),
// 지번 주소 표시
                  subtitle: Text('${subAddress[2]} ${subAddress[3]}'),
                );
              },
            ),
          ),
        ],
      ),
    );
  }


// 주소 검색 함수 호출
  void onClickTextField(text) async {
    _addressModel = await AddressService().searchAddressByStr(text);
    setState(() {});
  }

}