视频连接 : https://www.bilibili.com/video/BV1eD4y1R73Ujava
XPage是一个很是方便的fragment页面框架!天下武功,惟快不破,XPage最大的特色就是快,提升开发的效率!android
XPage设计的初衷是但愿能作一个通用的Activity做为壳,Fragment做为页面填充展现,而且可以像Activity那样自由的切换和数据交互。
当初作Android开发时每当我写一个页面,都须要建立一个Activity,而且还须要在manifest中注册一堆Activity信息,这样既不方便,并且对资源的开销也比较大。所以当时我就设想可否创造出一个通用万能的Activity容器,能够全权负责Fragment的切换展现和数据交互,只须要一行代码便可完成全部的操做,还不须要本身手动去注册,能够一键生成。git
刚开始的时候真的很难,没有什么好的思路,最初只是简单封装了一个Activity,经过传入一些key值从而获取并加载对应的fragment,相似ARouter
中Fragment发现那种。其实这样作并无解决一个容器的问题,并且页面切换也不是很灵活,不够通用,使用起来也不是很方便。github
忽然有一天我发现Github上有个开源项目CorePage写得很是好,完美地解决了我对一个Activity容器的问题,因而我决定仔细研究其代码,并在其基础上设计出了XPage的最第一版本。json
就在XPage正式投入使用的过程当中,我发现仍是存在很多问题的:微信
对于API不够灵活的问题,我在以后的版本中陆续经过构造者模式设计以及Android主题属性等手段解决了。app
而对于手动注册的问题,我正是借鉴了ARouter的思路,经过Android APT技术,从而实现了Fragment信息的自动注册。框架
1.在项目根目录的build.gradle
的 repositories 添加jitpack
仓库dom
allprojects { repositories { ... maven { url "https://jitpack.io" } } }
2.在dependencies添加引用maven
如下是版本说明,选择一个便可。
dependencies { ... // XPage implementation 'com.github.xuexiangjys.XPage:xpage-lib:3.0.0' annotationProcessor 'com.github.xuexiangjys.XPage:xpage-compiler:3.0.0' // ButterKnife的sdk implementation 'com.jakewharton:butterknife:10.1.0' annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0' }
dependencies { ... // XPage implementation 'com.github.xuexiangjys.XPage:xpage-lib:2.3.0' annotationProcessor 'com.github.xuexiangjys.XPage:xpage-compiler:2.3.0' // ButterKnife的sdk implementation 'com.jakewharton:butterknife:8.4.0' annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0' }
【注意】若是你使用的是kotlin,请使用以下配置:
apply plugin: 'kotlin-kapt' dependencies { ... //XPage implementation 'com.github.xuexiangjys.XPage:xpage-lib:3.0.0' kapt 'com.github.xuexiangjys.XPage:xpage-compiler:3.0.0' //ButterKnife的sdk implementation 'com.jakewharton:butterknife:10.1.0' kapt 'com.jakewharton:butterknife-compiler:10.1.0' }
3.进行moduleName注册(非必要)
defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [ moduleName : project.getName() ] } } }
【注意】:若是不注册的话,默认ModuleName为app
。
1.自动进行页面注册【推荐】
使用apt编译时自动生成的页面注册配置类 "moduleName"+PageConfig 的getPages()进行注册。
PageConfig.getInstance() .setPageConfiguration(new PageConfiguration() { //页面注册 @Override public List<PageInfo> registerPages(Context context) { //自动注册页面,是编译时自动生成的,build一下就出来了。若是你还没使用@Page的话,暂时是不会生成的。 return AppPageConfig.getInstance().getPages(); //自动注册页面 } }) .debug("PageLog") //开启调试 .setContainActivityClazz(XPageActivity.class) //设置默认的容器Activity .enableWatcher(false) //设置是否开启内存泄露监测 .init(this); //初始化页面配置
【注意】:若是你的项目中只是增长了依赖,尚未使用@Page注解XPageFragment页面的话,在编译时是不会自动生成注册页面的!!
2.手动动态进行页面注册
PageConfig.getInstance() .setPageConfiguration(new PageConfiguration() { //页面注册 @Override public List<PageInfo> registerPages(Context context) { List<PageInfo> pageInfos = new ArrayList<>(); addPageInfoAndSubPages(pageInfos, MainFragment.class); pageInfos.add(PageConfig.getPageInfo(DateReceiveFragment.class)); return pageInfos; //手动注册页面 } }) .debug("PageLog") //开启调试 .enableWatcher(false) //设置是否开启内存泄露监测 .init(this); //初始化页面配置
在assets文件夹中新建“corepage.json“,而后进行以下配置:
[ { "name": "测试页面1", "classPath": "com.xuexiang.xpagedemo.fragment.TestFragment1", "params": "" }, { "name": "测试页面2", "classPath": "com.xuexiang.xpagedemo.fragment.TestFragment2", "params": { "key1":"这是参数1的值", "key2":"这是参数2的值" } }, ]
# fastjson -dontwarn com.alibaba.fastjson.** -keep class com.alibaba.fastjson.** { *; } -keepattributes Signature # xpage -keep class com.xuexiang.xpage.annotation.** { *; }
使用XPage,Activity必需要继承XPageActivity
,Fragment必需要继承XPageFragment
,不然将没法调用页面跳转的openPage
方法。
openPage
便可打开页面,入参可为跳转类的类名,也能够是类的标识(@Page标注的name字段)// 使用类名打开 openPage(TestFragment.class); // 使用标识打开 openPage("TestFragment");
popToBack
便可关闭页面。// 关闭当前页,返回上一页 popToBack(); // 关闭当前页并跳转至某个页面 popToBack("popBackName", null);
openPageForResult
便可,相似Activity里的startActivityForResult
。openPageForResult(TestFragment.class, null, REQUEST_CODE);
setFragmentResult
来设置页面关闭的返回值,相似Activity里的setResult
方法。// 设置返回的数据,相似Activity里的setResult Intent intent = new Intent(); intent.putExtra(KEY_BACK_DATA, "==【返回的数据】=="); setFragmentResult(500, intent); // 返回操做 popToBack();
onFragmentResult
方法来接收返回的数据,相似Activity里的onActivityResult
方法。@Override public void onFragmentResult(int requestCode, int resultCode, Intent data) { super.onFragmentResult(requestCode, resultCode, data); if (data != null) { Bundle extras = data.getExtras(); XToastUtils.toast("requestCode:" + requestCode + " resultCode:" + resultCode + " data:" + extras.getString(TestFragment.KEY_BACK_DATA)); } }
openPage
打开页面时,可传入Bundle做为参数。// 设置须要传递的参数 Bundle params = new Bundle(); params.putBoolean(DateReceiveFragment.KEY_IS_NEED_BACK, false); int id = (int) (Math.random() * 100); params.putString(DateReceiveFragment.KEY_EVENT_NAME, "事件" + id); params.putString(DateReceiveFragment.KEY_EVENT_DATA, "事件" + id + "携带的数据"); // 把参数传入 openPage(DateReceiveFragment.class, params);
数据接收和普通Fragment接收数据同样,使用getArguments
获取传入的数据。
Bundle arguments = getArguments(); String eventName = arguments.getString(DateReceiveFragment.KEY_EVENT_NAME); String eventData = arguments.getString(DateReceiveFragment.KEY_EVENT_DATA);
页面转场动画能够动态设置,也能够静态设置。
在咱们使用@Page
进行页面注册的时候,咱们能够静态设置转场动画、默认参数、拓展字段等。
Page注解的属性表:
属性名 | 类型 | 默认值 | 备注 |
---|---|---|---|
name | String | 注解类的类名 | 页面的名称、惟一标识符 |
params | String[] | {""} | 静态设置默认参数 |
anim | CoreAnim | CoreAnim.slide | 页面转场动画 |
extra | int | -1 | 拓展字段 |
使用openPage
打开页面时,可传入CoreAnim枚举设置页面转场动画。
switch(position) { case 0: openPage(TestFragment.PAGE_NAME, null, CoreAnim.none);//没有动画 break; case 1: openPage(TestFragment.PAGE_NAME, null, CoreAnim.present);//由下到上动画 break; case 2: openPage(TestFragment.PAGE_NAME, null, CoreAnim.slide);//从左到右动画 break; case 3: openPage(TestFragment.PAGE_NAME, null, CoreAnim.fade);//渐变 break; case 4: openPage(TestFragment.PAGE_NAME, null, CoreAnim.zoom);//放大 break; default: break; }
//自定义动画 openPage(TestFragment.PAGE_NAME, null, new int[]{ // OpenEnterAnimation, 页面打开进场动画 R.anim.custom_open_enter, // OpenExitAnimation, 页面打开退场动画 R.anim.custom_open_exit, // CloseEnterAnimation, 页面关闭进场动画 R.anim.custom_close_enter, // CloseExitAnimation, 页面关闭退场动画 R.anim.custom_close_exit });
使用PageOption.to
进行页面选项构建。
PageOption.to(TestFragment.class) //跳转的fragment .setAnim(CoreAnim.zoom) //页面转场动画 .setRequestCode(100) //请求码,用于返回结果 .setAddToBackStack(true) //是否加入堆栈 .setNewActivity(true, ContainActivity.class) //是否使用新的Activity打开 .putBoolean(DateReceiveFragment.KEY_IS_NEED_BACK, true) //传递的参数 .open(this); //打开页面进行跳转
能够设置XPageTitleBarStyle
主题样式来自定义标题栏的默认样式。
<!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/xpage_default_actionbar_color</item> <item name="colorPrimaryDark">@color/xpage_default_actionbar_color</item> <item name="colorAccent">@color/xpage_default_actionbar_color</item> <!--标题栏的背景图片,优先使用背景图片,没有背景图片才使用背景颜色,可选--> <item name="xpage_actionbar_background">@null</item> <!--标题栏的背景颜色--> <item name="xpage_actionbar_color">@color/xpage_default_actionbar_color</item> <!--是否支持沉浸式标题栏, 默认false--> <item name="xpage_actionbar_immersive">false</item> <!--标题栏返回箭头, 默认R.drawable.xpage_ic_navigation_back_white--> <item name="xpage_actionbar_navigation_back">@drawable/xpage_ic_navigation_back_white</item> <!--标题栏的高度,默认52dp--> <item name="xpage_actionbar_height">60dp</item> <!--标题栏标题文字的大小,默认18sp--> <item name="xpage_actionbar_title_text_size">21sp</item> <!--标题栏副标题文字的大小,默认12sp--> <item name="xpage_actionbar_sub_text_size">14sp</item> <!--标题栏动做文字的大小,默认15sp--> <item name="xpage_actionbar_action_text_size">18sp</item> <!--标题栏动做图片的padding,默认5dp--> <item name="xpage_actionbar_action_padding">6dp</item> <!--标题栏两侧文字的padding,默认14dp--> <item name="xpage_actionbar_side_text_padding">16dp</item> <item name="XPageTitleBarStyle">@style/XPageTitleBar.Custom</item> </style> <style name="XPageTitleBar.Custom"> <item name="tb_immersive">false</item> <item name="tb_centerGravity">center</item> </style>
详细可参见BottomNavigationViewFragment
就像正常使用ViewPager加载Fragment那样。可是这里须要注意的两点是:
@Override protected TitleBar initTitleBar() { //不使用@Page标注的必定要注意覆盖这个方法 return null; }
PageOption.to(TestFragment.class) //新建一个容器,以不影响当前容器 .setNewActivity(true) .open(this);
详细可参见ComplexActivity
1.自定义页面容器的布局,在布局中必定要包含idfragment_container
。
<FrameLayout android:id="@id/fragment_container" android:layout_width="match_parent" android:layout_height="400dp"> </FrameLayout>
2.在XPageActivity中设置页面容器的布局ID
@Override protected int getLayoutId() { return R.layout.activity_complex; }
3.使用changePage
方法切换Fragment。
changePage(TestFragment.PAGE_NAME, null, CoreAnim.none);
【注意】在切换Fragment的时候,fragment并不会走onResume和onPause生命周期,建议使用onHiddenChanged代替。
4.使用getPage
方法获取指定的Fragment,就能够获取该fragment页面中的数据。
TabAFragment tabAFragment = getPage(TabAFragment.class); if (tabAFragment != null) { ToastUtils.toast(tabAFragment.getData()); } else { ToastUtils.toast("页面还未加载!"); }
找不到AppPageConfig
?答:首先须要明确的是,AppPageConfig
是须要编译以后才会出现的,若是你没有编译的话,是确定没有的。若是你编译了仍是找不到,你能够根据以下步骤依次进行排查:
@Page
注解了,若是没有的话,即便编译了也是不会生成AppPageConfig
文件的。"moduleName"+PageConfig
的规则进行自动生成的,若是没有配置moduleName的话,默认才是app,这样自动生成的注册类才是AppPageConfig
。若是你配置了moduleName,并且模块的名称也不是app,那么自动生成的注册类确定不是AppPageConfig
。更多资讯内容,欢迎扫描关注个人我的微信公众号!
![]()