2013년 4월 23일 화요일

[Android] Action Bar ActionProvider

ActionProvider

ActionProvider는 하나의 component 안에서 다양한 메뉴의 상호작용을 의미한다. ActionProvider는 Action Bar에서 사용 할 수 있는 Action View를 생성하며, MenuItem에 서브메뉴를 동적으로 채운다. 그리고 기본 메뉴의 아이템을 처리합니다. ActionProvider는 MenuItem만을 위한 옵션을 설정할 수도 있으며, 간단한 버튼을 표시할때는 Action View를 만들어 표시 할 것이다.

ActionProvider는 추상 메서드로서 필요한 메서드를 Override해서 사용 할 수 있습니다. API Level 16부터 onCreateActionView()는 deprecated 되었으며 onCreateActionView(MenuItem forItem)이 추가 되었습니다. onCreateActionView() 메서드를 사용 하려면 android:targetSdkVersion을 16미만으로 적용 하시면 됩니다. onCreateActionView(MenuItem forItem)에서 MenuItem이 매개변수로 추가된 이유는 MenuItem을 재정의 할 수 있게 할려고 한게 아닌가 싶습니다. onCreateOptionsMenu(Menu menu)에서 정의된 Menu를 사용 할 수도 있겠지만 MenuItem만을 위한 재정의를 할 수 있게 추가 된게 아닐까 생각합니다. targetSdkVersion만 맞춰준다면 현재로서는 어떤 메서드를 사용하든지 상관 없으나 이왕이면 deprecated된 메서드 보다는 새로 추가 된 메서드를 사용 하시는걸 추천 합니다.

이번 포스팅에서는 Open Source 중 ActionBarSettingsActionProviderActivity에 대해 살펴 볼려고 합니다.
<?xml version=”1.0” encoding=”utf-8”?>
<menu xmlns:android=”http://schemas.android.com/apk/res/android”>

    <item android:id=”@+id/menu_item_action_provider_action_bar”
        android:showAsAction=”ifRoom”
        android:title=”@string/btn_api_provider_setting”
        android:actionProviderClass=”com.example.wawoops_test_actionbar.ActionBar_Api_Provider_Setting$SettingActionProvider”/>

    <item android:id=”@+id/menu_item_action_provider_overflow”
        android:showAsAction=”never”
        android:title=”@string/btn_api_provider_setting”
        android:actionProviderClass=”com.example.wawoops_test_actionbar.ActionBar_Api_Provider_Setting$SettingActionProvider”/>
</menu>
Menu를 보면 item이 2개인 것을 보실 수 있습니다. 여기서 주의깊에 봐야 할 부분은 android:showAsAciton부분입니다. 첫번째 item은 "ifRoom"으로 되어있고 두번째 item은 "never"로 되어있습니다. 첫번째 item은 만약 ActionBar에 공간이 있다면 표시하라는 뜻이며 두번째  item의 "never"는 overflow 영역으로 무조건 빼라는 뜻입니다. 즉 화면서 바로 보지 않겠다는 뜻입니다.
android:actionProviderClass를 설정하면 ActionProvider를 사용 할 수 있습니다. ActionProvider를 extends 하고 있는 클래스 경로명을 적어주면 되며, setActionProvider(ActionProvider)를 사용하여 자바코드에서도 설정해 줄 수 있습니다. 만약 공간이 부족해서 Overflow부분으로 빠진다면 텍스트가 보여져야 되므로 이왕이면 Title은 각 item마다 설정해 주는게 좋습니다.

public class ActionBarSettingsActionProviderActivity extends Activity {

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // TODO Auto-generated method stub
  getMenuInflater().inflate(R.menu.action_bar_settings_action_provider, menu);
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  // TODO Auto-generated method stub
  Toast.makeText(this, "선택된 버튼의 타이틀 : " + item.getTitle(), Toast.LENGTH_SHORT).show();
  return true;
 }
 
 public static class SettingActionProvider extends ActionProvider{
  private static final String TAG = "SettingActionProvider";
  private final Context mContext;
  private final Intent sSettingsIntent = new Intent(Settings.ACTION_SETTINGS);
  public SettingActionProvider(Context context) {
   super(context);
   // TODO Auto-generated constructor stub
   mContext = context;
  }

  @Override
  public View onCreateActionView(MenuItem forItem) {
   // TODO Auto-generated method stub
//   actionBar 영역에 들어가는 itme을 재정의 해 줄 수 있다. 
//   메뉴 버튼과 actionBar의 버튼을 서로 다르게 정의 할 수 있다.
//   forItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
   LayoutInflater layoutInflater = LayoutInflater.from(mContext);
   View view = layoutInflater.inflate(R.layout.action_bar_settings_action_provider, null);
   ImageButton button = (ImageButton) view.findViewById(R.id.button);
   button.setOnClickListener(new View.OnClickListener() {
    
    @Override
    public void onClick(View v) {
     // TODO Auto-generated method stub
     mContext.startActivity(sSettingsIntent);
    }
   });
   return view;
  }

  @Override
  @Deprecated
  public View onCreateActionView() {
   // TODO Auto-generated method stub
   return null;
  }

  @Override
  public boolean onPerformDefaultAction() {
   // TODO Auto-generated method stub
   Log.e(TAG, "onPerformDefaultAction()");
   mContext.startActivity(sSettingsIntent);
   return true;
  }
 }
}
onCreateOptionsMenu(Menu menu)에서  Menu를 inflate 해주면 Menu 버튼과 Action Bar 두곳 모두에서 사용 할 수가 있습니다. 이전 포스팅한 글에서 Menu는 Menu 버튼을 클릭하면 나타나는 것이고 MenuItem은 Action Bar에서 나타난다고 말했습니다. ActionProvider가 onCreateOptionsMenu(Menu menu)에서 inflate되는 Menu를 MenuItem에 추가 하는 기능을 합니다. 만약 onOptionsItemSelected(MenuItem item)가 호출 되지 않았다면 ActionProvider의 onPerformDefaultAction()이 호출 되었을 겁니다.  onPerformDefaultAction()은 Overflow 영역에 있을때 호출되며 이 메서드가 호출되면 onOptionsItemSelected(MenuItem item)은 호출 되지 않습니다.

소스에서는 onCreateActionView(MenuItem forItem)에서 inflate해준 view에 클릭 이벤트를  줬습니다. 이 결과 onPerformDefaultAction()와  onOptionsItemSelected(MenuItem item)가 호출 되지 않았으며 바로 onClick(View v)메서드가 호출되는 것을 확인 하였습니다. 간단하게 onCreateActionView(MenuItem forItem)메서드에서 만들어 놓은 레이아웃을 inflate 해주고 바로 이벤트를 걸어 사용 하면 되지 않을까 생각됩니다. onCreateActionView(MenuItem forItem)에서 버튼 하나를 만들어서 붙여 본 결과  onCreateOptionsMenu(Menu menu)에서 추가된 item 개수만큼 버튼이 생기는걸 확인 할 수 있었습니다.(물론 Action Bar에서 보여 질수 있는 item에 한해서 말하는 것입니다.)


참조

댓글 없음:

댓글 쓰기