Skip to content

Instantly share code, notes, and snippets.

@xian
Forked from JakeWharton/ActionBarSherlockRobolectric.java
Last active December 14, 2015 07:48
Show Gist options
  • Save xian/5052673 to your computer and use it in GitHub Desktop.
Save xian/5052673 to your computer and use it in GitHub Desktop.
Here's the magic to get ActionBarSherlock working with Robolectric 2.0-alpha-2!

You need to add the files below, and do this once in your base test runner:

ActionBarSherlock.registerImplementation(ActionBarSherlockRobolectric.class);
ActionBarSherlock.unregisterImplementation(ActionBarSherlockNative.class);
ActionBarSherlock.unregisterImplementation(ActionBarSherlockCompat.class);
// Copyright 2012 Square, Inc. License: Apache 2.
package com.squareup.test;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import com.actionbarsherlock.ActionBarSherlock;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.internal.ActionBarSherlockCompat;
import com.actionbarsherlock.internal.ActionBarSherlockNative;
import com.actionbarsherlock.view.MenuInflater;
import com.squareup.test.actionbarsherlock.SherlockMenuInflater;
import static org.robolectric.Robolectric.shadowOf;
/**
* During initialization, {@link ActionBarSherlock} figures out which {@link
* com.actionbarsherlock.app.ActionBar} to use based on the API level. It does this by checking the
* Build.Version.SDK_INT value which depends on the hidden <i>SystemProperties</i> class.
*
* Because Roboelectric does not have this, it always returns <code>0</code> for its API level
* causing {@link ActionBarSherlock} to crash. This class helps resolve this issue by providing
* an {@link ActionBarSherlockNative} implementation for API level 0.
* @see ActionBarSherlock#registerImplementation(Class)
*/
@ActionBarSherlock.Implementation(api = 0)
public class ActionBarSherlockRobolectric extends ActionBarSherlockCompat {
final private ActionBar actionBar;
public ActionBarSherlockRobolectric(Activity activity, int flags) {
super(activity, flags);
actionBar = new MockActionBar(activity);
}
@Override public void setContentView(int layoutResId) {
LayoutInflater layoutInflater = LayoutInflater.from(mActivity);
View contentView = layoutInflater.inflate(layoutResId, null);
shadowOf(mActivity).setContentView(contentView);
}
@Override public void setContentView(View view) {
shadowOf(mActivity).setContentView(view);
}
@Override public ActionBar getActionBar() {
return actionBar;
}
@Override protected Context getThemedContext() {
return mActivity;
}
@Override public MenuInflater getMenuInflater() {
if (mMenuInflater == null) {
mMenuInflater = new SherlockMenuInflater(mActivity);
}
return mMenuInflater;
}
}
// Copyright 2012 Square, Inc. License: Apache 2.
package com.squareup.test;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.SpinnerAdapter;
import com.actionbarsherlock.app.ActionBar;
public class MockActionBar extends ActionBar {
String title;
String subtitle;
View customView;
Context realContext;
public MockActionBar(Context context) {
realContext = context;
}
@Override public void setCustomView(View view) {
setCustomView(view, null);
}
@Override public void setCustomView(View view, LayoutParams layoutParams) {
this.customView = view;
}
@Override public void setCustomView(int resId) {
}
@Override public void setIcon(int resId) {
}
@Override public void setIcon(Drawable icon) {
}
@Override public void setLogo(int resId) {
}
@Override public void setLogo(Drawable logo) {
}
@Override
public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) {
}
@Override public void setSelectedNavigationItem(int position) {
}
@Override public int getSelectedNavigationIndex() {
return 0;
}
@Override public int getNavigationItemCount() {
return 0;
}
@Override public void setTitle(CharSequence title) {
this.title = (String) title;
}
@Override public void setTitle(int resId) {
title = realContext.getString(resId);
}
@Override public void setSubtitle(CharSequence newSubtitle) {
subtitle = (String) newSubtitle;
}
@Override public void setSubtitle(int resId) {
subtitle = realContext.getString(resId);
}
@Override public void setDisplayOptions(int options) {
}
@Override public void setDisplayOptions(int options, int mask) {
}
@Override public void setDisplayUseLogoEnabled(boolean useLogo) {
}
@Override public void setDisplayShowHomeEnabled(boolean showHome) {
}
@Override public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
}
@Override public void setDisplayShowTitleEnabled(boolean showTitle) {
}
@Override public void setDisplayShowCustomEnabled(boolean showCustom) {
}
@Override public void setBackgroundDrawable(Drawable d) {
}
@Override public View getCustomView() {
return customView;
}
@Override public CharSequence getTitle() {
return title;
}
@Override public CharSequence getSubtitle() {
return subtitle;
}
@Override public int getNavigationMode() {
return 0;
}
@Override public void setNavigationMode(int mode) {
}
@Override public int getDisplayOptions() {
return 0;
}
@Override public Tab newTab() {
return null;
}
@Override public void addTab(Tab tab) {
}
@Override public void addTab(Tab tab, boolean setSelected) {
}
@Override public void addTab(Tab tab, int position) {
}
@Override public void addTab(Tab tab, int position, boolean setSelected) {
}
@Override public void removeTab(Tab tab) {
}
@Override public void removeTabAt(int position) {
}
@Override public void removeAllTabs() {
}
@Override public void selectTab(Tab tab) {
}
@Override public Tab getSelectedTab() {
return null;
}
@Override public Tab getTabAt(int index) {
return null;
}
@Override public int getTabCount() {
return 0;
}
@Override public int getHeight() {
return 0;
}
@Override public void show() {
}
@Override public void hide() {
}
@Override public boolean isShowing() {
return false;
}
@Override public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
}
@Override
public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
}
}
// Copyright 2012 Square, Inc. License: Apache 2.
package com.squareup.test.actionbarsherlock;
import android.content.Context;
import android.util.AttributeSet;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.SubMenu;
import org.robolectric.internal.Implementation;
import org.robolectric.res.MenuNode;
import org.robolectric.res.ResName;
import org.robolectric.res.ResourceLoader;
import org.robolectric.util.I18nException;
import static org.robolectric.Robolectric.shadowOf;
/**
* Inflates menus that are part of ActionBarSherlock instead. Uses ABS custom {@link
* com.actionbarsherlock.view.Menu} instead of the stock one.
*/
public class SherlockMenuInflater extends MenuInflater {
private final Context context;
public SherlockMenuInflater(Context context) {
super(context);
this.context = context;
}
@Implementation
public void inflate(int resource, Menu root) {
String qualifiers = shadowOf(context.getResources().getConfiguration()).getQualifiers();
ResourceLoader resourceLoader = shadowOf(context).getResourceLoader();
ResName resName = shadowOf(context).getResName(resource);
MenuNode menuNode = resourceLoader.getMenuNode(resName, qualifiers);
try {
addChildrenInGroup(menuNode, 0, root);
} catch (I18nException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("error inflating " + resName, e);
}
}
private void addChildrenInGroup(MenuNode source, int groupId, Menu root) {
for (MenuNode child : source.getChildren()) {
String name = child.getName();
AttributeSet attributes = shadowOf(context).createAttributeSet(child.getAttributes(), null);
if (name.equals("item")) {
if (child.isSubMenuItem()) {
SubMenu sub = root.addSubMenu(groupId,
attributes.getAttributeResourceValue("android", "id", 0),
0, attributes.getAttributeValue("android", "title"));
MenuNode subMenuNode = child.getChildren().get(0);
addChildrenInGroup(subMenuNode, groupId, sub);
} else {
root.add(groupId,
attributes.getAttributeResourceValue("android", "id", 0),
0, attributes.getAttributeValue("android", "title"));
}
} else if (name.equals("group")) {
int newGroupId = attributes.getAttributeResourceValue("android", "id", 0);
addChildrenInGroup(child, newGroupId, root);
}
}
}
}
@mag
Copy link

mag commented Jun 20, 2013

Christian, this code has a square copyright on it. Can you slap an open source license on it so we can integrate it without license uncertainty?

@mag
Copy link

mag commented Aug 16, 2013

Christian, do you have a moment to change this to something like MIT or Apache license?

@edatkinvey
Copy link

is this still needed for Robolectric 2.1.1?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment