티스토리 뷰
[Android] SDK 3.0(HoneyComb)이전 호환 가능한 액션바(Action Bar) 만들기
Unikys 2012. 4. 4. 23:47[안드로이드] 안드로이드 이전 버전도 호환가능한 액션바 만들기
이전에 올렸던 안드로이드 인터페이스 디자인 패턴 영상에(참고: [Android] UI Design patterns) 나왔던 액션 바 (Action Bar)를 만드는 방법에 대해서 알아보자.
- 참고: 액션 바(ActionBar)는 안드로이드 SDK 3.0 (HoneyComb) 이후 추가되어 보다 쉽게 사용이 가능하다. 하지만 3.0 이전 버전에서는 ActionBar가 존재하지 않는다.
하지만 그 이전의 안드로이드 버전에 호환이 불가능하기 때문에 무턱대고 사용했다간 호환성문제에 부딪칠 것이다. 따라서 안드로이드 개발자 사이트에서는 호환가능한 예제를 제공해주어서 이 문제를 해결하도록 도와주고 있다.(참고: http://developer.android.com/resources/samples/ActionBarCompat/index.html)
여기서 사용하는 방법은 ActionBar의 생성을 버전별로 다르게 도와주는 Helper를 두어서 버전마다 다르게 설정하는 방식을 이용하고 있다.
즉, 3.0 이후의 버전에서는 그냥 ActionBar를 이용하고, 그 이전의 버전에서는 지금 ActionBar에서 하고 있는 것을 하드코딩으로 넣도록 도와주고 있다. 그 이전에는 MenuInflater를 이용해서 타이틀바 대신 액션바를 만들어서 넣어주는 방식을 취하고 있다.
그럼 예제를 따라가면서 3.0 이전 버전의 액션바를 한번 만들어보자.
* 3.0 이후의 버전은 위의 참고 사이트에서 ActionBarHelperICS와 ActionBarHelperHoneyComb 을 참고.
0. 이후에 만들 파일들
- res/menu/event_list.xml
- res/layout/actionbar_compat.xml
- res/drawable/actionbar_compat_item.xml
- res/drawable/actionbar_compat_item_pressed.xml
- res/drawable/actionbar_compat_item_focused.xml
- ActionBarHelper.java
- ActionBarHelperBase.java
- SimpleMenu.java
- SimpleMenuItem.java
- ActionBarActivity.java
+ 기타 xml 파일들
1. res/menu/event_list.xml 만들기
: 사용할 메뉴의 xml을 만드는 작업이다. res 폴더에 가서 우클릭 > New > Android XML file 선택하고 아래와 같이 Resource Type을 Menu로 선택하고 Root Element를 menu로 선택하고 파일명을 입력하고 Finish를 누르자.
* 이후에도 여러개의 xml파일들을 만들어야한다.
: 만들고나서 다음과 같이 보여줄 아이템들을 설정하자.
:xml 파일을 텍스트로 살펴보면 다음과 같다. 위의 인터페이스를 사용하는 것이 불편하면 아래처럼 직접 xml 파일을 입력하면 된다.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/menu_invite"
android:title="@string/invite"
android:icon="@android:drawable/ic_menu_agenda"
android:orderInCategory="1"
android:showAsAction="always" />
<item android:id="@+id/menu_create_event"
android:title="@string/create_event"
android:icon="@android:drawable/ic_menu_save"
android:orderInCategory="0"
android:showAsAction="always" />
</menu>
2. ActionBarHelper 클래스 만들기
: 이 클래스는 abstract 클래스로 다른 안드로이드 버전에 따라 다른 ActionBarHelper를 리턴하게 될 것이다. 각 함수 설명은 영어로 된 주석이 있으니 참고하자. 여기서 static 함수인 createInstance에서 안드로이드의 버전에 따라 다르게 리턴하는 것을 볼 수 있다. 일단은 3.0 이전 버전에 맞는 액션바를 ActionBarHelperBase만 리턴하도록 했다. 생성자에 Activity를 받음으로써 해당하는 Activity에 액션바를 추가하는 방식으로 되어있다.
public abstract class ActionBarHelper {
protected Activity mActivity;
/**
* Factory method for creating {@link ActionBarHelper} objects for a
* given activity. Depending on which device the app is running, either a basic helper or
* Honeycomb-specific helper will be returned.
*/
public static ActionBarHelper createInstance(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// return new ActionBarHelperICS(activity);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.DONUT) {
// return new ActionBarHelperHoneycomb(activity);
} else {
return new ActionBarHelperBase(activity);
}
return new ActionBarHelperBase(activity);
}
protected ActionBarHelper(Activity activity) {
mActivity = activity;
}
/**
* Action bar helper code to be run in {@link Activity#onCreate(android.os.Bundle)}.
*/
public void onCreate(Bundle savedInstanceState) {
}
/**
* Action bar helper code to be run in {@link Activity#onPostCreate(android.os.Bundle)}.
*/
public void onPostCreate(Bundle savedInstanceState) {
}
/**
* Action bar helper code to be run in {@link Activity#onCreateOptionsMenu(android.view.Menu)}.
*
* NOTE: Setting the visibility of menu items in <em>menu</em> is not currently supported.
*/
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
/**
* Action bar helper code to be run in {@link Activity#onTitleChanged(CharSequence, int)}.
*/
protected void onTitleChanged(CharSequence title, int color) {
}
/**
* Sets the indeterminate loading state of the item with ID {@link R.id.menu_refresh}.
* (where the item ID was menu_refresh).
*/
public abstract void setRefreshActionItemState(boolean refreshing);
/**
* Returns a {@link MenuInflater} for use when inflating menus. The implementation of this
* method in {@link ActionBarHelperBase} returns a wrapped menu inflater that can read
* action bar metadata from a menu resource pre-Honeycomb.
*/
public MenuInflater getMenuInflater(MenuInflater superMenuInflater) {
return superMenuInflater;
}
}
3. ActionBarHelperBase 클래스 만들기
: 이 클래스가 Activity에 액션바를 추가하는 루틴을 만들게 되는 클래스이다. 여기서 getMenuInflater에서 내부 클래스인 WrappedMenuInflater 클래스를 보면 메뉴에 해당하는 xml파일을 읽어와서 각 아이템을 추가하는데, showAsAction의 추가적인 속성을 처리하는 것을 볼 수 있다. 보여주는 속성으로 되어있으면 xml 안에 있는 item을 메뉴에 추가하는 방식이다.
: 액션바의 추가는 onPostCreate함수에서 이루어진다. 여기서 사용하고 있는 SimpleMenu와 SimpleMenuItem을 간단하게 구현을 해서 추가해야한다.
- 이 소스에는 불필요한 소스가 꽤 많이 포함되어있다. 특히 새로고침을 할때 액션바에 프로그래스를 띄우는 소스도 포함되어있는데 참고할만할거 같아서 일단 놔두었다. 봐두면 요긴하게 사용할 수 있을 것이다.(setRefreshActionItemState 함수 등)
public class ActionBarHelperBase extends ActionBarHelper {
private static final String MENU_RES_NAMESPACE = "http://schemas.android.com/apk/res/android";
private static final String MENU_ATTR_ID = "id";
private static final String MENU_ATTR_SHOW_AS_ACTION = "showAsAction";
protected Set<Integer> mActionItemIds = new HashSet<Integer>();
protected ActionBarHelperBase(Activity activity) {
super(activity);
}
/**{@inheritDoc}*/
@Override
public void onCreate(Bundle savedInstanceState) {
mActivity.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
}
/**{@inheritDoc}*/
@Override
public void onPostCreate(Bundle savedInstanceState) {
mActivity.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.actionbar_compat);
setupActionBar();
SimpleMenu menu = new SimpleMenu(mActivity);
mActivity.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu);
mActivity.onPrepareOptionsMenu(menu);
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
if (mActionItemIds.contains(item.getItemId())) {
addActionItemCompatFromMenuItem(item);
}
}
}
/**
* Sets up the compatibility action bar with the given title.
*/
private void setupActionBar() {
final ViewGroup actionBarCompat = getActionBarCompat();
if (actionBarCompat == null) {
return;
}
LinearLayout.LayoutParams springLayoutParams = new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.FILL_PARENT);
springLayoutParams.weight = 1;
// Add Home button
SimpleMenu tempMenu = new SimpleMenu(mActivity);
SimpleMenuItem homeItem = new SimpleMenuItem(
tempMenu, android.R.id.home, 0, mActivity.getString(R.string.app_name));
homeItem.setIcon(android.R.drawable.ic_menu_revert);
addActionItemCompatFromMenuItem(homeItem);
// Add title text
TextView titleText = new TextView(mActivity, null, R.attr.actionbarCompatTitleStyle);
titleText.setLayoutParams(springLayoutParams);
titleText.setText(mActivity.getTitle());
actionBarCompat.addView(titleText);
}
/**{@inheritDoc}*/
@Override
public void setRefreshActionItemState(boolean refreshing) {
View refreshButton = mActivity.findViewById(R.id.actionbar_compat_item_refresh);
View refreshIndicator = mActivity.findViewById(
R.id.actionbar_compat_item_refresh_progress);
if (refreshButton != null) {
refreshButton.setVisibility(refreshing ? View.GONE : View.VISIBLE);
}
if (refreshIndicator != null) {
refreshIndicator.setVisibility(refreshing ? View.VISIBLE : View.GONE);
}
}
/**
* Action bar helper code to be run in {@link Activity#onCreateOptionsMenu(android.view.Menu)}.
*
* NOTE: This code will mark on-screen menu items as invisible.
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Hides on-screen action items from the options menu.
for (Integer id : mActionItemIds) {
menu.findItem(id).setVisible(false);
}
return true;
}
/**{@inheritDoc}*/
@Override
protected void onTitleChanged(CharSequence title, int color) {
TextView titleView = (TextView) mActivity.findViewById(R.id.actionbar_compat_title);
if (titleView != null) {
titleView.setText(title);
}
}
/**
* Returns a {@link android.view.MenuInflater} that can read action bar metadata on
* pre-Honeycomb devices.
*/
public MenuInflater getMenuInflater(MenuInflater superMenuInflater) {
return new WrappedMenuInflater(mActivity, superMenuInflater);
}
/**
* Returns the {@link android.view.ViewGroup} for the action bar on phones (compatibility action
* bar). Can return null, and will return null on Honeycomb.
*/
private ViewGroup getActionBarCompat() {
return (ViewGroup) mActivity.findViewById(R.id.actionbar_compat);
}
/**
* Adds an action button to the compatibility action bar, using menu information from a {@link
* android.view.MenuItem}. If the menu item ID is <code>menu_refresh</code>, the menu item's
* state can be changed to show a loading spinner using
* {@link com.example.android.actionbarcompat.ActionBarHelperBase#setRefreshActionItemState(boolean)}.
*/
private View addActionItemCompatFromMenuItem(final MenuItem item) {
final int itemId = item.getItemId();
final ViewGroup actionBar = getActionBarCompat();
if (actionBar == null) {
return null;
}
// Create the button
ImageButton actionButton = new ImageButton(mActivity, null,
itemId == android.R.id.home
? R.attr.actionbarCompatItemHomeStyle
: R.attr.actionbarCompatItemStyle);
actionButton.setLayoutParams(new ViewGroup.LayoutParams(
(int) mActivity.getResources().getDimension(
itemId == android.R.id.home
? R.dimen.actionbar_compat_button_home_width
: R.dimen.actionbar_compat_button_width),
ViewGroup.LayoutParams.FILL_PARENT));
if (itemId == R.id.menu_my_peeps) {
actionButton.setId(R.id.actionbar_compat_item_refresh);
}
actionButton.setImageDrawable(item.getIcon());
actionButton.setScaleType(ImageView.ScaleType.CENTER);
actionButton.setContentDescription(item.getTitle());
actionButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mActivity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item);
}
});
actionBar.addView(actionButton);
/* if (item.getItemId() == R.id.menu_my_peeps) {
// Refresh buttons should be stateful, and allow for indeterminate progress indicators,
// so add those.
ProgressBar indicator = new ProgressBar(mActivity, null,
R.attr.actionbarCompatProgressIndicatorStyle);
final int buttonWidth = mActivity.getResources().getDimensionPixelSize(
R.dimen.actionbar_compat_button_width);
final int buttonHeight = mActivity.getResources().getDimensionPixelSize(
R.dimen.actionbar_compat_height);
final int progressIndicatorWidth = buttonWidth / 2;
LinearLayout.LayoutParams indicatorLayoutParams = new LinearLayout.LayoutParams(
progressIndicatorWidth, progressIndicatorWidth);
indicatorLayoutParams.setMargins(
(buttonWidth - progressIndicatorWidth) / 2,
(buttonHeight - progressIndicatorWidth) / 2,
(buttonWidth - progressIndicatorWidth) / 2,
0);
indicator.setLayoutParams(indicatorLayoutParams);
indicator.setVisibility(View.GONE);
indicator.setId(R.id.actionbar_compat_item_refresh_progress);
actionBar.addView(indicator);
}
*/
return actionButton;
}
/**
* A {@link android.view.MenuInflater} that reads action bar metadata.
*/
private class WrappedMenuInflater extends MenuInflater {
MenuInflater mInflater;
public WrappedMenuInflater(Context context, MenuInflater inflater) {
super(context);
mInflater = inflater;
}
@Override
public void inflate(int menuRes, Menu menu) {
loadActionBarMetadata(menuRes);
mInflater.inflate(menuRes, menu);
}
/**
* Loads action bar metadata from a menu resource, storing a list of menu item IDs that
* should be shown on-screen (i.e. those with showAsAction set to always or ifRoom).
* @param menuResId
*/
private void loadActionBarMetadata(int menuResId) {
XmlResourceParser parser = null;
try {
parser = mActivity.getResources().getXml(menuResId);
int eventType = parser.getEventType();
int itemId;
int showAsAction;
boolean eof = false;
while (!eof) {
switch (eventType) {
case XmlPullParser.START_TAG:
if (!parser.getName().equals("item")) {
break;
}
itemId = parser.getAttributeResourceValue(MENU_RES_NAMESPACE,
MENU_ATTR_ID, 0);
if (itemId == 0) {
break;
}
showAsAction = parser.getAttributeIntValue(MENU_RES_NAMESPACE,
MENU_ATTR_SHOW_AS_ACTION, -1);
if (showAsAction == MenuItem.SHOW_AS_ACTION_ALWAYS ||
showAsAction == MenuItem.SHOW_AS_ACTION_IF_ROOM) {
mActionItemIds.add(itemId);
}
break;
case XmlPullParser.END_DOCUMENT:
eof = true;
break;
}
eventType = parser.next();
}
} catch (XmlPullParserException e) {
throw new InflateException("Error inflating menu XML", e);
} catch (IOException e) {
throw new InflateException("Error inflating menu XML", e);
} finally {
if (parser != null) {
parser.close();
}
}
}
}
}
4. SimpleMenu와 SimpleMenuItem 클래스 구현
: 액션바에서 사용할 메뉴 클래스와 메뉴 아이템 클래스이다. 이 클래스에서는 Menu 인터페이스를 구현하여 메뉴의 순서와 추가/삭제를 도와주는 함수들을 구현하면 된다. 액션바에서 다른 추가적인 함수들은 사용안하므로 구현을 안해도 된다.
: 먼저 SimpleMenu 클래스
public class SimpleMenu implements Menu {
private Context mContext;
private Resources mResources;
private ArrayList<SimpleMenuItem> mItems;
public SimpleMenu(Context context) {
mContext = context;
mResources = context.getResources();
mItems = new ArrayList<SimpleMenuItem>();
}
public Context getContext() {
return mContext;
}
public Resources getResources() {
return mResources;
}
public MenuItem add(CharSequence title) {
return addInternal(0, 0, title);
}
public MenuItem add(int titleRes) {
return addInternal(0, 0, mResources.getString(titleRes));
}
public MenuItem add(int groupId, int itemId, int order, CharSequence title) {
return addInternal(itemId, order, title);
}
public MenuItem add(int groupId, int itemId, int order, int titleRes) {
return addInternal(itemId, order, mResources.getString(titleRes));
}
/**
* Adds an item to the menu. The other add methods funnel to this.
*/
private MenuItem addInternal(int itemId, int order, CharSequence title) {
final SimpleMenuItem item = new SimpleMenuItem(this, itemId, order, title);
mItems.add(findInsertIndex(mItems, order), item);
return item;
}
private static int findInsertIndex(ArrayList<? extends MenuItem> items, int order) {
for (int i = items.size() - 1; i >= 0; i--) {
MenuItem item = items.get(i);
if (item.getOrder() <= order) {
return i + 1;
}
}
return 0;
}
public int findItemIndex(int id) {
final int size = size();
for (int i = 0; i < size; i++) {
SimpleMenuItem item = mItems.get(i);
if (item.getItemId() == id) {
return i;
}
}
return -1;
}
public void removeItem(int itemId) {
removeItemAtInt(findItemIndex(itemId));
}
private void removeItemAtInt(int index) {
if ((index < 0) || (index >= mItems.size())) {
return;
}
mItems.remove(index);
}
public void clear() {
mItems.clear();
}
public MenuItem findItem(int id) {
final int size = size();
for (int i = 0; i < size; i++) {
SimpleMenuItem item = mItems.get(i);
if (item.getItemId() == id) {
return item;
}
}
return null;
}
public int size() {
return mItems.size();
}
public MenuItem getItem(int index) {
return mItems.get(index);
}
// Unsupported operations.
public SubMenu addSubMenu(CharSequence charSequence) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public SubMenu addSubMenu(int titleRes) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public int addIntentOptions(int i, int i1, int i2, ComponentName componentName,
Intent[] intents, Intent intent, int i3, MenuItem[] menuItems) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void removeGroup(int i) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void setGroupCheckable(int i, boolean b, boolean b1) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void setGroupVisible(int i, boolean b) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void setGroupEnabled(int i, boolean b) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public boolean hasVisibleItems() {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void close() {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public boolean performShortcut(int i, KeyEvent keyEvent, int i1) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public boolean isShortcutKey(int i, KeyEvent keyEvent) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public boolean performIdentifierAction(int i, int i1) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void setQwertyMode(boolean b) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
}
: 다음은 SimpleMenuItem 클래스
: MenuItem을 구현하며 아이콘을 그려주는 부분이 중요
public class SimpleMenuItem implements MenuItem {
private SimpleMenu mMenu;
private final int mId;
private final int mOrder;
private CharSequence mTitle;
private CharSequence mTitleCondensed;
private Drawable mIconDrawable;
private int mIconResId = 0;
private boolean mEnabled = true;
public SimpleMenuItem(SimpleMenu menu, int id, int order, CharSequence title) {
mMenu = menu;
mId = id;
mOrder = order;
mTitle = title;
}
public int getItemId() {
return mId;
}
public int getOrder() {
return mOrder;
}
public MenuItem setTitle(CharSequence title) {
mTitle = title;
return this;
}
public MenuItem setTitle(int titleRes) {
return setTitle(mMenu.getContext().getString(titleRes));
}
public CharSequence getTitle() {
return mTitle;
}
public MenuItem setTitleCondensed(CharSequence title) {
mTitleCondensed = title;
return this;
}
public CharSequence getTitleCondensed() {
return mTitleCondensed != null ? mTitleCondensed : mTitle;
}
public MenuItem setIcon(Drawable icon) {
mIconResId = 0;
mIconDrawable = icon;
return this;
}
public MenuItem setIcon(int iconResId) {
mIconDrawable = null;
mIconResId = iconResId;
return this;
}
public Drawable getIcon() {
if (mIconDrawable != null) {
return mIconDrawable;
}
if (mIconResId != 0) {
return mMenu.getResources().getDrawable(mIconResId);
}
return null;
}
public MenuItem setEnabled(boolean enabled) {
mEnabled = enabled;
return this;
}
public boolean isEnabled() {
return mEnabled;
}
// No-op operations. We use no-ops to allow inflation from menu XML.
public int getGroupId() {
// Noop
return 0;
}
public View getActionView() {
// Noop
return null;
}
public MenuItem setActionProvider(ActionProvider actionProvider) {
// Noop
return this;
}
public ActionProvider getActionProvider() {
// Noop
return null;
}
public boolean expandActionView() {
// Noop
return false;
}
public boolean collapseActionView() {
// Noop
return false;
}
public boolean isActionViewExpanded() {
// Noop
return false;
}
@Override
public MenuItem setOnActionExpandListener(OnActionExpandListener onActionExpandListener) {
// Noop
return this;
}
public MenuItem setIntent(Intent intent) {
// Noop
return this;
}
public Intent getIntent() {
// Noop
return null;
}
public MenuItem setShortcut(char c, char c1) {
// Noop
return this;
}
public MenuItem setNumericShortcut(char c) {
// Noop
return this;
}
public char getNumericShortcut() {
// Noop
return 0;
}
public MenuItem setAlphabeticShortcut(char c) {
// Noop
return this;
}
public char getAlphabeticShortcut() {
// Noop
return 0;
}
public MenuItem setCheckable(boolean b) {
// Noop
return this;
}
public boolean isCheckable() {
// Noop
return false;
}
public MenuItem setChecked(boolean b) {
// Noop
return this;
}
public boolean isChecked() {
// Noop
return false;
}
public MenuItem setVisible(boolean b) {
// Noop
return this;
}
public boolean isVisible() {
// Noop
return true;
}
public boolean hasSubMenu() {
// Noop
return false;
}
public SubMenu getSubMenu() {
// Noop
return null;
}
public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener onMenuItemClickListener) {
// Noop
return this;
}
public ContextMenu.ContextMenuInfo getMenuInfo() {
// Noop
return null;
}
public void setShowAsAction(int i) {
// Noop
}
public MenuItem setShowAsActionFlags(int i) {
// Noop
return null;
}
public MenuItem setActionView(View view) {
// Noop
return this;
}
public MenuItem setActionView(int i) {
// Noop
return this;
}
}
5. ActionBarActivity 클래스 구현
: 이 클래스는 Activity를 확장하는 클래스로 액션바를 사용하고자하는 Activity는 이 클래스를 확장하면 된다. 위에서 구현한 ActionBarHelper를 가지고 onCreate나 onPostCreate 이벤트때 액션바를 초기화해준다.
public class ActionBarActivity extends Activity {
final ActionBarHelper mActionBarHelper = ActionBarHelper.createInstance(this);
/**
* Returns the {@link ActionBarHelper} for this activity.
*/
protected ActionBarHelper getActionBarHelper() {
return mActionBarHelper;
}
/**{@inheritDoc}*/
@Override
public MenuInflater getMenuInflater() {
return mActionBarHelper.getMenuInflater(super.getMenuInflater());
}
/**{@inheritDoc}*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActionBarHelper.onCreate(savedInstanceState);
}
/**{@inheritDoc}*/
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mActionBarHelper.onPostCreate(savedInstanceState);
}
/**
* Base action bar-aware implementation for
* {@link Activity#onCreateOptionsMenu(android.view.Menu)}.
*
* Note: marking menu items as invisible/visible is not currently supported.
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean retValue = false;
retValue |= mActionBarHelper.onCreateOptionsMenu(menu);
retValue |= super.onCreateOptionsMenu(menu);
return retValue;
}
/**{@inheritDoc}*/
@Override
protected void onTitleChanged(CharSequence title, int color) {
mActionBarHelper.onTitleChanged(title, color);
super.onTitleChanged(title, color);
}
}
6. 액션바가 들어갈 Activity 구현
:아래와 같이 ActionBarActivity를 확장하고
public class EventListActivity extends ActionBarActivity{
: 아래와 같이 함수를 오버라이드해서 메뉴를 초기화 및 메뉴를 눌렀을때의 이벤트 처리를 하면 된다.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.event_list, menu); // 위에서 만든 xml로 초기화
// Calling super after populating the menu is necessary here to ensure that the
// action bar helpers have a chance to handle this event.
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
break;
case R.id.menu_my_peeps:
//menu_my_peeps 처리
break;
case R.id.menu_search:
this.onSearchRequested();
break;
case R.id.menu_create_event:
// 액션바 menu_create_event 처리
return super.onOptionsItemSelected(item);
}
7. ActionBar에서 사용할 xml 파일들 설정하기
- actionbar_compat.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@id/actionbar_compat"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
</LinearLayout>
- actionbar_compat_item.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/actionbar_compat_item_pressed"
android:state_pressed="true" />
<item android:drawable="@drawable/actionbar_compat_item_focused"
android:state_focused="true" />
<item android:drawable="@android:color/transparent" />
</selector>
- actionbar_compat_item_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#eda700" />
</shape>
- actionbar_compat_item_focused.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#ef7000" />
</shape>
-
8. 기타 xml 파일 설정하기
: http://developer.android.com/resources/samples/ActionBarCompat/index.html에 나와있는 xml파일들을 가져와도 되고, 리소스를 이용하는 부분부분들을 수정해도 된다. 아래의 파일 내용들은 위의 사이트에 있는대로 가져온것이다. 스타일/설정에 따라 바꿔주자.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="actionbar_compat" type="id"/>
<item type="id" name="actionbar_compat_title" />
<item type="id" name="actionbar_compat_item_refresh_progress" />
<item type="id" name="actionbar_compat_item_refresh" />
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="actionbar_compat_height">48dp</dimen>
<dimen name="actionbar_compat_button_width">48dp</dimen>
<dimen name="actionbar_compat_button_home_width">56dp</dimen>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="AppTheme">
<attr name="actionbarCompatTitleStyle" format="reference" />
<attr name="actionbarCompatItemStyle" format="reference" />
<attr name="actionbarCompatItemHomeStyle" format="reference" />
<attr name="actionbarCompatProgressIndicatorStyle" format="reference" />
</declare-styleable>
<declare-styleable name="BezelImageView">
<attr name="maskDrawable" format="reference" />
<attr name="borderDrawable" format="reference" />
</declare-styleable>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="android:style/Theme.Light">
<item name="android:windowTitleSize">@dimen/actionbar_compat_height</item>
<item name="android:windowTitleBackgroundStyle">@style/ActionBarCompat</item>
<item name="android:windowContentOverlay">@drawable/actionbar_shadow</item>
<!-- for programmatic instantiation -->
<item name="actionbarCompatTitleStyle">@style/ActionBarCompatTitle</item>
<item name="actionbarCompatItemStyle">@style/ActionBarCompatItem</item>
<item name="actionbarCompatItemHomeStyle">@style/ActionBarCompatHomeItem</item>
<item name="actionbarCompatProgressIndicatorStyle">@style/ActionBarCompatProgressIndicator</item>
</style>
<style name="ActionBarCompat">
<item name="android:background">#eee</item>
</style>
<style name="ActionBarCompatItemBase">
<!-- layout_width/height must be set in code -->
<item name="android:scaleType">center</item>
<item name="android:background">@drawable/actionbar_compat_item</item>
</style>
<style name="ActionBarCompatProgressIndicator" parent="android:style/Widget.ProgressBar.Large">
<item name="android:indeterminate">true</item>
</style>
<style name="ActionBarCompatTitleBase">
<item name="android:id">@id/actionbar_compat_title</item>
<!-- layout_width/height/weight must be set in code -->
<item name="android:gravity">center_vertical</item>
<item name="android:textSize">14sp</item>
<item name="android:paddingLeft">6dp</item>
<item name="android:paddingRight">6dp</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">marquee</item>
</style>
<style name="ActionBarCompatTitle" parent="style/ActionBarCompatTitleBase">
<item name="android:textColor">@color/actionbar_title_color</item>
</style>
<style name="ActionBarCompatItem" parent="style/ActionBarCompatItemBase">
</style>
<style name="ActionBarCompatHomeItem" parent="style/ActionBarCompatItemBase">
</style>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="actionbar_title_color">#224894</color>
* 결과
- 이제 아이콘과 스타일을 자기 입맛에 맞게 수정하면 된다.
* 앞으로 다른 Activity에 액션바(ActionBar)를 추가하려면
a. 위의 1번의 액션바에 해당하는 xml을 만들고,
b. 6번 ActionBarActivity를 확장하고 초기화에서 위 a의 xml을 설정하고 이벤트들 처리해주고,
c. 8번 AndroidManifest.xml 에서 액션바 스타일을 설정해주면 된다.
- Total
- Today
- Yesterday
- mini project
- HTML5 튜토리얼
- gae
- TIP
- 안드로이드
- lecture
- ny-school
- Android
- 속깊은 자바스크립트 강좌
- php
- 강좌
- 자바스크립트
- 서울
- 사진
- Python
- Javascript
- GX-10
- google app engine
- 삼식이
- 안드로이드 앱 개발 기초
- K100D
- 팁
- 뽐뿌
- HTML5
- 탐론 17-50
- gre
- java
- Writing
- c++
- 샷
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |