태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

#04. 예제로 알아보는 GUI 디자인 - (3) 리스너 추가 및 마무리하기

2009/02/21 00:22

지난 강좌에서, 사용자가 입력한 할 일이 저장되어있는 ArrayList와 입력된 할 일을 화면에 표시해주는 ListView를 ArrayAdapter를 통해 연결시켜주는 코드까지 작성하였습니다. 

이번 강좌에서는, 키패드의 CENTER 버튼을 누르면 EditText를 통해 입력된 할일이 ArrayList에 저장되게끔 하는 코드, 즉 KeyListener를 작성하여 예제 어플리케이션을 완성해보도록 하겠습니다.

그나저나, 왼쪽 화면에서 뭔가 차이점을 느끼셨나요?
아마 저번 강좌 화면에서는 못보던 "키패드"를 보실 수 있으실 겁니다. 아시는 분은 다 아시겠지만, 아직까지 안드로이드 SDK에는 터치 키보드가 적용이 되어있지 않은데, 안드로이드 컵케익에는 이 터치 키보드가 적용되어있습니다.

요새 제가 컵케익을 적용시켜서 이것저것 만져보느라, 본의 아니게 화면이 바뀌게 되어버렸네요. :) 뭐, 예제도 설명하면서 겸사겸사 컵케익에 관련된 것도 소개하니, 어떻게 보면 일석이조라고 할 수도 있나요? ^^;;

안드로이드 컵케익에 관한 정보 및 설치법은 (2009/01/29 - [안드로이드/이거, 알고있니?] - 안드로이드 Cupcake 업데이트, 직접 체험해보자!)를 참조하세요.

그럼, 이제부터 본격적으로 마무리를 지어가도록 하겠습니다.

사용자로부터 입력받은 할일을 ArrayList로 넘기는 역할을 해주는 코드도 짜야 하고, 사용자의 특정 입력, 이 예제에서는 CENTER 버튼이 눌렸을 때 입력받은 정보를 ArrayList로 넘겨주는 KeyListner의 작성, 즉 이 두 가지를 이번 강좌에서 다루도록 하겠습니다. 일단, 코드부터 보겠습니다.

package com.androidhuman.ToDoList;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.EditText;
import java.util.ArrayList;
import android.widget.ArrayAdapter;
import android.view.*; // View객체를 사용하기 위해 import합니다.
import android.view.View.OnKeyListener; // 키 리스너를 사용하기 위해 import 합니다.

public class HelloWorld extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        ListView myListView = (ListView)findViewById(R.id.myListView);
        final EditText myEditText = (EditText)findViewById(R.id.myEditText);
        
        final ArrayList<String> todoItems = new ArrayList<string>(); // java
        
        final ArrayAdapter<String> aa; // android
        aa=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, todoItems);
        
        myListView.setAdapter(aa);
        
        myEditText.setOnKeyListener(new OnKeyListener(){ // (1) 
         public boolean onKey(View v, int keyCode, KeyEvent event) { // (2)
          if(event.getAction()==KeyEvent.ACTION_DOWN)  // (3)
          {
           if(keyCode==KeyEvent.KEYCODE_DPAD_CENTER) {
                       
           todoItems.add(0, myEditText.getText().toString()); // (4) 
           aa.notifyDataSetChanged(); // (5) 
           myEditText.setText(""); //(6) 
           return true;
           }
          }
          return false;
         }
        });
    }
}

으음... 상당히 복잡한 모습을 갖추고 있습니다(....)
저도 처음에 저걸 봤을때 (사실 지금도 무서워요...) 뭐 저래.. 했는데, 하나하나씩 차근차근 풀어나가다 보니 많이 복잡한 구조를 가지고 있지는 않았습니다. 하지만, 코드 자체가 좀 복잡하고, 중괄호 하나하나도 헷갈리기 쉬우므로 잘 보세요.
헷갈리지 마시라고 색깔로 구분해 두었습니다. :)

키 리스너를 가지는 객체는 실질적으로 객체가 가지고 있는 데이터를 "가지고 있는" 객체, 즉 EditText 객체가 가져야 합니다. 그래야 EditText 에 입력한 할 일을 ArrayList에 저장할 수 있겠죠??

