Android/ListView
[Android] 커스텀 리스트뷰 : Custom ListView - Layout : 레이아웃
croute
2011. 5. 4. 13:56
[Android] 커스텀 리스트뷰 : Custom ListView - Layout : 레이아웃
사실 리스트뷰는 안드로이드의 거의 모든 뷰를 그려낼 수 있는 녀석입니다.
특히 모바일의 특성상 목록에 대한 부분들이나, 여러가지를 선택하는 것들에 대해서 리스트 형식으로 보여주어야 하는 경우가 많기 때문이죠.
아이폰에는 테이블뷰 라는 녀석이 있죠. 그에 비견되는 녀석이 안드로이드의 리스트뷰입니다.
물론 아직은 인터페이스 빌더에 비해서 UI 작성쪽에서 후달리는^^; 경우가 많이 있지만, 그래도 이 놈 여러가지를 할 수 있어서 매력적입니다.
여기서는 간단하게 리스트뷰의 한 row(또는 cell)을 커스텀해서 구현하는 것에 대해 이야기 하려고 합니다.
결과적으로는 아래 스크린샷과 같은 프로젝트를 만들어 낼 것입니다.
먼저 중요한 몇가지 개념에 대해서 알아보도록 하겠습니다. ( Data, Adapter, Custom Layout, LayoutInflater )
필수개념 : Custom Layout - 커스텀 레이아웃 |
일반적으로 ListView는 안드로이드에서 제공하는 것들을 사용하면,
텍스트 하나를 출력하거나, 텍스트와 체크박스를 같이 두거나, 라디오버튼을 가지고 선택을 할 수 있다거나 하는 등의 레이아웃을 가질 수 있습니다.
여기서는 프로그래머가 직접 만든 Custom Layout을 리스트뷰에 사용할 것입니다.
하나의 레이아웃을 만들고, 데이터를 받아섯 세팅해주면,
각 아이템(리스트뷰의 한 아이템-row)마다 같은 레이아웃, 다른 데이터를 사용하게 될 것입니다.
간단하게는 여러 오픈 API 중 트위터 같이 트윗들을 모아서 보여주는 데이터가 있을 수 있습니다.
여기서는 트윗들을 보여주는것에 대해 이야기 합니다.
트위터를 보여줄 것이므로 이미지뷰(ImageView)와 여러개의 텍스트뷰(TextView)가 필요합니다.
간단한 예제를 만들것이므로, 유저의 스크린네임(ScreenName)과 텍스트(Text), 그리고 프로필 이미지만 보여줄 수 있는 레이아웃 만듭니다.
결과적으로는 아래의 이미지와 같은 row를 만들것입니다.
위의 레이아웃을 위한 코드는 다음과 같습니다.
/res/layout/list_view_row.xml
필수개념 : Layout Inflater - 레이아웃 인플레이터 : 레이아웃 객체로 뽑아내기 |
안드로이드에서는 Layout Inflater 라는 것을 이용해 xml 로 만들어둔 layout 을 자바 객체로 만들어서 사용할 수 있습니다.
번외적인 얘기로 잠깐 언급하고 가자면, 안드로이드에서 UI를 구성하는 방법은 3가지가 있습니다.
1. 자바 코드로 UI 만들기
2. XML로 UI 만들기
3. 자바 코드 및 XML을 함께 사용해 UI 만들기
1번과 2번을 사용하는것은 각각 장단점을 가지고 있기때문에, 저는 3번의 방법을 많이 사용합니다.
여기서도 3번 비스무례한 방법을 사용할 것입니다.
이미 XML로 만든 UI는 위의 Custom Layout에서 만들어두었습니다.
이제 이 레이아웃 리소스을 Inflater로 뽑아서 객체화 시켜 사용할 것입니다.
코드는 정말 간단합니다.
LayoutInflater 를 만들어줍니다.
이제 이 인플레이터 인스턴스를 통해 inflate 해서 객체를 뽑아내기만 하면 됩니다.
convertView 는 R.layout.list_view_row 이라는 녀석을 UI로 하는 View 객체로 탄생했습니다.
이 녀석이 바로 우리가 만들려던 XML 레이아웃의 뽑아내진 객체입니다.
위의 커스텀 레이아웃에서 보았던 그런 모양을 하고 있는 뷰죠.
이 커스텀 레이아웃과 어댑터를 결합해 사용자들에게 보여줄 리스트를 만들것입니다.
필수개념 : Data - 데이터 |
이번에는 리스트뷰에 넣을 데이터들을 만들 차례입니다.
여러가지 데이터들이 있겠지만, 위에서 언급했듯이, 트윗들을 보여줄 것입니다.
요즘 대세인 아이유에 대해 어떤 얘기들이 오가는지 트위터로 검색해 봅니다.
트윗을 검색하기 위해 아래와 같은 트윗 검색 API를 사용합니다.
http://search.twitter.com/search.json?
쿼리 스트링을 지정해 주어야 하는데, 한글은 검색이 제대로 이루어 지지 않으므로,
아이 이유 를 동시에 검색해서 아이유에 대한 트윗을 검색하도록 해봅니다.
http://search.twitter.com/search.json?q=아이+이유&page=1
이 API를 통해 검색된 결과는 더보기를 통해 확인 가능합니다.
이 데이터들을 코드상으로 받아오기 위해서는 간단한 절차가 필요합니다.
인터넷 통신을 하기 위해서는 퍼미션 하나가 필요합니다. AndroidManifest.xml 에 아래의 퍼미션을 추가해 줍니다.
우선 HttpClient 가 필요하고, HttpGet, 또는 HttpPost 등의 인스턴스가 필요합니다.
또 결과값을 받아주는 HttpResponse 도 필요하죠.
( 통신하는 방식은 여러가지가 있으니, 편한 코드를 사용하면 됩니다. )
2011.11.04 18:28 추가내용 아래의 코드는 Honeycomb에서 제대로 실행이 되지 않을 수 있습니다. android.os.NetworkOnMainThreadException이 발생하게 된다는군요. 위의 예외가 발생한 경우 참고하세요. ---> 강철삽질님의 블로그 : 48번글 |
이렇게 받아온 결과를 통해서 실제로 리스트를 만들 차례입니다.
이 검색 결과를 JSON 파싱을 통해 리스트로 만들어 주어야 하죠.
필수개념 : Adapter / Custom Adapter - 어댑터 / 커스텀 어댑터 |
어댑터는 매우 중요합니다. 데이터를 어떤 방식으로 보여줄지를 결정할 수 있기때문이죠.
데이터는 어댑터를 거치고나서 리스트뷰에 뿌려지게 됩니다.
어떻게, 어떤 모양으로, 어떤 방식을 거쳐서 화면에 보여질지는 Adapter에서 결정하면 됩니다.
모든 일들은 어댑터에서 일어나지요.
여기서는 BaseAdapter가 아닌, ArrayAdapter를 상속받아서 사용합니다.
(BaseAdapter를 상속받아서 사용해도 무방합니다.)
ArrayAdapter 의 generic 으로 TweetInfo 를 사용해 CustomAdapter 라는 어댑터를 만들어 줍니다.
여러 생성자들이 있지만, (Context , int , List<TweetInfo> ) 라는 생성자를 사용해 봅니다.
생성자의 파라미터들을 약간 고쳐 사용합니다.
어댑터는 입력된 리스트의 전체 길이만큼을 getView 라는 메소드를 통해 화면에 그려줍니다.
모든 처리는 getView() 에서 하면 됩니다.
getView() 의 파라미터를 보면 이번에 그려줄 녀석이 몇번째 position 인지등도 나와있으므로, 손쉽게 그릴 수 있습니다.
getItem 등의 여러 메소드들이 있지만, 이 예제에서는 중요하지 않으므로 override 하지 않습니다.
간단하게 다시 생각해보자면,
어댑터는 데이터를 리스트로 입력 받았고,
이 리스트의 길이만큼 getView를 호출해서 화면에 그려준다.
이때 기존에 xml로 만들어둔 layout을 객체화 하여 사용한다.
그리고 각 포지션에 맞는 데이터들을 불러내 convertView를 통해 화면에 세팅해준다.
입니다.
커스텀 어댑터의 전체 코드는 아래와 같습니다.
// 주석에도 써있지만, 논제에 맞지 않는 코드들은 배제하였습니다.
주제에 맞지 않는 부분은 최대한 배제하고 설명하려 했지만, 꼭 필요한 부분들은 추가적으로 들어가있습니다.
마지막으로 정리하면서 아래 세장의 그림들로 마무리를 지어 봅니다.
데이터를 리스트로 만들어 줍니다.
리스트뷰의 한 row에 사용될 레이아웃을 xml로 만들어 두고, LayoutInflater 를 통해 객체화 합니다.
이를 ListView에 보여줍니다.
끝으로 예제 프로젝트를 첨부합니다.
부족하다고 생각되는 부분이나, 여러 의견들은 댓글이나 방명록으로 알려주세요 ^^