GitHub - neevek/Paginize: Paginize is a light-weight application framework for Android.

Paginize 是一个轻量级的 Android 应用框架,它提供了对项目充分模块化的支持,使得开发者能够最大程度地复用代码。它的设计初衷是想通过更好的组织代码结构,把复杂的问题简单化,提高代码的复用率、可维护性和加快开发周期,同时摆脱一个界面对应一个 Activity 的窘境。

Paginize 把一个屏幕上的内容的管理操作封装成一个 Page, 在某些场景下,一个 Page 的内容可能会比较复杂,可以把屏幕上的部分内容封装成一个 InnerPage,多个 InnerPage 可以被嵌套到一个 ContainerPage(ContainerPage 是 Page 的子类) 中。Paginize 提供了不同 Page 之间切换的 API,提供了『布局继承』等功能。

Paginize 可以被用于现有项目(因为它只需要一个 Activity 作为容器)和全新项目。目前最新版是 0.6.1,可通过 Gradle 引入依赖:

dependencies {
compile net.neevek.android:paginize:0.6.1
}

下面是使用 Paginize 编写的例子,主要演示『布局继承』、界面切换和相关注解(Annotation)的使用。

  • 创建一个 BasePage 使用的布局文件(R.layout.page_base),这个布局使用了 Support Library 的 Toolbar 控制项,用于实现 Material Design 的标题栏。内容区域是一个 FrameLayout,继承 BasePage 的子类可以把内容填充到这个 FrameLayout 中实现不同的界面。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width_="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#fff"
>
<android.support.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width_="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
>
<android.support.v7.widget.Toolbar
android:id="@+id/tb_header_bar"
android:layout_width_="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/>
</android.support.design.widget.AppBarLayout>

<FrameLayout
android:id="@+id/layout_content_container"
android:layout_width_="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>

  • 创建抽象类 BasePage,继承自 Page。这里用抽象类是因为我们不太可能直接使用一个 BasePage,因为它所提供的功能并不完整,它只有一个标题栏和一个内容容器。在这个类里面,使用了 @PageLayout 注解把布局文件和 BasePage 进行了关联,这样在 BasePage 中就可以通过 @InjectView 注解注入 View,也可以直接使用 findViewById 获取这个布局中的 View 了。

// 通过 @PageLayout 注解把布局文件 R.layout.page_base.xml
// 和当前的 BasePage 进行关联,这样在 BasePage
@PageLayout(R.layout.page_base)
public abstract class BasePage extends Page {

@InjectView(R.id.tb_header_bar)
private Toolbar mTbToolbar;

public BasePage(PageActivity pageActivity) {
super(pageActivity);

// Page 栈上的 Page 数量如果大于 1,
// 就启用 Toolbar 左上角的返回按钮
if (getContext().getPageCount() > 1) {
ToolbarHelper.setNavigationIconEnabled(mTbToolbar, true, new View.OnClickListener() {
@Override
public void onClick(View v) {
onNavigationIconClicked(v);
}
});
}
}

// 提供给子类设置当前界面的标题
protected final void setTitle(String title) {
mTbToolbar.setTitle(title);
}

// 提供给子类设置右上角的菜单,菜单是跟 Page 绑定的,
// 而不是跟 Activity 绑定的
protected final void setupMenu(@MenuRes int menuResId) {
ToolbarHelper.setupMenu(mTbToolbar, menuResId, new Toolbar.OnMenuItemClickListener() {
@Override

public boolean onMenuItemClick(MenuItem item) {
return BasePage.this.onMenuItemClick(item);
}
});
}

protected void onNavigationIconClicked(View v) {
// 关闭当前的 Page(从 Page 栈上删除当前 Page)
hide(true);
}

// 子类可以覆盖此方法处理右上角菜单按钮事件
protected boolean onMenuItemClick(MenuItem item) {
return false;
}

// 提供给子类直接操作 Toolbar 的途径
protected final Toolbar getToolbar() {
return mTbToolbar;
}
}

  • 再创建一个用于实现具体功能的 Page 与其对应的布局文件(R.layout.page_hello),这个界面很简单,只有标题栏和中间的一个 TextView 用于显示 『Hello Paginize!』,标题栏是继承自 BasePage 的,所以这个布局文件里面只需要一个 TextView:

<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv_hello"
android:layout_width_="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize=「28sp"
android:padding="10dip"
/>

  • HelloPage 也很简单,继承 BasePage,通过使用 @InsertPageLayout 指定关联的布局文件,再通过指定的 parent 属性,把当前布局插入到 BasePage 的 R.id.layout_content_container 元素中(这里的 parent 属性是可选的,如果不指定,当前布局就会被插到 BasePage 布局最后一个元素的位置)。通过以上的继承,HelloPage 只需要实现其对 TextView 的操作就可以了。

@InsertPageLayout(value = R.layout.page_test, parent = R.id.layout_content_container)
public class HelloPage extends BasePage {
@InjectView(R.id.tv_hello)
private TextView mTvHello;

public TestPage(PageActivity pageActivity) {
super(pageActivity);
setTitle("Hello Paginize!");
mTvHello.setText("Hello Paginize!");
}
}

  • 最后要把这个 HelloPage 显示出来,我们还需要一个 Activity,这个 Activity 需要继承 PageActivity(PageActivity 通过使用 PageManager 对 Page 栈的进行管理)。对于 PageActivity,可以使用 @InjectPageAnimator 注解指定 Page 的过场动画,开发者也可以自定义自己的 PageAnimator 实现不同的过场动画效果。注:目前 Paginize 也提供了类似微信的过场动画效果,但暂时不是通过 @InjectPageAnimator 实现,而是通过调用 PaginizeManager.enableSwipeToHide() PaginizeManager.useSwipePageTransitionEffect() 来实现的。

@InjectPageAnimator(SlidePageAnimator.class)
public class MainActivity extends PageActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 使用类似微信过场动画效果,调用这两个方法之后
// @InjectPageAnimator 设置的 PageAnimator 将被忽略
// getPageManager().enableSwipeToHide();
// getPageManager().useSwipePageTransitionEffect();

// 显示 HelloPage
new HelloPage(this).show(true);
}
}

  • 效果

上面的例子演示了通过『布局继承』,实现一个包含具体业务功能(显示 Hello Paginize!)的 Page,这个 Page 的代码很简单,只包含了对其本身 TextView 的操作,与具体业务无关的功能都在父类中实现,且只需要实现一次。这里的 Page 扮演著 Controller 的角色。

看到这里,你可能会拿它跟 Fragment 做比较,对此我不敢对 Fragment 做过多评价,因为实际上我并没怎么用过 Fragment,Paginize 的雏形早在 2012 年就在公司的项目中用过,当时我还不知道有 Support Library 这个东西(说来真是惭愧)。所以比较就只能让 Fragment 的深度用户去做啦 :-)

想了解 Paginize 更多的功能和更完整的例子,可以直接 clone github 上的 demo,也可以直接下载安装 Demo APK。

推荐阅读:

相关文章