您的位置:首页 > 其它

HoloEverywhere 分析(一)

2013-12-20 10:51 61 查看
由于Android3.0以上版本才有ActionBar,所以如果要在Android3.0以下的版本用上ActionBar似乎是一件不可能的事情,至少对于新手来说几乎不可能实现,对于一般的老手也没有一个完整的解决方案,即要适配新版本又要在低版本上用到Actionbar.不过很幸运的是已经有牛人实现这一工作,我们要做的就是学会使用它就好,但是你肯定很想知道到底牛人是怎么实现的,去github上找源码吧.

我也很想知道牛人是怎么实现的,毕竟结果不重要,重要的是思路,想法,对吧?那让我们一起来分析他们的思路与想法吧!

最近只看了HoloEverywhere Library中的android.support.v7.app包.这个包中有如下几个类:

ActionBarActivity.java
ActionBar.java
ActionBarImplICS.java
ActionBarImplBase.java
ActionBarImplHC.java
ActionBarActivityDelegate.java
ActionBarActivityDelegateICS.java
ActionBarActivityDelegateBase.java
ActionBarActivityDelegateHC.java

现在来分析一下这个类的关系.首先这9个类分为三大类:

第一类只有一个类:ActionBarActivity.java,这是一个单独的类,是对外提供给使用者使用的类.看类声明就知道,只有这个类的权限是public权限,如果需要用ActionBar,在Activity中继承这个类就可以.这个类对所有版本使用ActivityBar进行了封装和统一管理.会根据不同的Android版本自动适配不同的ActionBar且提供了统一的接口(方法)对ActionBar进行操作.

第二类有四个类:ActionBarActivityDelegate.java ActionBarActivityDelegateICS.java ActionBarActivityDelegateBase.java ActionBarActivityDelegateHC.java

通过阅读源码知道,其实ActionBarActivity工作很简单,里面是通过ActionBarActivityDelegate类的一个实现来操作ActionBar的.所以真正的工作是ActionBarActivityDelegate这个类来完成的,所有版本适配工作都是在这个类中完成.那么他是怎么完成的呢?

是在ActionBarActivityDelegate中的一个静态方法实现的.

static ActionBarActivityDelegate createDelegate(ActionBarActivity activity) {
final int version = Build.VERSION.SDK_INT;
if (version >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return new ActionBarActivityDelegateICS(activity);
} else if (version >= Build.VERSION_CODES.HONEYCOMB) {
return new ActionBarActivityDelegateHC(activity);
} else {
return new ActionBarActivityDelegateBase(activity);
}
}
如果是在4.0版本上,返回ActionBarActivityDelegateICS实例,如果是3.0以上返回ActionBarActivityDelegateHC实例,如果是3.0以下的所有版本都返回ActionBarActivityDelegateBase实例.看类结构可以发现类关系



所以不同的版本交由不同的类去处理,而ActionBarActivityDelegate只是一个抽象类,提供一些接口而已.所以再往下看,看看具体实现.主要看看createSupportActionBar()方法的实现.

在ActionBarActivityDelegateICS中的代码如下

@Override
public ActionBar createSupportActionBar() {
return new ActionBarImplICS(mActivity, mActivity);
}
所以ActionBarActivityDelegate中的实现交给了ActionBarImplICS类实现,而ActionBarActivityDelegateBase则给ActionBarImplBase来实现,ActionBarActivityDelegateHC则给ActionBarImplHC实现.所以现在我们看看第三类.

第三类,ActionBar具体实现,这一分类有四个类:ActionBar.java ActionBarImplICS.java ActionBarImplBase.java ActionBarImplHC.java; 而这四个类的关系如下:



所以我们看到了,这九个类的关系,十分简单明了,在ActionBarActivity中ActionBarActivityDelegate mImpl引用了ActionBarActivityDelegate来管理与操作ActionBar,而ActionBarActivityDelegate中引用了ActionBar,具体分配只有它的子类去引用不同的ActionBar,具体实现则到了ActionBar的不同子类.在ActionBarImplICS.java中对应的4.0以上版本,而4.0以上版本已经有完美的ActionBar,所以只是用系统的ActionBar而已.而3.0以下的版本没有ActionBar.所以在ActionBarImplBase.java实现中,作者写了自己的布局文件R.id.action_bar_overlay_layout来代替系统中没有ActionBar.

private void init(ActionBarActivity activity) {
mOverlayLayout = (ActionBarOverlayLayout) activity.findViewById(
R.id.action_bar_overlay_layout);
if (mOverlayLayout != null) {
mOverlayLayout.setActionBar(this);
}
mActionView = (ActionBarView) activity.findViewById(R.id.action_bar);
mContextView = (ActionBarContextView) activity.findViewById(R.id.action_context_bar);
mContainerView = (ActionBarContainer) activity.findViewById(R.id.action_bar_container);
mTopVisibilityView = (ViewGroup) activity.findViewById(R.id.top_action_bar);
if (mTopVisibilityView == null) {
mTopVisibilityView = mContainerView;
}
mSplitView = (ActionBarContainer) activity.findViewById(R.id.split_action_bar);

if (mActionView == null || mContextView == null || mContainerView == null) {
throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
"with a compatible window decor layout");
}

mActionView.setContextView(mContextView);
mContextDisplayMode = mActionView.isSplitActionBar() ?
CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;

// This was initially read from the action bar style
final int current = mActionView.getDisplayOptions();
final boolean homeAsUp = (current & DISPLAY_HOME_AS_UP) != 0;
if (homeAsUp) {
mDisplayHomeAsUpSet = true;
}

ActionBarPolicy abp = ActionBarPolicy.get(mContext);
setHomeButtonEnabled(abp.enableHomeButtonByDefault() || homeAsUp);
setHasEmbeddedTabs(abp.hasEmbeddedTabs());
setTitle(mActivity.getTitle());
}
这样就实现了不管是版本版本,我们只需要继承AtionBarActivity就可以了,如果是4.0以上的版本,会自动去用系统的ActionBar,如果是3.0~4.0的版本会去用ActionBarImplHC中的实现,而3.0以下去调用ActionBarImplBase.java中的Bar.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: