視頻連接 : 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
。更多資訊內容,歡迎掃描關注個人我的微信公衆號!