몇 일전 스타트업 빙글의 테스트를 보았다.
어찌어찌 요구사항은 모두 만족하였지만, 맘 한구석이 무거웠다.
역시나 역시나 열정만큼 따라오지 않는 실력이 아쉬웠다.
그래서 안드로이드 개발력(?)에 대해 피드백도 받고싶고, 한걸음 성숙한 개발자가 되고 싶어 기술 블로그를 시작 하게 되었다.
오늘은 첫 포스팅 다운 포스팅을 하려고 한다.(세상에서 제일 못하는 것들 중 하나가 글쓰기다... 아아 물론 개발도 포함된다^ㅠ^ 쓰다보면 늘지 않을까 싶다)
필자는 주말마다 한남동에 가서 안드로이드 개발을 배우고 있다.(사실 프로젝트지만 배움의 느낌이 더크다.)
개발자는 모두 5명으로 3명은 안드로이드, 2명은 서버이다.
안드로이드 진영은 네이버 웹툰 개발자, 카카오 개발자, 그리고 백수인 나(눈물이 흐른다.) 서버 진영은 잘 나가는 스타트업 서버 개발자, 앞으로 하나 금융 그룹에서 일하게 될 학교 동기(현재는 회사의 교육기간 중에 있다)이다.
개발을 하는 도중 두개의 액티비티에서 사용되게 될 커스텀 뷰를 만들어 달라는 요구사항이 도착했다-
항상 가져다만 썼지, 만드는 거에는 전혀 신경을 써보지 못해서 머리가 머엉 해졌다. 뭐가 되었건 키보드를 누르기 시작했다.
위 사진의 기획처럼 네모칸 있는 부분 커스텀 뷰를 만들어
최대 2개 지역을 선택하는 부분에 적용 하면 finish...
(결국 지역 api 를 통해 네모 스피너 두개가 하나같이 움직이는 뷰를 만들어 뿌려주면 되는 일이다)
아는 지식이 없어 일단은 데이터를 받아오는 부분 부터 완성 시켰다.
팀원들과 상의했을때 지역과 세부지역을 메모리에 가지고 있는 쪽으로 의견이 정해졌다.
서버 쪽 데이터를 한번 확인하고 일단 시작!
앱 실행시에 데이터를 물고 있을수 있게 Appication을 상속받은 클래스에 코딩했다.
참고로 소스중 나머지 부분은 다 지워버렸다.(코드가 너무나도 길어질까봐...)
public class AppApplication extends Application {
private static AppApplication instance;
@Override
public void onCreate() {
super.onCreate();
this.instance = this;
inits();
}
private void inits() {
Ln.init(this);
NetworkState.init(this);
initFacebook();
initRealm();/* 요기부분 */
AddressServiceManager.refreshAddress();
}
}
public static void refreshAddress() {
getsFirstAddress().subscribe(
new EmptySubscriber<Response<BaseResponse<List<AddressModel>>>>());
}
private static List<FirstAddress> sFirstAddress = new ArrayList<>();
private static Map<String, List<AddressModel.SecondAddress>> sSecondAddress = new HashMap<String, List<AddressModel.SecondAddress>>();
public static final Observable<Response<BaseResponse<List<AddressModel>>>> getsFirstAddress() {
return SERVICE.getFirstAddress()
.subscribeOn(ServiceHelper.getPriorityScheduler(Priority.MEDIUM))
.lift(new ServiceErrorChecker<>(new BaseServiceErrorChecker<List<AddressModel>>()))
.map(new Func1<Response<BaseResponse<List<AddressModel>>>, Response<BaseResponse<List<AddressModel>>>>() {
@Override
public Response<BaseResponse<List<AddressModel>>> call(Response<BaseResponse<List<AddressModel>>> baseResponseResponse) {
sFirstAddress.clear();
sSecondAddress.clear();
for (AddressModel addressModel : baseResponseResponse.body().mResult) {
sFirstAddress.add(new FirstAddress(addressModel.mId, addressModel.mAddressName));
sSecondAddress.put(addressModel.mAddressName, addressModel.mSecondAddress);
}
return baseResponseResponse;
}
});
}
api model은 http://www.jsonschema2pojo.org/을 통해 해결한뒤,(넘나 편함..)
map 자료 구조를 이용해 지역 이름을 기준으로 세부 지역 이름 셋팅하였다.
데이터를 받아오는 부분은 완성 이제 정말 뷰를 만드는것만 남았다.
일단은 xml을 완성 시켰다.
LinearLayout 안에 스피너 위치 시키고 1대1로 비율 준게 끝이다..
본격적으로 클래스를 만들어보자
LocalSelectView로 네이밍 하고 LinearLayout을 상속받았다. 그리고 필요한 함수들을 Alt + insert를 통해 모두 임포트했다.
/**
* Created by kinamare on 2017-04-29.
* @author kinamare
* 지역 선택 뷰
*/
public class LocalSelectView extends LinearLayout {
private static final String TAG = LocalSelectView.class.getSimpleName();
@BindView(R.id.local_spinner) AppCompatSpinner local_spinner;
@BindView(R.id.local_detail_spinner) AppCompatSpinner local_detail_spinner;
public LocalSelectView(Context context) {
this(context, null);
}
public LocalSelectView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public LocalSelectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
View v = LayoutInflater.from(context).inflate(R.layout.local_select_view, this, true);
ButterKnife.bind(this,v);
}
버터나이프로 필요한 뷰들은 연결 시켜주고, 본격적으로 스피너를 구현 해보자.
커스텀 아답터로 구현해야 했지만 테스트 용도로 안드로이드 기본 아답터를 사용하였다.
private static final int BASEVALUE = 0;
private List<AddressModel.SecondAddress> getSecondAddress;
private List<FirstAddress> sFirstAddress;
를 선언 해주고
겟터를 만들어 메모리에 있는 지역, 지역세부 목록들을 가지고 온다.
private void initFirstSpinner() {
sFirstAddress = AddressServiceManager.getFirstAddressList();
String[] firstArray = new String[sFirstAddress.size()];
for (int i =0; i < sFirstAddress.size(); i++){
firstArray[i] = sFirstAddress.get(i).mName;
}
ArrayAdapter localAdapter = new ArrayAdapter(
getApplicationContext(), R.layout.custom_spinner_item,firstArray);
localAdapter.setDropDownViewResource(
R.layout.custom_spinner_dropdown_item);
local_spinner.setAdapter(localAdapter);
local_spinner.setPrompt("지역 설정");
local_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
initSecondSpinner(position);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
private void initSecondSpinner(int position) {
getSecondAddress = AddressServiceManager.getSecondAddress(sFirstAddress.get(position).mName);
String[] secondArray = new String[getSecondAddress.size()];
for (int i =0; i < getSecondAddress.size(); i++){
secondArray[i] = getSecondAddress.get(i).mAddressName;
}
ArrayAdapter localAdapter = new ArrayAdapter(
getApplicationContext(), R.layout.custom_spinner_item, secondArray);
localAdapter.setDropDownViewResource(
R.layout.custom_spinner_dropdown_item);
local_detail_spinner.setAdapter(localAdapter);
local_detail_spinner.setPrompt("지역 세부 설정");
}
완성 시켰다. 생각나는 로직이 없어서 처음에는 배열에 있는 처음 값들을 세팅해줬다
public LocalSelectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
View v = LayoutInflater.from(context).inflate(R.layout.local_select_view, this, true);
ButterKnife.bind(this,v);
initFirstSpinner();
initSecondSpinner(BASEVALUE);
}
생성자에 넣어주면 완성이 된거같으니 써본다.
<LinearLayout
android:layout_marginTop="20dp"
android:weightSum="5"
android:id="@+id/popup_filter_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v7.widget.AppCompatTextView
android:layout_weight="1"
android:text="봉사지역"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
<com.vocketlist.android.view.LocalSelectView
android:id="@+id/local_select_view"
android:layout_weight="4"
android:layout_width="0dp"
android:layout_height="wrap_content">
</com.vocketlist.android.view.LocalSelectView>
</LinearLayout>
다행히 잘 보이는 거 같다.
이제 실행 고고
어우 다행히 잘 작동한다....
이제 심미적 요소를 더하는 것만 남았다!
'Android' 카테고리의 다른 글
Grab, Kakao T 같은 모빌리티 샘플 앱 구현하기 (0) | 2020.06.29 |
---|---|
안드로이드 Q (API 29) 관련 파일 저장 퍼미션 문제 (0) | 2019.11.17 |
커스텀 다이얼 로그를 만들어 보자(왕왕초보자) (0) | 2017.06.12 |
인텐트 및 인텐트 필터에 대해 알아보자. (0) | 2017.05.06 |
Apk는 어떻게 만들어지는 걸까? (0) | 2017.05.04 |