(1)번을 보시면, EditText에 OnKeyListner를 추가해주는 것을 볼 수 있습니다(setOnKeyListner). 그와 동시에, OnKeyListner를 추가해주고 있는데, 이 생김새 자체가 저는 너무 어색했습니다. 그래서 아직 저도 완벽하게 이해한 상태가 아니라, 일단은 "무작정 따라하고" 있는 중입니다. ^^;; 일단은 따라하시고, 나중에 제가 리스너 인터페이스에 대해서 좀 더 공부한 이후에 포스팅할테니, 그때까지 기다려주세요~~ (물론, 이 쪽에 대해 잘 아시는 분은 개념 정도라도 설명해주신다면 감사하겠습니다 :)

(2)에서 보면, 키가 입력되었을 때 반응하는 메소드인 OnKey() 메소드 안에 우리가 필요한 내용들을 추가하고 있습니다. (3) 을 보면, 키카 눌렸을 때 반응하도록 되어있습니다. 

키가 눌렸을 때에는 어떤 키가 눌렸는지를 알려주는 keyCode를 인식하게 됩니다. 입력받은 키는 코드 형태로 KeyListener에 전달되게 되는데, 이렇게 전달된 키코드에 따라 어떻게 반응할 지 정할 수 있습니다.

이 예제에서는 CENTER 버튼을 눌렀을 때 반응해야 하므로, keyCode가 KEYCODE_DPAD_CENTER일 때, 즉 가운데 버튼을 눌렀을 때 반응하도록 되어있습니다.

다음은, 원하는 키가 눌렸을 때 해 줄 작업을 추가하였습니다. 즉, EditText에 입력된 내용을 ArrayList에 넣어주는 작업입니다.
이 과정은 의외로 간단합니다. (4)에서, EditText에 있는 텍스트를 String형태로 ArrayList(todoItems)에 바로 전달합니다. 이는, ArrayList에 항목을 추가하는 메소드인 add()를 통해서 이루어집니다.

그리고, ArrayList의 내용이 변경되었으므로 이를 ListView에 알려서 내용을 갱신해야 합니다. 이를 수행하기 위하여, ListView와 ArrayList를 연결해주는 ArrayAdapter(aa)의 notifyDataSetChanged()메소드를 이용하여 변경된 사실을 ListView에 알려줍니다. 그렇게 되면, ListView는 화면을 갱신해주어 사용자가 입력한 할 일이 리스트에 추가되어 화면에 나오게 됩니다 (5).

마지막으로, 사용자로부터 추가적으로 할 일 입력을 받기 위해 EditText에 입력된 내용을 지워줍니다(6).
마지막으로, OnKey 메소드가 boolean 이므로, 모든 과정이 정상적으로 작동하였다면 true를 반환하여 메소드를 종료합니다.

이 과정을 제데로 따라오셨다면, 다음 화면과 같이 작동할 것입니다. :)


이로서, 꽤 오랜 시간동안 쉬었다 다시 시작한 입문 강좌의 한 단원이 끝났습니다. 다음 강좌는 언제 쓸 수 있을지 모르겠지만, 공부 좀 더 열심히 해서 가급적 빠른 시일 내에 올릴 수 있도록 하겠습니다.

Hint. 다음 강좌는 아마도 Intent를 다룰 듯 합니다. :)




 

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

커니 유저 인터페이스/레이아웃(Layout) , , , , , , , , , ,

  1. Blog Icon
    An

    안녕하세요. 올리신 정보 많은 도움 되고 있네요.
    한가지만 질문드리겠습니다.

    (4)번 코드에서
    todoItems.add(0, myEditText.getText().toString());

    add 하는것은 알겠습니다. 헌데 저는 인덱스가 0인 이유가 대체 해석이 안되네요..
    추가되는 스트링들이 인덱스 0번째에 입력되고 그전에 인덱스 0에 있던 스트링은 1로 밀리는 건가요?
    아니면 리스트에는 인덱스 0에만 계속 스트링이 입력되는것인가요?

    ArrayList 즉, todoItems 는 데이터가 저장이 되지 않는것인가요?

  2. 인덱스가 0인 이유는, 항상 맨 앞에 추가시키기 위해서입니다. 이 방법으로 추가하게 되면, 기존에 있던 데이터를 자동으로 뒤로 밀리게 됩니다.

    이 예제를 실행해보시면, 실제로 이전 데이터들이 뒤로 미리는 것을 확인하실 수 있으실 겁니다.

    그리고, 실질적인 데이터의 저장은 ArrayList, 즉 todoItems에 저장되는 것이 맞습니다. ㅎㅎ
    ArrayAdapter는 ArrayList의 데이터를 ListView에 전달을 해주는 역할만 하지요~

  3. Blog Icon
    BAdBOy

    올려주는 글 잘 보고 있습니다.
    저도 안드로이드에 관심이 있어서 컨텐츠나 하나 짜볼까 하고 시작한 대학생입니다.
    이거 영어가 미천하다 보니 Android Application Development 책을 봐도
    영 -0-;;;

    4장 까지 책 따라가면서 해보고 있는데
    질문 하나만 해도 될까여?

    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

    이쪽 함수에서
    클릭시 remove만 지원 되는데
    list 목록을 다 삭제 할려고하는데

    이거 도통 감이 안옵니다....

  4. http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html#clear()

    이걸 사용해보시면 어떨까요?

  5. Blog Icon
    An

    답변 감사합니다. 자바 애플리케이션을 처음 접하며 안드로이드 애플을 하려다 보니 갈길이 너무 먼것 같네요.

    다시 한번 감사드리며, 좋은 하루 되시기 바래요.

  6. Blog Icon
    BAdBOy

    감사합니다.^^

    이해하는데 많은 도움이 되었습니다.

    언제나 강좌 잘 보고 잇어요...

  7. Blog Icon
    simsiss

    오... 작동되는거 보고 소리질렀습니다!!

    감사합니다 ㅋㅋ 처음 올리신 강좌부터 보고 있는데 ㅋㅋ 하하하 ㅋㅋ

  8. 이 당시의 강좌들이 뭔가 부족한 것들이 좀 많았는데.. 잘 진행하셨다니 뿌듯하네요 ^^

  9. Blog Icon
    플머

    강좌 잘보고있습니다. 따라해보았는데 에러가 나서 질문드립니다.
    <STRING> 부분에서 에러가 나서 <String>으로 대체해서 구문에러는 없는데 어플리케이션을 돌리서 보면
    에러가 나네요 이클립스 어플리케이션 디버깅 을 따로 보는곳이 있는지.. <STRING>부분을 어떻게 처리해야되는지 알고싶습니다..

  10. 정확히 어느 부분을 말씀하시는건지요?

  11. Blog Icon
    소난

    저도 플머님과 같이 오류가나는데.. STRING 부분을 고치면 밑에 add에서 빨간줄이 기어다니고....
    ㅜㅜㅜㅜㅜㅜ어떻게 처리해야할까요

  12. Blog Icon
    소안

    Sorry
    The application TodoList
    has stopped unexpectedly
    Please try again.

    왜 안될까요 이거.. 후..ㅜ_ㅜ
    -----------
    히결되었습니다

    main.xml 문제 였네요 ;;ㅎ

    <LinearLayout 을 소문자로 쓰면 안되더라고요 ㅋ

  13. Blog Icon
    justloveher

    강좌 정말 잘 보고 있습니다. 프로그램을 첨 시작해서 모르는게 많은데요..
    질문한가지 드립니다. 다른게 아니라 위 코드를 작성해서 실행하면 에뮬이 돌아가고 todolist 응용프로그램이 예상치 않게 중지 되었습니다. 다시시도하세요라고 나오며서 강제로 닫기라는 버튼이 나옵니다. 답변부탁드립니다.
    jdk-6.0 , android sdk-1.5.r3 , 이클립스는 가니메데..사용중입니다.

  14. 안드로이드 시작한지 한달도 안된 완전 초보인데,,
    여기 블로그에서 많이 보고 배우고 있습니다^^
    감사합니다!!
    아참!! 질문이 하나있는데요,,
    버튼을 두개 만들어서 각자 다른 액티비티를 호출하려면
    버튼마다 intent와 listener을 각각 만들어서 액티비티를 호출하면 되나요?
    예제들이 대부분 버튼하나짜리라서 참고할 만한 자료가 없네요..ㅜㅠ
    감사합니다~ㅎ

  15. 인텐트는 당연히 두개가 있어야 하고, 리스너는 각각 버튼에 리스너 하나씩 할당한다면 두개가 되겠고, 아니면 액티비티에 OnClickListener 인터페이스를 구현하고 ID에 따라 각각 처리해줄 작업을 다르게 지정해주면 리스너 하나로도 가능합니다.

  16. 오오!!완전 대박 감사합니다^^

  17. Blog Icon
    옙홍

    궁금한게 있는데요.... 메인 Activity에서 버튼을 눌렀을때 ListActivityㄹ를 상속받은 놈으로 전환 하려고 하는데
    그거 원래 되는건가요?? 원래 안되는지 되는지를 모르겠어서 제가 하면 안되더라구요 제가 뭘 잘못했는지....

    원래 안되는건지 모르겠어서 혹시 아시나욤

  18. 당연히 전환 가능합니다.안된다는게 정확히 안된다는게 어떻게 안된다는건지는 잘 모르겠지만.....

    기존에 그냥 액티비티를 사용할 때는

    import android.app.Activity;

    라고 되어있던걸

    import android.app.ListActivity;

    로 바꿔주기는 해야죠. ㅎㅎ

  19. Blog Icon
    난최장군

    ㅠㅠ 이상하네요.. 실행하자마자 왜 자꾸 런타임 오류가 뜰까요;;

  20. Blog Icon
    근육돼지

    저는 실행은 되는데 이상하게 글적고
    엔터를 치면 에디터텍스트만 길어지고
    리스트뷰에는 안넘어가염..ㅠㅠ 왜그렇죠?

  21. 엔터가 아니라 버튼을 클릭해야 입력됩니다 :)

  22. Blog Icon
    ㅊㅊㅊ

    d-pad center 버튼 클릭하면 입력한 텍스트가 밑으로 내려오지 않고 텍스트수정이라는 새로운창이뜨면서 '모두 선택' '텍스트선택' '모두 잘라내기' 등등의 텍스트수정방법을 선택하는 창이 뜨네요.
    당최뭔지 ;; 이런경우 있으신가요??

  23. Blog Icon
    초보 안드로이더

    키보드에서 어떤 버튼을 눌러야되나요 아무리 해도 입력이 안되네요

  24. 글자를 입력하면 입력되지 않나요? 물론 입력하기 전에 EditTest가 선택된 상태여야 합니다. (EditText를 터치)

  25. Blog Icon
    worstlie

    내용 부분에서 이해가 안가는 부분이 있어 염치없이 질문 드립니다.
    많은 분들이 이해를 잘 못하시는 부분인거같은데요..
    CENTER버튼이라는게 정확히 어떤버튼인지요..?
    키보드입력후 어떤행동을 해야 되는건지 잘 모르겠습니다..
    염치없지만 답변 부탁드립니다..ㅠㅠ

  26. 에뮬레이터의 방향키 가운데 있는 버튼을 뜻합니다~
    현재 단말기에는 이 버튼이 없는 경우가 대다수라, 테스트를 하려면 엔터터(KeyEvent.KEYCODE_ENTER) 를 사용하는 것이 편리합니다.

  27. Blog Icon
    worstlie

    예제 33열을 고치면 되는군요.. 감사합니다:)
    그럼 내용을 바꾸면 버튼을 선택하여 입력할수도 있겠군요..

  28. Blog Icon
    buzzer

    커니님 감사합니다. ^^ 많이 배우고 갑니다.

    if(keyCode==KeyEvent.KEYCODE_ENTER)
    이렇게 고치니까 엔터키로 바로 되네요.