【Android】组件化打造第三方知乎日报系列(二)——主界面框架搭建

【Android】组件化打造第三方知乎日报系列(二)——主界面框架搭建

本节完整代码可以前往github查看,项目地址:https://github.com/N0tExpectErr0r/Zhihu-Daily

AppModule

AppModule是我们的壳工程,我们通过这个壳工程来将各个组件层的Module集合到一起。

在AppModule中我们只有一个空的Activity—LauncherActivity,这个Activity用于管理我们启动应用后的跳转。

public class LauncherActivity extends DailyBaseActivity {

    @Override
    protected int getContentViewId() {
        return R.layout.app_activity_launcher;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        // 一些预处理及跳转
    }
}

HomeModule

整体设计

HomeModule中展示了我们的主界面,是我们的第一个组件层的Module,我们的主界面决定采用底部栏TabLayout配合ViewPager的形式来实现。这里TabLayout使用了第三方库FlycoTabLayout

build.gradle

由于这里是第一个组件层的Module,所以先给大家展示一下它的build.gradle,其他组件层的gradle大同小异,以后就不再赘述。

其中我们需要关注的有几点。

注释1处,根据是否是集成编译运用了不同的apply语句,使得该模块在非集成编译的时候以application的形式存在,可以单独编译。而在集成编译时则以library的形式存在,可以被AppModule所引用。

注释2处,如果是单独编译,则使用自己的Manifest。如果是集成编译,则使用App壳工程的Manifest。

注释3处,就像第一篇中说到的,BaseModule被我们的各个组件层的Module所引用。

// 1
if(isSingleBuild.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

android {
    compileSdkVersion COMPILE_SDK_VERSION

    defaultConfig {
        minSdkVersion MIN_SDK_VERSION
        targetSdkVersion TARGET_SDK_VERSION
        versionCode VERSION_CODE
        versionName VERSION_NAME

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }
    }


    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    resourcePrefix "home_"

    sourceSets{
        main{
            // 2
            if(isSingleBuild) {
                manifest.srcFile '../home/src/main/AndroidManifest.xml'
            } else {
                manifest.srcFile '../app/src/main/AndroidManifest.xml'
            }
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation "com.android.support:appcompat-v7:${SUPPORT_LIB_VERSION}"
    implementation "com.android.support:design:${SUPPORT_LIB_VERSION}"
    implementation "com.android.support:cardview-v7:${SUPPORT_LIB_VERSION}"
    implementation "com.alibaba:arouter-api:${AROUTER_VERSION}"
    implementation "com.flyco.tablayout:FlycoTabLayout_Lib:${FLYCO_TAB_VERSION}@aar"
    annotationProcessor "com.alibaba:arouter-compiler:${AROUTER_COMPILER_VERSION}"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    // 3
    implementation project(':base')
}

界面布局

布局如下所示,一个Toolbar,一个ViewPager及一个TabLayout。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical">
    <android.support.v7.widget.Toolbar
        android:id="@+id/home_tb_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:title="@string/app_name" />
    <android.support.v4.view.ViewPager
        android:id="@+id/home_vp_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <com.flyco.tablayout.CommonTabLayout
        android:id="@+id/home_tl_bottom"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:background="@color/tab_background"
        app:tl_iconHeight="18dp"
        app:tl_iconMargin="5dp"
        app:tl_iconWidth="18dp"
        app:tl_indicator_color="@color/colorPrimary"
        app:tl_indicator_gravity="BOTTOM"
        app:tl_indicator_height="0dp"
        app:tl_textSelectColor="@color/tab_select_color"
        app:tl_textUnselectColor="@color/tab_unselect_color"
        app:tl_underline_color="#DDDDDD"
        app:tl_underline_gravity="TOP"
        app:tl_underline_height="1dp"/>
</LinearLayout>

Java实现

下面是具体的Java代码,可以看到这里比较特别的是,我们使用了@Route注解。这就是我们之前用到ARouter的原因了,这样其他Activity就可以通过我们HomeMainActivity的path来跳转到这个Activity。

然后我们看到getFragmentList方法,在我们后面需要Fragment加入主界面时只用改动这里即可。

@Route(path = RouterConstant.ACTIVITY_HOME_MAIN)
public class HomeMainActivity extends DailyBaseActivity {
    private ViewPager mVpContainer;
    private CommonTabLayout mTlTab;
    private Toolbar mTbTitle;
    private FragmentManager mFragmentManager;
    private List<Fragment> mFragmentList;

    @Override
    protected int getContentViewId() {
        return R.layout.home_activity_main;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        mVpContainer = findViewById(R.id.home_vp_container);
        mTlTab = findViewById(R.id.home_tl_bottom);
        mTbTitle = findViewById(R.id.home_tb_toolbar);
        mFragmentManager = getSupportFragmentManager();
        mFragmentList = getFragmentList();
        setSupportActionBar(mTbTitle);
        initViewPager();
        initTabItems();
    }

    private void initViewPager() {
        CommonPagerAdapter adapter = new CommonPagerAdapter(mFragmentManager, mFragmentList);
        mVpContainer.setAdapter(adapter);
        mVpContainer.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                mTlTab.setCurrentTab(position);
                this.onPageSelected(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
        mVpContainer.setCurrentItem(0);
    }

    private List<Fragment> getFragmentList() {
        List<Fragment> fragmentList = new ArrayList<>();
        return fragmentList;
    }

    private List<CommonTabBean> getTabBeanList() {
        List<CommonTabBean> beans = new ArrayList<>();
        beans.add(new CommonTabBean("首页", R.drawable.home_ic_home_select,R.drawable.home_ic_home_unselect));
        beans.add(new CommonTabBean("栏目", R.drawable.home_ic_category_select,R.drawable.home_ic_category_unselect));
        beans.add(new CommonTabBean("收藏", R.drawable.home_ic_star_select,R.drawable.home_ic_star_unselect));
        return beans;
    }

    private void initTabItems() {
        List<CommonTabBean> tabBeans = getTabBeanList();
        ArrayList<CustomTabEntity> tabEntityList = new ArrayList<>(tabBeans);
        mTlTab.setTabData(tabEntityList);
        mTlTab.setOnTabSelectListener(new OnTabSelectListener() {
            @Override
            public void onTabSelect(int position) {
                mVpContainer.setCurrentItem(position);
            }

            @Override
            public void onTabReselect(int position) {

            }
        });
    }
}

然后,我们需要在LauncherActivity中通过ARouter跳转到此Activity。

ARouter.getInstance().build(RouterConstant.ACTIVITY_HOME_MAIN).navigation();

同时,我们还需要在集成编译模式下让AppModule引用此Module

if (!isSingleBuild.toBoolean()) {
    implementation project(":home")
}

效果展示

可以看到,效果如下

发表评论

电子邮件地址不会被公开。 必填项已用*标注

%d 博主赞过: