태터데스크 관리자

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

태터데스크 메시지

저장하였습니다.

#11. List 집중공략! - (3) Custom ArrayAdapter를 이용한 ListView

2009/06/08 05:42



강좌 작성환경
SDK Version : Android SDK 1.5, release 2
ADT Version : 0.9.1

추후 SDK업데이트로 인해 글의 내용과 실제 내용간 차이가 있을 수 있습니다.

이번 강좌에서는 리스트뷰에 사용자가 원하는 레이아웃대로 항목을 표시하도록 만들어보겠습니다.

지난 강좌 (2009/06/04 - [안드로이드 이야기/안드로이드 입문] - #11. List 집중공략! - (1) 기본 다지기) 에서 설명했듯이, ListView는 ListView 하나로 이루어지는 것이 아니라 리스트뷰에 표시할 항목을 담고 있는 리스트 객체, 리스트 객체의 데이터를 리스트뷰에서 표시할 수 있게 해주는 어댑터, 최종적으로 화면에 리스트를 표시해 주는 리스트뷰(ListView)로 구성됩니다.

이 세 구성요소 중 가장 중요한 역할을 하는 것은 단연 어댑터(Adapter)라고 할 수 있습니다.
어댑터는 리스트 객체를 리스트뷰에서 표시해주는 기능, 즉 리스트 객체의 내용과 리스트 항목의 레이아웃을 연결시켜주는 역할을 합니다. 따라서, 어댑터가 없다면 일단 리스트 객체의 데이터를 리스트뷰에 표시하는 것은 불가능합니다.

그럼, 지난 강좌에서 썼던 ArrayAdapter를 한번 살펴볼까요?

ArrayAdapter<String> aa = new ArrayAdapter<String>(this,
        		android.R.layout.simple_list_item_1, list);


ArrayAdapter의 생성자에서 두번째 인자, android.R.layout.simple_list_item_1은 리스트에서 각 항목을 표시할 레이아웃을 뜻합니다. 이 레이아웃은 리스트 한 줄에 한 줄의 텍스트만이 표시되도록 되어있죠.

하지만, 리스트에 표시할 항목이 하나가 아닌 여러 가지가 있는 경우가 있습니다. 당장 연락처 어플리케이션이나 설정 어플리케이션을 봐도 리스트 항목 하나에 텍스트 하나만 표시되지는 않죠. 그래소, 이번 강좌에서는 리스트 항목 하나에 두 줄의 텍스트, 그리고 하나는 큰 텍스트, 하나는 작은 텍스트로 표시되도록 만들어 볼 것입니다.

이렇게, 리스트에 사용자가 원하는 레이아웃을 표시하기 위해서는 사용자 정의 어댑터를 만들어야 합니다. ArrayAdapter는 한 줄에 하나의 텍스트만을 표시하도록 코딩되어있으므로, 우리는 이와는 달리 두 줄로, 텍스트 두 개가 표시되게끔 어댑터를 만들어야겠지요?


이번 강좌에서는 위 스크린샷처럼 두 개의 텍스트를 표시하고, 위에는 이름, 아래는 전화번호를 표시하는 어댑터를 만들어보도록 하겠습니다.

이를 구현하기 위해 이름과 전화번호 데이터를 각각 String 형식으로 저장하고 있는 Person 클래스를 만들었으며, 이 객체의 저장은 ArrayList를 이용하였습니다. 새로 만들 어댑터의 이름은 PersonAdapter로 지정하였습니다.

일단, 전체 소스 코드와 레이아웃을 살펴보도록 하겠습니다.

[소스코드 : ListExample.java]

package com.androidhuman.ListExample;

import java.util.ArrayList;
import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class ListExample extends ListActivity{ // ListActivity를 상속받습니다.
       
        
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ArrayList<Person> m_orders = new ArrayList<Person>();
        
        Person p1 = new Person("안드로이드", "011-123-4567"); // 리스트에 추가할 객체입니다.
        Person p2 = new Person("구글", "02-123-4567"); // 리스트에 추가할 객체입니다.
        
        m_orders.add(p1); // 리스트에 객체를 추가합니다.
        m_orders.add(p2); // 리스트에 객체를 추가합니다.
        
        PersonAdapter m_adapter = new PersonAdapter(this, R.layout.row, m_orders); // 어댑터를 생성합니다.
        setListAdapter(m_adapter); // 
                
    }
    
    private class PersonAdapter extends ArrayAdapter<Person> {

        private ArrayList<Person> items;

        public PersonAdapter(Context context, int textViewResourceId, ArrayList<Person> items) {
                super(context, textViewResourceId, items);
                this.items = items;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
                View v = convertView;
                if (v == null) {
                    LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    v = vi.inflate(R.layout.row, null);
                }
                Person p = items.get(position);
                if (p != null) {
                        TextView tt = (TextView) v.findViewById(R.id.toptext);
                        TextView bt = (TextView) v.findViewById(R.id.bottomtext);
                        if (tt != null){
                        	tt.setText(p.getName());                            
                        }
                        if(bt != null){
                        		bt.setText("전화번호: "+ p.getNumber());
                        }
                }
                return v;
        }
}
    class Person {
        
        private String Name;
        private String Number;
        
        public Person(String _Name, String _Number){
        	this.Name = _Name;
        	this.Number = _Number;
        }
        
        public String getName() {
            return Name;
        }

        public String getNumber() {
            return Number;
        }

    }
}

[ 레이아웃 : main.xml / 액티비티의 레이아웃 ]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   >
<ListView
    android:id="@+id/android:list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    />
<TextView
    android:id="@+id/android:empty"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:text="tets"/>
</LinearLayout>



[레이아웃 : row.xml / 리스트 항목의 레이아웃 ]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="6dip" android:orientation="vertical">
        <TextView
            android:id="@+id/toptext"
            android:layout_width="fill_parent"
            android:gravity="center_vertical"
        android:layout_height="wrap_content" android:textSize="20px"/>
        <TextView
            android:layout_width="fill_parent"
            android:id="@+id/bottomtext"
            android:singleLine="true"
            android:ellipsize="marquee"
        android:layout_height="wrap_content"/>
    
</LinearLayout>



우선, 이름과 전화번호 데이터를 저장할 수 있는 객체인 Person 클래스부터 살펴보겠습니다. 아주 간단~한 구조로 이루어져 있습니다.


    class Person {
        
        private String Name;
        private String Number;
        
        public Person(String _Name, String _Number){
        	this.Name = _Name;
        	this.Number = _Number;
        }
        
        public String getName() {
            return Name;
        }

        public String getNumber() {
            return Number;
        }

    }

Person 클래스 내에는 각각 이름(Name)과 전화번호(Number)를 저장하는 String형 변수가 2개 있고, 생성자를 통해 각각의 값을 초기화시키며 getName()메소드와 getNumber()를 통해 각각의 데이터를 반환하는 구조입니다.

그럼, 이번 강좌의 핵심인 어댑터, PersonAdapter를 보도록 하겠습니다.

private class PersonAdapter extends ArrayAdapter<Person> {

        private ArrayList<Person> items;

        public PersonAdapter(Context context, int textViewResourceId, ArrayList<Person> items) {
                super(context, textViewResourceId, items);
                this.items = items;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
                View v = convertView;
                if (v == null) {
                    LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    v = vi.inflate(R.layout.row, null);
                }
                Person p = items.get(position);
                if (p != null) {
                        TextView tt = (TextView) v.findViewById(R.id.toptext);
                        TextView bt = (TextView) v.findViewById(R.id.bottomtext);
                        if (tt != null){
                        	tt.setText(p.getName());                            
                        }
                        if(bt != null){
                        		bt.setText("전화번호: "+ p.getNumber());
                        }
                }
                return v;
        }
}


PersonAdapter 클래스는 ArrayAdapter 클래스를 상속하여, ArrayList의 데이터를 받아와 이를 ListView에 표시되게 해 줍니다. ArrayAdapter 클래스가 하나의 TextView만을 제공했던 것과 달리, PersonAdapter는 우리가 이 강좌에서 사용하는 Person 객체에 맞게끔 구현되어 있습니다.

그럼, PersonAdapter의 코드를 차근차근 보도록 하죠.
    private class PersonAdapter extends ArrayAdapter<Person> {

        private ArrayList<Person> items;

        public PersonAdapter(Context context, int textViewResourceId, ArrayList<Person> items) {
                super(context, textViewResourceId, items);
                this.items = items;
        }

일단, PersonAdapter 클래스 내부에 우리가 리스트에 표시할 항목을 저장할 리스트객체 (ArrayList items)가 보이네요. 이는 PersonAdapter 생성자를 통해 넘어온 리스트객체의 데이터를 저장하는 역할을 합니다. 생성자 내부에서는 생성자의 인자로 넘어온 리스트 객체(ArrayList items)를 PersonAdapter 내부의 리스트 객체 (this.items)로 연결시켜주는 모습을 확인할 수 있습니다.

@Override
        public View getView(int position, View convertView, ViewGroup parent) {
                View v = convertView;
                if (v == null) {
                    LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    v = vi.inflate(R.layout.row, null);
                }
                Person p = items.get(position);
                if (p != null) {
                        TextView tt = (TextView) v.findViewById(R.id.toptext);
                        TextView bt = (TextView) v.findViewById(R.id.bottomtext);
                        if (tt != null){
                        	tt.setText(p.getName());                            
                        }
                        if(bt != null){
                        		bt.setText("전화번호: "+ p.getNumber());
                        }
                }
                return v;


getView()메소드는 PersonAdapter 클래스의 핵심이라 할 수 있습니다. 우리가 원하는 기능 (리스트 항목에 두 줄의 텍스트가 표시되도록..) 을 이곳에서 구현하고 있거든요. 우선, getView()메소드의 API부터 보도록 하죠,


public abstract View getView (int position, View convertView, ViewGroup parent)
Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML layout file. When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters unless you use inflate(int, android.view.ViewGroup, boolean) to specify a root view and to prevent attachment to the root.

Parameters
position
  The position of the item within the adapter's data set of the item whose view we want.
convertView  The old view to reuse, if possible.
Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view.
parent  The parent that this view will eventually be attached to

Returns
A View corresponding to the data at the specified position.


getView()메소드는 리스트 전체의 레이아웃을 책임지는(?) 것이 아니라, 리스트 각 항목에 대한 레이아웃만을 책임집니다. API에서도 position; 리스트 항목의 인덱스를 받아 그에 해당하는 레이아웃을 출력해주는 것을 볼 수 있습니다.


그럼, 각 항목에 대한 레이아웃은 어떻게 지정해줄까요?
아래의 코드에서 확인해보죠.

View v = convertView;
                if (v == null) {
                    LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    v = vi.inflate(R.layout.row, null);
                }


화면의 구성 단위인 View에 우리가 원하는 레이아웃을 적용시켜주기 위해 LayoutInflater를 사용하였습니다. LayoutInflater에 시스템 서비스를 받아온 후, inflate()메소드를 통해 레이아웃을 적용시켜주면 됩니다. inflate()메소드에 대한 API는 여기를 참조하세요.

Person p = items.get(position);
                if (p != null) {
                        TextView tt = (TextView) v.findViewById(R.id.toptext);
                        TextView bt = (TextView) v.findViewById(R.id.bottomtext);
                        if (tt != null){
                        	tt.setText(p.getName());                            
                        }
                        if(bt != null){
                        		bt.setText("전화번호: "+ p.getNumber());
                        }
                }
                return v;

이 부분부터는 실질적으로 Person 객체 내의 데이터를 화면에 표시해주는 역할을 해주고 있습니다.
아까 Person객체를 저장하고 있는 ArrayList를 PersonAdapter 내의 리스트에 저장했는데, 이 List로부터 리스트의 해당 인덱스의 데이터를 받아오게 됩니다. 그리고, 이 데이터가 null(데이터 없음) 이 아니라면, 우리가 지금까지 해왔던 방법과 똑같이 findViewById()메소드를 통해 레이아웃 객체를 참조하여 데이터를 화면에 표시해주게 됩니다.
데이터와 레이아웃을 연결해주는 작업이 끝나면, 최종적으로 작업이 완료된 View를 반환하여 화면에 표시하도록 합니다.


휴...
지금까지 그 어떤 강좌보다도 공부할 때에도 애를 많이 먹었고, 강좌 쓰는 시간도 많이 걸렸네요.
하지만, 그만큼 더 이것저것 많이 알게 된 계기가 되지 않않나 싶습니다 ^^;;

위의 방법을 사용해서 리스트에 이미지가 나오게도 할 수 있으니, 응용해서 한번 연습해보세요~ ㅎㅎ
다음 강좌는 일단 데이터베이스(SQLite)를 다루는 것을 목표로.... 서서히 공부해야나가야겠습니다 :)

p.s 강좌 소스 코드 첨부합니다.

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

커니 화면 구성/뷰(View) , , , , , , , ,

  1. Blog Icon
    마창

    커니님 강좌 항상 감사히 잘 보구있습니다~ 감사감사

    질문이 하나 있는데여

    저렇게 리스트 목록에 액션을 줄려면 어떻게 해야되는지요? 예를 들면 위에 캡쳐그림에

    노란색 영역 표시되어있는 구글을 클릭하는 액션을 주고 싶은데 도저히 방법을 찾을 수 없어서

    질문드립니다~~

  2. protected void onListItemClick (ListView l, View v, int position, long id)
    This method will be called when an item in the list is selected. Subclasses should override. Subclasses can call getListView().getItemAtPosition(position) if they need to access the data associated with the selected item.

    Parameters
    l The ListView where the click happened
    v The view that was clicked within the ListView
    position The position of the view in the list
    id The row id of the item that was clicked


    요놈을 사용해보세요~

  3. Blog Icon
    김인구

    안녕하세요 커니님.
    포스팅 해 주시는 내용들 너무나 감사히 보고 있습니다.
    질문이 있어 이렇게 글 올립니다.

    getView() 함수내의 Person p = items.get(position); 코드를 아래와 같이 써도 되는것 같습니다.
    Person p = this.getItem(position);
    이렇게 PersonAdapter의 생성자로 넘겨준 내용들을 PersonAdapter가 관리 하고 있는것으로 봐서
    R.layout.row도 넘겨주니까 관리 하고 있을꺼 같아서 디버깅창에서 보니
    PersonAdapter의 mDropDownResource, mResoruce라는 멤버 변수가 R.layout.row 값을 가지고 있었습니다.
    물론 context 같은 다른곳에서도 저장되어 있었습니다.
    그런데 이 값을 가져올 수 있는지, 그런 방법이 있는지는 찾지 못하였습니다.
    더불어 가능하다면 R.id.toptext와 R.id.bottomtext도 가져올 수 있지 않을까 생각하는데 혹시 분석이 되셨는지 궁금합니다.

    질문이 두서가 없었습니다...
    다시한번 연재하시는 강좌에 대해 감사드립니다.
    수고하세요~

  4. 저도 아직은 배우는 입장이라 여러 모로 테스트해보지는 못했네요~ 한번 테스트해보겠습니다. :)

    좋은 정보 감사합니다. :)

  5. Blog Icon
    투탄

    좋은 강의 감사합니다.
    질문이 있는데요 현재의 2행에서 체크버튼까지 추가 하려면 어떻게 해야 하나요?
    이제 배우는 입장이라 부탁드리겠습니다.

  6. row.xml 파일에 체크박스를 추가하고,
    getView()메소드 내에서 적절히 처리를 해주면 됩니다.

    예를들면 아래와 같이 되겠죠.

    CheckBox cb = (CheckBox)v.findViewById(R.id.check_box);

    if(cb != null){
    cb.setChecked(p.isChecked()); // 체크 유무를 확인하여 체크
    }

  7. Blog Icon
    포스

    커니님 강좌 보고 열심히 공부하고 있습니다.
    그런데 위의 있는 소스를 변형시켜서 테스트를 하려고 하니까 onListItemClick 함수에 이벤트가 공급되지 않습니다.
    텍스트 두 줄 있던 상황에서 이미지 버튼 하나를 더 넣은거밖에 차이가 없어서 뭐가 문제인지 알 수가 없어서 이렇게 질문 올립니다.

  8. 이미지버튼의 focusable을 false로 해보세요!~

  9. Blog Icon
    포스

    답변감사합니다.
    해보니까 Butoon일때는 focusable을 넣으니까 되는데 ImageButton일때는 안되네요.

  10. Blog Icon
    후니

    좀 생뚱 맞은 질문입니다만, 혹시 알고 계시면 좀 알려주셨으면 합니다.

    Toast.makeText(toast.this, textToShow.getText().toString(), LENGTH_TO_SHOW).show();
    이런식으로 메소드가 선언 되어 있을때 textToShow.getText().toString() 이부분에서 메소드가 어떤순서로 작동을 하는지요?
    1) textToShow.getText().
    2) textToShow.getText().toString()
    이 실행이 되는지
    A)textToShow.toString()
    B)textToShow.getText().toString()가 실행이 되는지요?

    여러개가 나열 되어 실행되는 것을들 볼때 어떻게 실행이 되는지 순서를 알수가 없어서요..

  11. 순서는 당연히 읽는 순서대로입니다 :)

    EditText.getText() - Editable

    Editable.toString() - String

    이 과정을 거쳐서 최종적으로 EditText 위젯의 텍스트가 String형태로 반환되는 것입니다.

  12. Blog Icon
    후니

    답변 감사합니다. 자바와 많이 달라서 많이 헤메고 있습니다. 고맙습니다.

  13. Blog Icon
    최기동

    클릭한 리스트의 text를 가져올때
    person mmd = (person)l.getAdapter().getItem(position);

    이런식으로 강제 형변환 해서 가져 오는게 맞는건가요 에러없이 동작은 합니다만...

  14. getItem()에서 Person 형태로 반환해주지 않나요??

  15. Blog Icon
    상민

    커니님 리스트뷰에 checkbox 를 추가할때요 스크롤이 있을때 체크박스를 맨위쪽의 리스트들을

    체크했을 경우 스크롤로 내려갔다 올리면 위쪽의 리스트들의 체크됐던 상태가 사라져버려요.

    아마 getview 문제 같은데 어떻게 해결해야 하나요?..

    listview 의 height 를 fll 로 하면 된다던 분이 있었는데 스크롤에 대해선 상태가 변하지 않지만

    터치모드로 스크롤을 움직일 시 같은 현상이 발생합니다.

  16. 안드로이드펍이나 안드로이드사이드같은 커뮤니티에 질문을 올려보는 것이 좋을 것 같습니다. 저도 이 부분은 많이 해보질 않아서...;;

  17. Blog Icon
    우신

    어디에다가 질문해야 할지 몰라서 이곳에 적게 되네여 ^^;
    제가 하려는 작업은 탭처럼 일종에 화면을 분할해서 화면을 구성하려고 하는데여..
    상하로 나뉘며, 위에는 메뉴에 해당하는 버튼들이 있고 버튼을 누르면 하위에서 인텐트로 다른 액티비티를 보여주는 식으로 구상을 하고 있는데... 도저히 감을 못잡겠네여...
    TableLayout에 FrameLayout을 넣고 FrameLayout에 다가 내용을 보여주는 식으로 하려고 하는데..
    위에 나온것을 응용을 해볼까 하는데...
    FrameLayout을 자바 오브젝트로 불러와서 intent 할수 있는 방법이 있나여?
    질문이 복잡해진거 같은데.. 도움 주심 감사하겠슴돠 ㅠㅠ

  18. API Demos 를 찾아보시면 Intent를 이용해서 탭을 구성하는 예제가 있으니 참고하세요 :)

  19. Blog Icon
    초보운짱.

    간단 명료하게 잘 설명하시네요..
    좋은 도움 받고 갑니다. 꾸벅~

  20. Blog Icon
    김태이

    강좌 내용 너무 좋네요. 감사합니다.

    질문이 하나 있는데요.

    만약에 셀마다 다른 형태를 주는 것도 가능할까요?

    예를 들면, 안드로이드 이름은 노란색으로 한다던가

    전화번호가 없는 항목은 아래의 전화번호 TextView를 표시하지 않는다던가 말이죠.

  21. 위와 같이 커스텀 어댑터를 만드신다면 가능합니다.
    특별한 문자의 색을 바꾸는건 위의 코드를 조금만 수정하셔도 가능하고, 전화번호가 없을 경우 텍스트뷰를 표시하지 않는건 해당 항목 레이아웃의 생성을 코드에서 동적으로 처리하도록 하면 되갰네요 :)

  22. Blog Icon
    엄청난넘

    이 예제를 바탕으로 리스트뷰를 만들었습니다.

    tabhost로 activity를 여러개로 나누고 리스트뷰를 뿌려주는 activity에서 리스트 아이템을 클릭할때 다른 activity를 호출하게 됩니다.

    그런데 activity가 전환될때 tabhost가 모두 사라지고 전체 화면에 다른 activity가 로드 되는데

    tabhost가 사라지지 않고 전환되는 방법을 아시면 조언좀 부탁드립니다. ㅠㅠ

  23. Blog Icon
    슈슈

    항상 잘 보면서 많은 도움 받았는데 여기선 잘안되네요ㅜ
    만약에 EditText를 두어서 입력받은 문자를 출력하는데
    이미지와 함께 출력하고싶은데 그게 잘안됩니다ㅜ
    버튼을 누르면 Force close 가 뜨면서 종료하게되요 ㅜ
    getView안에다가 버튼 리스너를 두었는데 person같은 객체따로 두지않고
    입력받은 내용과 이미지를 바로바로 띄우려면 어떻게 해야될까여? 도와 주쎄영 ㅋㅋㅋ ㅜ-ㅜ

  24. Force Close로 인한 오류 대처법은 아래를 확인하세요.
    http://androidhuman.tistory.com/notice/386

    로그를 확인하면 어디에서 에러가 나는지 확인하실 수 있습니다.

  25. Blog Icon
    커니님!!

    안녕하세요??
    강좌 매우 유용하고 잘보았습니다.
    그런데 한가지 질문이 있습니다. 저기 예제에선 현재 리스트를 두개밖에 추가 안했지만 리스트항목들을 여러개 add시키면 리스트 라인줄이 두껍고 얇고 두껍고 얇고 두껍고 얇고 이런식으로 됩니다.
    m_orders.add(p1); // 리스트에 객체를 추가합니다.
    m_orders.add(p2); // 리스트에 객체를 추가합니다.
    m_orders.add(p2); // 리스트에 객체를 추가합니다
    m_orders.add(p2); // 리스트에 객체를 추가합니다
    m_orders.add(p2); // 리스트에 객체를 추가합니다
    한 이정도만 더 해도...라인줄이 일정치 않다는것을 볼수가 있는데요...(일정치 않다기보다 2개 간격으로 두껍고 얇고 이런식으로 되요...)혹시 왜이런지 원인을 알 수 있을까요? 급해서 그런데...이 댓글 보시면 꼭꼭 답변달아주셨으면 합니다. 감사합니다!!

  26. Blog Icon
    커니님!!

    앗 알아냈어요 padding값이 있었네요...-_-;;

  27. 알아내셨다니 다행입니다 ㅎㅎ
    혼자 발견하신만큼 실력 향상에 꽤나 도움이 되었을 겁니다 :)

  28. Blog Icon
    0soon2

    저는 왜, 한번에 모든 리스트들이 출력되지 않을까요??ㅜ 하나만 나오네요..
    다 표시하려면 스크롤을 왔다 갔다 해야 나오고,, 그 리스트 순서도 약간 어긋나있는것들도 보이네요..

  29. Blog Icon
    지나가다

    지나가다 우연히 발견해서 글 남깁니다.
    저도 리스트가 하나밖에 안나와서 고생 좀 했는데 알고보니
    저같은 경우는 ScrollView에 ListView를 띄우려고 해서 그랬더군요.
    ScrollView 없애고 LinearLayout에 넣으니 잘 나옵니다.
    혹시 저같은 분 계실까봐 글 남깁니다.

  30. Blog Icon

    비밀댓글입니다

  31. Blog Icon
    커니님!!!!!!

    protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.list);
    ArrayList<Vocabulary> Voca = new ArrayList<Vocabulary>();

    Resources myResources=getResources();
    InputStream myFile=myResources.openRawResource(R.raw.day1);

    try {
    br=new BufferedReader(new InputStreamReader(myFile, "EUC_KR";));
    } catch (Exception e) {
    e.printStackTrace();
    }
    for(int j = 0; j<50; j++){
    try{
    eng[count] = br.readLine();
    kor[count] = br.readLine();
    Toast.makeText(List.this,kor[count],Toast.LENGTH_SHORT).show();
    v = new Vocabulary(eng[count], kor[count]);
    Voca.add(v);

    count++;
    }
    catch(Exception e){
    e.printStackTrace();
    }

    VocaAdapter v_adapter = new VocaAdapter(this, R.layout.row, Voca);
    setListAdapter(v_adapter);
    }

    }
    public class VocaAdapter extends ArrayAdapter<Vocabulary>{

    private ArrayList<Vocabulary> items;

    public VocaAdapter(Context context, int textViewResourceId, ArrayList<Vocabulary> items) {
    super(context,textViewResourceId, items);
    this.items = items;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent){
    View view = convertView;
    if (view == null) {
    LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    view = vi.inflate(R.layout.row, null);
    }
    Vocabulary v = items.get(position);
    if (v!=null) {
    TextView tt= (TextView) view.findViewById(R.id.toptext);
    TextView bt = (TextView) view.findViewById(R.id.bottomtext);
    if (tt!=null){
    tt.setText(v.getEng());
    }
    if(bt !=null){
    bt.setText(v.getKor());
    }
    }
    return view;
    }
    }

    class Vocabulary {
    private String Eng;
    private String Kor;

    public Vocabulary(String Eng, String Kor){
    this.Eng = Eng;
    this.Kor = Kor;
    }
    public String getEng() {
    return Eng;
    }
    public String getKor(){
    return Kor;
    }
    }
    }

    비슷하게 한번 구현해 봤는데 ㅜㅜ 안돼요 ㅜㅜ
    도와주세요 ..ㅜㅜㅜㅜ
    어플이 켜지지 않고 강제 종료 되네요 ㅜㅜ
    도와주세요!!ㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜ

  32. 강제종료 될 경우는 DDMS를 통해서 에러메시지를 확인해 보시는 것이 도움이 될 거에요. 공지글 한번 확인해보세요~

  33. 흠..ArrayAdapter 상속받은 걸로 현재 PullParser 사용해서 네이버 API쓰고 있는데요,
    뭐 그거빼곤 님이랑 소스코드 다 똑같네요.. 근데;

    protected void onListItemClick(ListView l, View v, int position, long id){
    이 인식을 못하네요.. 로그캣이랑 디버그로 다 하고있는데, 클릭이벤트를 아예 인식 못합니다;
    이거 어떻게 방법 없을까요;

  34. 이번트를 받는 다른 부분에서 이번트를 먹어버리는(?) 부분이 있는지 확인해보세요. 터치이벤트 같은 경우 한 곳에서 이벤트를 먹어버리게(return false) 되면 다른곳에서 이벤트를 못받는 현상이 발생하는데... 그거랑 관련된 문제인 듯 합니다.

  35. Blog Icon
    이제막시작

    이제막 안드로이드을 시작한 초보입니다.
    여기저기서 샘플소스를 구해서 독학을 하고 있는데
    그리드뷰에서 막혔습니다. 전혀 진도가 안나가요..
    도와주세요
    결론적으로 해보려고 하는것은 그리드뷰에서 보여지는 이미지들을 한개씩 선택할때 마다
    새로운 액티비티에 띄우려고 합니다.
    도와주세요...


    public class ImageThumbnailsActivity extends Activity {

    private Cursor imagecursor, actualimagecursor;
    private int image_column_index, actual_image_column_index;
    GridView imagegrid;
    private int count, tmpID;
    protected static int[] mThumbIds;
    protected static final int position = 0;


    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    imagegrid=(GridView) findViewById(R.id.PhoneImageGrid);
    imagegrid.setAdapter(new ImageAdapter(this));

    imagegrid.setOnItemClickListener(new OnItemClickListener() {

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    Toast.makeText(getApplicationContext(), "이그림을 선택하셨습니다." + position,
    Toast.LENGTH_SHORT).show();


    Intent intent = new Intent(getApplicationContext(), ViewImage.class);
    intent.putExtra("position", position);
    startActivity(intent);


    }
    });

    }




    public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
    mContext = c;
    }
    public int getCount() {
    return mThumbIds.length;
    }
    public Object getItem(int position) {
    return null;
    }
    public long getItemId(int position) {
    return 0;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
    ImageView imageView;

    if (convertView == null) {
    imageView = new ImageView(mContext);
    imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    imageView.setPadding(8, 8, 8, 8);

    } else {
    imageView = (ImageView) convertView;
    }

    imageView.setImageResource(mThumbIds[position]);

    return imageView;
    }

    private Integer[] mThumbIds = {
    R.drawable.sample_0, R.drawable.sample_1,
    R.drawable.sample_2, R.drawable.sample_3,
    R.drawable.sample_4, R.drawable.sample_5,
    R.drawable.sample_6, R.drawable.sample_7,

    };


    }
    }

    ///////////////////////////////////////////////////////////////////////////////////

    public class ViewImage extends Activity {


    private final int imgWidth = 320;
    private final int imgHeight = 372;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.viewimage);

    Intent i = getIntent();
    Bundle extras = i.getExtras();
    String imgPath = extras.getString("position";);

    BitmapFactory.Options bfo = new BitmapFactory.Options();
    bfo.inSampleSize = 2;
    ImageView gv = (ImageView)findViewById(R.id.ImageV);
    Bitmap im = BitmapFactory.decodeFile(imgPath, bfo);
    Bitmap resized = Bitmap.createScaledBitmap(im, imgWidth, imgHeight, true);
    gv.setImageBitmap(resized);
    setContentView(gv);


    }
    }

  36. Blog Icon
    나그네

    강좌 잘 보고 갑니다. 헌데, 강좌 내용이 Software Passion 에서 본것과 상당히 유사하네요.
    우연의 일치라고 보기에는 변수 명명도 너무나 흡사하네요.

    태클 걸려는건 아니고요, 뭐 충분히 그럴 수도 있긴 하지만, 너무 같아서 .. ㅎㅎ

  37. 외국사이트 말하는건가요??? 그거라면 맞을겁니다 ㅎㅎ
    예전에 거기에서 보면서 공부한걸 정리했던 포스트라...

    원래는 공부한걸 블로그에 정리만 하려 했었는데, 아마 이 글 쓸때쯤부터 강좌 형식으로 쓰게된 것 같습니다. :)

  38. Blog Icon
    개미

    안녕하세요 커니님.
    요즘들어 님 강의 보면서 공부하고 있습니다.
    List에 항목을 추가할때 다른 줄에 추가가 되는데
    같은 라인에 [ 1 안드로이드 ] 이런식으로 출력할려면 어떻게 해야할까요?

  39. Blog Icon
    chrees

    감사합니다. ^^
    공부 많이 됐어요~

  40. Blog Icon
    웅;;

    getView 안에 있는 getSystemService 요 부분에서 에러가 나네요;;

    로그챗에서 이렇게 나오는데;
    The method getSystemService(String) is undefined for the type CustomArrayAdapter