http://developer.android.com/guide/topics/ui/menus.html
- Android 3.0 이상부터는 contextual action mode 라는 것이 생겨서, 선택된 content 에 대한 action 을 조금 다르게 처리해주어야 한다.
- Menu 의 종류는 다음과 같이 3개. Option menu ( 3.0 이상부터는 ActionBar 로 ), Context menu, 그리고 Popup menu 가 있다.
- Menu xml 구성요소는 <menu> <item> <group> 이 있다.
- android:showAsAction 은 action bar 에서 언제 그리고 어떻게 보여질지를 결정하는 attribute.
- menu xml 은 MenuInflater 를 이용하여 inflate.
- submenu는 <item> 하단에 바로 <menu> 를 등록함으로서 가능, submenu 는 또 다른 submenu 를 가질 수 없음.
- Android 3.0 부터는 Actionbar 의 우측에 Optional Menu 가 나타나며, 특정 item 에 대해 Action Bar 에 빼려면 다음 옵션을 주면 된다. android:showAsAction="ifRoom".
- Activity 에도, Fragment 에도 OptionMenu 를 설정했다면, 둘이 ActionBar 에 섞여서 나타난다. Activity 것이 먼저 나오고 Fragment 것이 뒤에 나온다. 여러 Fragment 에서 OptionMenu 를 설정했다면, add 되는 순서대로 나온다. 이 순서는 바굴 수 있는데, <item> 의 android:orderInCategory 옵션을 잘 조정하면 된다.
- HoneyComb ( Android 3.0 ) 이전에는 Menu 버튼을 최초로 누를 때 onCreateOptionMenu() 가 불리며 Menu 를 initialize 하지만, Android 3.0 이상부터는 Action Bar 에 메뉴 표시를 위해 Activity 가 create 되는 시점에 불린다.
- onOptionsItemSelected() 에서 return 값이 중요하다. super 는 default 로 false 를 return 한다. Fragment 에도 option menu 가 있는 경우에는 Activity 의 onOptionsItemSelected() 가 먼저 불리고, return 값이 true 가 될때까지, activity 에 붙은 순서대로 fragment들의 onOptionsItemSelected() 가 호출된다.
- Android 3.0 부터는 XML 에 android:onClick 속성을 추가할 수 있다. 속성값으로는 Activity 에 정의된 함수이름을 기술할 수 있으며, 이 함수는 public 으로 정의되고, MenuItem 을 single parameter 로 받는다. 메뉴가 click 되면 자동으로 이 함수가 callback 으로 불린다.
- 여러개의 Activity 가 같은 Menu 를 공유한다면, onCreateOptionMenu 와 onOptionsMenuSelected 만 구현한 Activity 를 만들고, 그 녀석을 상속시키는 방법이 좋다.
- onCreateOptionsMenu() 는 Menu 최초 생성시에만 호출되고, Runtime 에 Menu 를 바꾸고 싶다면, onPrepareOptionsMenu() 를 구현해주어야 한다. Android 3.0 미만의 버전에서는 메뉴 버튼이 눌릴 때마다 항상 이 함수가 호출되지만, 3.0 이상부터는 Menu 는 항상 보이는 존재이기 때문에, invalidOptionMenu() 를 호출해주어야 onPrepareOptionsMenu() 가 호출된다.
- View의 Focus 유무에 따른 Menu 의 갱신은 위험하다. Touch mode 에서는 focus 를 가질 수 없다. View 에 관련된 메뉴를 제공하고 싶다면 Context메뉴를 사용하라.
- Android 3.0 이상부터는 Contextual action mode 란 것이 추가되었는데. contextual action bar 라는 것이 추가되고, 앱이 allow 한다면, 여러개의 item 들에 대해 action 을 한번에 수행할 수 있다.
- Context Menu 는 registerForContextMenu() 를 통해 view 를 등록해줌으로서 가능하다. 만약 ListView 나 GridView 의 모든 Item 을 등록하고 싶다면, ListView 나 GridView 를 전달하면 자동으로 전달이 된다.
- onCreateContextMenu 에는 Click 된 view 와 함께 MenuInfo 가 함께 전달이 된다. 이 MenuInfo 에는 click 된 item 에 대한 추가 정보가 들어있다. 이건 여러 뷰가 동시에 ContextMenu 를 제공할 때, 유용하게 사용된다.
- Contextual action mode 는 user 가 item 을 선택( view long-click 또는 checkbox 등을 check )함으로서 enable 되고, enable 되면 화면 상단에 contextual action bar 가 나타난다. Contextual Action Mode 가 되면 user 는 여러개의 item 을 동시 선택할 수 있다. ( 제공한다면 ) 반대로 모든 아이템을 deselect 하거나, Back button 을 누르거나, Done 버튼을 눌렀을 때, Contextual Action Mode 는 종료되고, Contextual Action Bar 도 사라진다.
- Contextual Action Bar 가 일반 Action Bar 의 위치를 점유하긴 하지만, 다른 녀석이다.
- 각 View 에 Contextual Action Bar 등록하기.
ActionMode.Callback 을 구현하고, Activity.startActionMode( actionModeCallback ) 을 호출해준다.
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return true;
}
// Called each time the action mode is shown. Always called after
onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_share:
shareCurrentItem();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
// Called when the user exits the action mode
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
someView.setOnLongClickListener(new View.OnLongClickListener() {
// Called when the user long-clicks on someView
public boolean onLongClick(View view) {
if (mActionMode != null) {
return false;
}
// Start the CAB using the ActionMode.Callback defined above
mActionMode = getActivity().startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
- ListView 나 GridVIew ( or AbsListVIew 상속한 녀석 )에 Contextual Action 등록하기.
AbsListView.MultiChoiceModeListener 를 구현하여, AbsListView.setMultiChoiceModeListener( multiChoiceModeListener ) 에 등록해준다. AbsListView.setChoiceMode( CHOICE_MODE_MULTIPLE_MODAL ) 도 호출해주어야 한다.
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// Here you can do something when items are selected/de-selected,
// such as update the title in the CAB
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// Respond to clicks on the actions in the CAB
switch (item.getItemId()) {
case R.id.menu_delete:
deleteSelectedItems();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate the menu for the CAB
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context, menu);
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// Here you can make any necessary updates to the activity when
// the CAB is removed. By default, selected items are deselected/unchecked.
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here you can perform updates to the CAB due to
// an invalidate() request
return false;
}
});
- PopupMenu 는 API Level 11 이상부터 사용 가능.
public void showPopup(View v) {
PopupMenu popup = new PopupMenu(this, v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.actions, popup.getMenu());
// above two lines can be substituted for following one line if your API level is above 14.
// PopupMenu.inflate()
popup.show();
}
- Menu 를 Group화하면 setGroupVisible(), setGroupEnabled(), setGroupCheckable() 등을 설정할 수 있어 편하다. Grouping 되어도 다른 menu item 들과 같은 depth 에 있다. groupID 를 통해서 group item 을 일괄처리 할 수 있어 편하다. android:showAsAction="ifRoom" 도 마찬가지로 일괄적으로 적용된다.
- Option Menu 에 있는 Menu Item 은 checkbox 나 radio button 을 가질 수 없다. 만약 checkable 로 만들고 싶다면, 직접 state 관리도 하고, icon, text 등도 교체해주어야 한다.
- Context Menu 등을 checkable 로 만들기 위해서는 <item> 의 android:checkable 이나, <group> 의 android:checkableBehavior 를 설정해주어야 한다. value 는 single( radio ), all( checkbox ), none 이다. checkable item 을 설정해 준것은 callback 을 부르는 역할밖에 하지 못한다. Radio 나 Checkbox 토글은 직접 구현해주어야 한다.
- 특정 Activity 를 띄우는 Intent 가 있을 경우에만 Menu 를 나오게 하고싶다면, CATEGORY_ALTERNATIVE 나 CATEGORY_SELETED_ALTERNATIVE 를 이용하면 된다. Intent 를 하나 만들고 위 2개의 flag 중 하나 혹은 2개 모두를 setting 한다. Menu.addIntentOptions() 를 호출해주면, 이 intent 를 처리할 수 있는 activity 가 있을 때만 menu item 으로 등록하고 그렇지 않을 경우는 자동으로 등록되지 않는다. 등록될 때, target 이 되는 Activity 의 icon 과 label 이 사용된다.
- CATEGORY_SELECTED_ALTERNATIVE 는 현재 화면에서 선택된 element 에 대한 처리를 할 때 사용되는 녀석이기 때문에 onCreateContextMenu() 에서만 쓰인다.
- 반대로 내가 만드는 Activity 가 다른 App 의 Menu.addIntentOption 에 item 으로 등록될 수 있도록 하려면, Manifest 에 CATEGORY_ALTERNATIVE 와/나 CATEGORY_SELECTED_ALTERNATIVE 를 category 로 filter 에 넣어준다.
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[Android/안드로이드] Toast (0) | 2012.05.25 |
---|---|
[Android/안드로이드] Dialog 고급정보. (0) | 2012.05.25 |
[Android/안드로이드] Input Events. (0) | 2012.05.24 |
[Android/안드로이드] XML Layout. (0) | 2012.05.24 |
[Android/안드로이드] Thread 고급정보. (2) | 2012.05.23 |
댓글