목 차
1. AdapterViews & Adapters
A. ListView
B. Spinner
2. Layouts
3. Menu
A. Menu Example
B. 유용한 menu 기능
4. ActionBar
5. Dialogs
6. 시리즈 연재
* 이전 포스트에 이어지는 포스트입니다.
1. AdapterViews & Adapters
이전에 살펴봤던 ViewGroup들은 이미 정의된 데이터들을 다루는 것들이다. 즉, TimePicker나 DatePicker의 경우, ‘시간’ 혹은 ‘날짜’ 같이 이미 정의된 데이터 타입을 다루게 된다.
하지만 정의되지 않은 데이터를 다뤄야 할 경우는 어떨까? 이를 위해서 안드로이드 플랫폼에서는 AdapterView와 Adapter를 제공해준다. AdapterView 또한 ViewGroup을 상속 받고 있기 때문에 모든 AdapterView는 하나 이상의 View들을 가질 수 있다. 아래 그림을 살펴보자.
AdapterView : 순수하게 그림을 그리는 부분 만을 담당한다.
Adapter : 정보를 관리하고 이를 포장해서 View형태로 AdapterView에게 제공해주는 역할을 담당한다.
안드로이드에서 제공하는 AdapterView를 상속 받은 ViewGroup들은 관련된 하는 Adapter 또한 제공된다. Adapter의 기능이 부족할 경우에는 Adapter 혹은 Adapter의 Child Class를 다시 상속 받는 형태로 구현을 하기도 한다.
A. ListView
스크롤 가능한 형태로 View들을 보여주는 AdapterView이다.
Adapter는 ListAdapter이다.
[이미지]
[Layout]
<ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/listView" android:background="#ff000000" /> |
[code]
private ListView mListView = null; private ArrayAdapter<String> mAdapter = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); mListView = (ListView) findViewById(R.id.listView); mAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1); mAdapter.add("One"); mAdapter.add("Two"); mAdapter.add("Tree"); mListView.setAdapter(mAdapter); mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(getApplicationContext(), mAdapter.getItem(position).toString(), Toast.LENGTH_SHORT).show(); } }); } |
코드를 보면 알겠지만 ListView를 쓰기 위해서는 Adapter만 잘 만들어서 연결해주면 끝이다. 만약 문자열이 아닌 다른 형태로 ListView를 보여주고 싶다면 View 배치를 정리한 xml 파일을 만들고 Adapter를 상속 받아서 필요한 부분만 추가 구현해주면 된다.
B. Spinner
윈도우 프로그래밍에서의 콤보박스와 비슷한 녀석이다. 클릭시 Dialog 혹은 DropDown 형태로 선택 UI를 그려 준다.
스크롤 가능한 형태로 View들을 보여주는 AdapterView이다
SpinnerAdapter에 의해서 Item들이 관리된다.
[Layout]
<Spinner android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/spinner" /> |
[code]
private Spinner mSpinner = null; private ArrayAdapter<String> mAdapter = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); mSpinner = (Spinner) findViewById(R.id.spinner); mAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1); mAdapter.add("One"); mAdapter.add("Two"); mAdapter.add("Tree"); mSpinner.setAdapter(mAdapter); mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(getApplicationContext(), mAdapter.getItem(position).toString(), Toast.LENGTH_SHORT).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } |
2. Layouts
View들의 배치에 대해서 정책을 가지고 있는 ViewGroup이다. 레이아웃 이름에 따라서 배치에 대한 정책이 다르다. 내용이 너무 많아서 필요하다면 다음에 정리하고 여기서는 어떤 정책에 대해서만 간략히 정리한다.
[LinearLayout]
[RelativeLayout]
[FrameLayout]
[TableLayout]
아래 유투브 동영상을 보면 실제 예제 및 설명을 볼 수 있다.
3. Menu
최신 안드로이드는 ActionBar를 통해서 Menu를 제공하고 있다. ActionBar를 공부하기 전에 과거의 menu 방법부터 살펴보자. 메뉴는 다음과 같은 Type 이 있다.
Option menu : 유저가 menu 버튼을 클릭했을 때 보이는 메뉴다.
Submenu : 메뉴 중에 하나를 선택했을 보이는 하위 메뉴다.
Context menu : 특정 View를 오래 동안 누르고 있을 때 보이는 메뉴다.
Options 및 Submenu는 Activity 레벨에서 다뤄지는 메뉴이고 Context 메뉴는 View 레벨에서 다뤄지는 메뉴이다.
A. Menu Example
우선 [Option memu]다. 내 휴대폰에는 S/W 메뉴키가 없어서 해당 키는 캡쳐가 되지 않았다.
다음은 [submenu]다. 위에서 [세 번째 아이템]을 클릭했을 때 나타난다.
마지막은 [context menu]다. [New Button]을 오래 동안 누르고 있으면 나타난다.
Option menu와 비슷해 보이지만 혼동하지 말자. Context menu의 경우, submenu와 비슷하게 Dialog 처럼 나타난다.
아래는 실제 구현 코드다.
[layout.xml]
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context="com.tistory.kkangeva.realestatecalculator.OptionMenuMainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Button" android:id="@+id/button" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> </RelativeLayout> |
[menu.xml]
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context="com.tistory.kkangeva.realestatecalculator.ExampleActivty"> <item android:id="@+id/item_one" android:title="첫 번째 아이템" /> <item android:id="@+id/item_two" android:title="두 번째 아이템" /> <item android:id="@+id/item_three" android:title="세 번째 아이템"> <!-- 아래는 submenu가 됩니다 --> <menu> <item android:id="@+id/item_three_one" android:title="3-1 아이템"/> <item android:id="@+id/item_three_two" android:title="3-2 아이템"/> </menu> </item> </menu> |
[activity.java]
public class OptionMenuMainActivity extends Activity { private Button mButton = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_option_menu_main); mButton = (Button) this.findViewById(R.id.button); registerForContextMenu(mButton); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_option_menu_main, menu); return true; } private void makeToast(String message) { Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show(); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.item_one: makeToast("Menu item_one"); return true; case R.id.item_two: makeToast("Menu item_two"); return true; case R.id.item_three: makeToast("Menu item_three"); return true; case R.id.item_three_one: makeToast("Menu item_three_one"); return true; case R.id.item_three_two: makeToast("Menu item_three_two"); return true; default: return super.onOptionsItemSelected(item); } } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); getMenuInflater().inflate(R.menu.menu_option_context, menu); } @Override public boolean onContextItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.item_one: makeToast("Context item_one"); return true; case R.id.item_two: makeToast("Context item_two"); return true; case R.id.item_three: makeToast("Context item_three"); return true; case R.id.item_three_one: makeToast("Context item_three_one"); return true; case R.id.item_three_two: makeToast("Context item_three_two"); return true; default: return super.onContextItemSelected(item); } } } |
B. 유용한 menu 기능
내용이 너무 길어질 것 같아서 여기서는 다루지는 않는다.
메뉴 item들을 그룹핑 가능
메뉴 item들에 단축키를 할당 가능
메뉴 item에 intent를 할당 가능 ⇒ 메뉴 선택시 intent 발생 (개인적으로는 코드에서하는 것이 맞을 것 같다)
4. ActionBar
일반 데스크탑 S/W에서 ‘메뉴바’와 비슷한 역할을 수행하는 기능이라고 생각하면 된다. 이를 통해서 특정 기능에 손쉽게 접근할 수 있다. 아래는 편집기의 메뉴바를 예로 캡쳐해 본 거다.
AcitonBar는 결국 다른 형태의 메뉴일 뿐이다. 아래의 캡처는 이전 챕터의 결과를 가지고 두 가지만 수정해서 나온 결과다. 뭐가 달라졌을까? 우선 ‘메뉴바’ 같은 녀석이 생겼다. 안드로이드에서는 이것을 ‘ActionBar’라고 부른다. 여기에 [두 번째 아이템] 이라는 메뉴 아이템이 추가되었다. ‘ActionBar’에 있는 [두 번째 아이템]을 클릭할 경우, 메뉴에서 클릭한 것과 동일한 로직이 수행된다.
수정 포인트는 다음과 같다.
[menu.xml]
<item android:id="@+id/item_two" app:showAsAction="always" android:title="두 번째 아이템" /> |
showAsAction 라인이 추가되었다. 여기서는 always를 선택해서 항상 ActionBar에 보이도록 했는데 다른 옵션들도 존재한다.
[activity.java]
public class OptionMenuMainActivity extends ActionBarActivity { // … 중략 ... } |
부모 클래스를 Activity에서 ActionBarActivity로 변경하였다.
ActionBar의 장점은 어떤 것이 있을까? 개인적으로는 기존의 option menu와 context menu의 사이에 존재하는 느낌이다. ActionBar의 메뉴는 동적으로 변경이 용의 한 편이고 실제로도 그런 예제가 많이 보인다. 다른 장점으로는 매우 중요한 기능을 항상 화면에 보이게 할 수 있다는 것이다. 주로 ‘공유하기’, ‘검색하기’에 해당하는 기능을 ActionBar에 사용하더라.
5. Dialogs
사용자와의 상호작용을 위해서 사용되는 독립적인 윈도우이다. 아래와 같은 예들이 있다.
AlertDialog
ProgressDialog
DatePickerDialog
TimePickerDialog
실제로 나타나는 화면은 다음과 같다.
[AlertDialog]
[ProgressDialog]
[DatePickerDialog]
[TimePickerDialog]
사용 방법은 간단하다. 이전 메뉴 예제를 이용해서 화면에 띄우는 부분만 구현해 봤다.
@Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.item_one: AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this); alertBuilder.setTitle("Title"); alertBuilder.setMessage("message"); alertBuilder.setPositiveButton("YES", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); alertBuilder.setNegativeButton("NO", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); AlertDialog alertDialog = alertBuilder.create(); alertDialog.show(); return true; case R.id.item_two: ProgressDialog progressDialog = new ProgressDialog(this); progressDialog.setTitle("Title"); progressDialog.setMessage("message"); progressDialog.show(); return true; case R.id.item_three: makeToast("Menu item_three"); return true; case R.id.item_three_one: DatePickerDialog datePickerDialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() { @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { } }, 2015, 7, 5); datePickerDialog.setTitle("Title"); datePickerDialog.setMessage("message"); datePickerDialog.show(); return true; case R.id.item_three_two: TimePickerDialog timePickerDialog = new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() { @Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) { } }, 2, 2, true ); timePickerDialog.setTitle("Title"); timePickerDialog.setMessage("message"); timePickerDialog.show(); return true; default: return super.onOptionsItemSelected(item); } } |
6. 시리즈 연재
'소프트웨어 > 안드로이드앱' 카테고리의 다른 글
안드로이드 스타일과 테마 알기 (0) | 2015.07.15 |
---|---|
안드로이드 머티리얼 디자인에 대해서 (Material Design) (0) | 2015.07.14 |
[안드로이드 기초#7-1] UI 클래스들 (0) | 2015.07.05 |
[안드로이드 기초#6] 프래그먼트 (Fragment) (1) | 2015.07.04 |
[안드로이드 기초#5] 권한 (Permission) (0) | 2015.07.03 |