어댑터 뷰(AdapterView)는 같은 종류의 뷰들을 특정한 방식으로 반복해서 보여주는데 적합하며,
ListView, GridView, Gallery, Spinner가 뷰 컨테이너 위젯에 속한다.
ListView
뷰 객체들을 수직 방향의 목록 형태로 보여준다. 수직 스크롤을 지원하며 일반적으로 목록의 각 항목은 자료를 담은 뷰이고, 사용자는 목록의 한 항목을 선택해서 일정한 작업을 수행한다.
GridView
뷰 객체들을 고정된 개수의 열들로 이루어진 격자(Grid) 형태(2차원의 표 형태)로 배치한다. 격자의 각 칸에 이미지 아이콘이 배치되는 경우가 많으며 사용자는 한 항목을 선택해서 일정한 작업을 수행한다.
Gallery
뷰 객체들을 수평 방향의 목록 형태로 표시한다. 수평 스크롤을 지원하며 이미지를 표시하는데 흔히 쓰인다. 사용자는 한 항목을 선택해서 일정한 작업을 수행한다.
Spinner
목록을 표시한다는 면에서 리스트뷰와 용도가 동일하나 ListView는 항상 펼쳐져 있는데 비해 Spinner는 클릭할 때만 팝업으로 펼쳐진다. 흔히 콤보박스라고 부르는 컨트롤이 바로 Spinner 위젯이며 화면이 좁은 모바일 환경에서 면적을 적게 차지하는 장점이 있지만 목록을 보려면 팝업을 열어야 하는 단점이 있다.
모든 위젯의 공동 조상인 AdapterView는 ViewGroup으로 부터 파생되므로 어댑터 뷰는 항복에 해당하는 여러 개의 차일드 뷰를 가질 수 있다 뿐만 아니라 linear, relative 같이 배치만 담당하는 레이아웃과는 달리 사용자와 상호 작용도 처리하므로 터치나 키패드로 항목을 선택할 수도 있다.
위의 위젯들을 adapter View 라고 부르는 이유는 표시할 항목 데이터를 adapter 객체로부터 공급받기 때문이다. 항목의 개수는 이론적으로 무한대일 뿐만 아니라 실행 중에 목록이 바뀔 수도 있으며 데이터의 원본도 다양하다. 이런 복잡한 데이터를 위젯이 직접 처리하는것은 효율적이지 못하므로 두 객체가 협동적으로 동작한다.
adapter은 원본으로부터 얻은 데이터를 관리하며 adapterView는 adapter가 전달한 데이터를 화면에 표시한다.
위젯과 연결될 수 있는 adapter들의 계층은 아래 그림과 같다.
최상위의 Adapter 인터페이스는 AdapterView와 데이터 간의 연결을 제공하고 항목의 집합을 관리하는 기본적인 method를 선언한다.
Adapter로부터 두 개의 인터페이스가 파생되는 데 ListAdapter와 SpinnerAdapter interface이다.
ListAdapter : ListView와 연결에 필요한 method를 정의한다.
SpinnerAdapter : Spinner와 연결에 필요한 method를 정의한다.
둘다 인터페이스이기 때문에 method가 구현되어 있지는 않다.
추상클래스 BaseAdapter에서 위에 두 interface의 method 중 기본적인 것을 구현한다.
또 BaseAdapter의 파생 클래스가 있는데 이 클래스들은 항목의 원본이 어디인가에 따라 아래처럼 나누어진다.
ArrayAdapter : 객체 배열이나 리소스에 정의된 배열로부터 데이터를 가져온다.
CursorAdapter : 데이터 베이스로부터 데이터를 공급받는다.
SimpleAdapter : xml 파일의 정적인데이터를 원본으로 사용한다.
어떠한 경로든 Adapter는 원본에서 구한 데이터로 뷰를 만들 책임이 있으며 adapter가 제공하는 View는 AdapterView에 항복 하나로 표시된다.
컨텍스트 메뉴는 옵션 메뉴와 거의 동일하다. 하지만 옵션메뉴처럼 메뉴버튼에 자동 등록된 녀석이 아니라 원하는 뷰마다 사용가능한 녀석이기 때문에 "등록" 이라는 메소드가 하나 추가되어 있다.
컨텍스트 메뉴를 생성하기 위해서는 아래 4가지 메소드를 재정의 합니다.
public void registerForContextMenu(View view)
- 특정 뷰에 컨텍스트 메뉴를 추가하고자 할때 매개변수로 등록하고자 하는
뷰를 넣어 메소드를 호출한다. 필요하다면 여러개 뷰의 등록도 가능하다.
public boolean onCreateContextMenu (ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo)
- 특정 뷰를 컨텍스트메뉴로 등록하였하면 해당 뷰를 롱클릭하면 onCreateContextMenu가 자동 호출된다. 복수의 등록이 가능하므로 2번째 매개변수를 통해 이벤트가 발생한 View를 알수 있으며 3번째 매개변수를 표시해야 할 아이템의 추가적인 정보를 담고 있습니다.
이 정보는 매개변수 v 에 따라 매우 다양하게 제공된다. 옵션메뉴와 다른 점은 이 메소드는 컨텍스트 메뉴가 사용될 때마다 호출된다는 점이다. 그렇기 때문에 옵션메뉴에 있던 onPrepareOptionsMenu() 가 컨텍스트메뉴에는 필요하지 않다.
public boolean onContextItemSelected (MenuItem item)
- 컨텍스트 메뉴의 항목을 선택했을때 호출되는 메소드.
매개변수로 넘어온 item은 사용자가 선택한 메뉴 항목이다.
void onCreatecontextMenu(ContextMenu menu)
- 자신이 필요한 컨텍스트메뉴를 개별적으로 재정의 하여 사용한다.
MenuTestActivity02.java
package com.example.menu.test;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MenuTestActivity02 extends Activity {
TextView tv;
Button colorBtn;
Button sizeBtn;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView)findViewById(R.id.testView);
colorBtn = (Button)findViewById(R.id.colorBtn);
sizeBtn = (Button)findViewById(R.id.sizeBtn);
//컨텍스트 메뉴에 등록을 합니다.
//이제 버튼을 꾸~욱 누르면 메뉴가 나타 납니다.
registerForContextMenu(colorBtn);
registerForContextMenu(sizeBtn);
}
//버튼에 따라 보여지는 메뉴를 구성합니다.
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
if(v == colorBtn){
//롱클릭이 발생한 뷰가 colorBtn이라면
menu.add(0, 0, 1, "빨강");
menu.add(0, 1, 1, "노랑");
menu.add(0, 2, 1, "파랑");
}else if(v == sizeBtn){
//롱클릭이 발생한 뷰가 sizeBtn이라면
menu.add(0, 3, 2, "작게");
menu.add(0, 4, 2, "보통");
menu.add(0, 5, 2, "크게");
}
super.onCreateContextMenu(menu, v, menuInfo);
}
//아이템을 선택하면 자동으로 실행되는 메소드 입니다.
@Override
public boolean onContextItemSelected(MenuItem item) {
서브 메뉴는 OptinosMenu와 ContextMenu에서 공통적으로 사용되는 메뉴이다.
일반적으로 두메뉴의 하위에 구성된 메뉴를 말한다. 기존에 작성한 메뉴들은 사용자가 메뉴항목을 선택하면 onXXxxxxxItemSelected() 메소드가 호출되어 해당 메소드에서 정의된 작업을 수행하게 되지만 Sub Menu로 구성된 항목을 선택하면 또다른 메뉴가 리스트 형태로 출력이 된다.
서브메뉴는 다른 메뉴들과는 다르지만 독립적으로 관리되는 것이 아니라 일반메뉴에 포함된 형태로 여겨지기 때문에 코드상에 모두 작성하면 된다.
서브메뉴에 서브메뉴를 추가하면 실행시 아래와 같은 에러가 발생합니다.
E/AndroidRuntime( 9248): java.lang.UnsupportedOperationException: Attempt to add a sub-menu to a sub-menu.
MeunTestActivity03.java
package com.example.menu.test;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MenuTestActivity03 extends Activity {