Android组件化打造第三方知乎日报系列(二)——主界面框架搭建
本节完整代码可以前往github查看,项目地址:github.com/N0tExpectEr…
Android组件化打造知乎日报系列(一)—— 项目架构搭建
Android组件化打造知乎日报系列(二)—— 主界面框架搭建
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.toBoolean()) {
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 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 getFragmentList() {
List fragmentList = new ArrayList<>();
return fragmentList;
}
private List getTabBeanList() {
List 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 tabBeans = getTabBeanList();
ArrayList 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")
}
复制代码
效果展示
可以看到,效果如下