Android使用Fragment打造万能页面切换框架(三)
2016-04-08 14:25
661 查看
接下来就是处理基类BaseFragment的问题了,这里贴出该类所有代码,具体请参考注释。
其实无论BaseActivity还是BaseFragment的原理都是一样的,都是通过接口中的函数进行切换,最终都是调用了我们前面所说的两个核心函数。所谓的难点,其实就是openPageForResult的函数。如果调整函数中指定了新开activity,则直接调用startActivityForResult函数进行跳转,目标Activity中为BaseActivity,传递一些参数用于识别。
最后的最后,也就是整个Fragment跳转框架的初始化了,继承Application编写一个应用程序类完成初始化。
之后的一切就会变得特别简单,调用即可。由于我是用android studio建的module,因此直接引用该module即可,然后提供一个程序入口Activity,该类继承BaseActivity,将该Activity声明在manifest文件中,然后我们再也不用新建Activity了,后续的页面跳转全都使用Fragment来完成。并且可以设置动画类型等一系列的参数。
使用非常简单
来一张样例动图。
public class BaseFragment extends Fragment { private static final String TAG = BaseFragment.class.getSimpleName(); protected Activity mActivity; //所在activity private String mPageName; //页面名 private int mRequestCode; //用于startForResult的requestCode private CoreSwitcher mPageCoreSwitcher; //openPageForResult接口,用于传递返回结果 private OnFragmentFinishListener mFragmentFinishListener; /** * 设置该接口用于返回结果 * @param listener OnFragmentFinishListener对象 */ public void setFragmentFinishListener(OnFragmentFinishListener listener) { this.mFragmentFinishListener = listener; } /** * 设置openPageForResult打开的页面的返回结果 * @param resultCode 返回结果码 * @param intent 返回的intent对象 */ public void setFragmentResult(int resultCode, Intent intent) { if(mFragmentFinishListener != null) { mFragmentFinishListener.onFragmentResult(mRequestCode, resultCode, intent); } } /** * 得到requestCode * @return 请求码 */ public int getRequestCode() { return this.mRequestCode; } /** * 设置requestCode * @param code 请求码 */ public void setRequestCode(int code) { this.mRequestCode = code; } /** * 将Activity中onKeyDown在Fragment中实现, * @param keyCode * @param event * @return */ public boolean onKeyDown(int keyCode, KeyEvent event) { return false; } /** * 数据设置,回调 * @param bundle */ public void onFragmentDataReset(Bundle bundle) { } /** * 弹出栈顶的Fragment。如果Activity中只有一个Fragemnt时,Acitivity也退出。 */ public void popToBack() { this.popToBack(null, null); } /** * 如果在fragment栈中找到,则跳转到该fragment中去,否则弹出栈顶 * @param pageName 页面名 * @param bundle 参数 */ public final void popToBack(String pageName, Bundle bundle) { CoreSwitcher coreSwitcher = getSwitcher(); if(coreSwitcher != null) { if(pageName == null) { coreSwitcher.popPage(); } else{ if(this.findPage(pageName)) { CoreSwitchBean page = newCoreSwitchBean(pageName, bundle); coreSwitcher.gotoPage(page); } else{ coreSwitcher.popPage(); } } } else{ Log.d(TAG, "pageSwitcher null"); } } /** * 得到页面切换Switcher,即BaseActivity * @return Switcher */ public CoreSwitcher getSwitcher() { synchronized(BaseFragment.this) {// 加强保护,保证pageSwitcher 不为null if(mPageCoreSwitcher == null) { if(this.mActivity != null&& this.mActivity instanceof CoreSwitcher) { mPageCoreSwitcher = (CoreSwitcher) this.mActivity; } if(mPageCoreSwitcher == null) { BaseActivity topActivity = BaseActivity.getTopActivity(); if(topActivity != null&& topActivity instanceof CoreSwitcher) { mPageCoreSwitcher = (CoreSwitcher) topActivity; } } } } return mPageCoreSwitcher; } public void setSwitcher(CoreSwitcher pageCoreSwitcher) { this.mPageCoreSwitcher = pageCoreSwitcher; } /** * 查找fragment是否存在,通过Switcher查找 * @param pageName 页面名 * @return 是否找到 */ public boolean findPage(String pageName) { if(pageName == null) { Log.d(TAG, "pageName is null"); return false; } CoreSwitcher coreSwitcher = getSwitcher(); if(coreSwitcher != null) { return coreSwitcher.findPage(pageName); } else{ Log.d(TAG, "pageSwitch is null"); return false; } } /** * 对应fragment是否位于栈顶,通过Switcher查找 * @param fragmentTag fragment的tag * @return 是否位于栈顶 */ public boolean isFragmentTop(String fragmentTag) { CoreSwitcher pageCoreSwitcher = this.getSwitcher(); if(pageCoreSwitcher != null) { return pageCoreSwitcher.isFragmentTop(fragmentTag); } else{ Log.d(TAG, "pageSwitcher is null"); return false; } } /** * 重新该方法用于获得返回的数据 * @param requestCode 请求码 * @param resultCode 返回结果码 * @param data 返回数据 */ public void onFragmentResult(int requestCode, int resultCode, Intent data) { Log.d(TAG, "onFragmentResult from baseFragment:requestCode-" + requestCode + " resultCode-" + resultCode); } /** * 在当前activity中打开一个fragment,并添加到返回栈中 * @param pageName Fragemnt 名,在page.json中配置。 * @param bundle 页面跳转时传递的参数 * @param coreAnim 指定的动画理性 none/slide(左右平移)/present(由下向上)/fade(fade 动画) * @return */ public final Fragment openPage(String pageName, Bundle bundle, CoreAnim coreAnim) { return this.openPage(pageName, bundle, CoreSwitchBean.convertAnimations(coreAnim), true); } /** * 在当前activity中打开一个fragment,并设置是否添加到返回栈 * @param pageName Fragemnt 名,在page.json中配置。 * @param bundle 页面跳转时传递的参数 * @param anim 指定的动画农林 none/slide(左右平移)/present(由下向上)/fade(fade 动画) * @param addToBackStack 是否添加到用户操作栈中 * @return */ public final Fragment openPage(String pageName, Bundle bundle, int[] anim, boolean addToBackStack) { return this.openPage(pageName, bundle, anim, addToBackStack, false); } /** * 打开一个fragment并设置是否新开activity,设置是否添加返回栈 * @param pageName Fragemnt 名,在page.json中配置。 * @param bundle 页面跳转时传递的参数 * @param anim 指定的动画理性 none/slide(左右平移)/present(由下向上)/fade(fade 动画) * @param addToBackStack 是否添加到用户操作栈中 * @param newActivity 该页面是否新建一个Activity * @return */ public finalFragment openPage(String pageName, Bundle bundle, int[] anim, boolean addToBackStack, boolean newActivity) { if(pageName == null) { Log.d(TAG, "pageName is null"); returnnull; } CoreSwitcher coreSwitcher = this.getSwitcher(); if(coreSwitcher != null) { CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, anim, addToBackStack, newActivity); return coreSwitcher.openPage(page); } else{ Log.d(TAG, "pageSwitcher is null"); return null; } } /** * 在当前activity中打开一个fragment,并添加到返回栈中 * * @param pageName Fragemnt 名,在page.json中配置。 * @param bundle 页面跳转时传递的参数 * @param anim 指定的动画理性 none/slide(左右平移)/present(由下向上)/fade(fade 动画) * @return */ public final Fragment openPage(String pageName, Bundle bundle, int[] anim) { return this.openPage(pageName, bundle, anim, true); } /** * 在当前activity中打开一个fragment,并设置是否添加到返回栈 * * @param pageName Fragemnt 名,在page.json中配置。 * @param bundle 页面跳转时传递的参数 * @param coreAnim 指定的动画理性 none/slide(左右平移)/present(由下向上)/fade(fade 动画) * @param addToBackStack 是否添加到用户操作栈中 * @return */ public final Fragment openPage(String pageName, Bundle bundle, CoreAnim coreAnim, boolean addToBackStack) { return this.openPage(pageName, bundle, CoreSwitchBean.convertAnimations(coreAnim), addToBackStack, false); } /** * 打开一个fragment并设置是否新开activity,设置是否添加返回栈 * @param pageName Fragemnt 名,在page.json中配置。 * @param bundle 页面跳转时传递的参数 * @param coreAnim 指定的动画理性 none/slide(左右平移)/present(由下向上)/fade(fade 动画) * @param addToBackStack 是否添加到用户操作栈中 * @param newActivity 该页面是否新建一个Activity * @return */ public final Fragment openPage(String pageName, Bundle bundle, CoreAnim coreAnim, boolean addToBackStack, boolean newActivity) { return this.openPage(pageName, bundle, CoreSwitchBean.convertAnimations(coreAnim), addToBackStack, newActivity); } /** * @param pageName * @param bundle * @param coreAnim * @return */ public Fragment gotoPage(String pageName, Bundle bundle, CoreAnim coreAnim) { return this.gotoPage(pageName, bundle, coreAnim,false); } /** * 新建或跳转到一个页面(Fragment)。找不到pageName Fragment时,就新建Fragment。找到pageName * Fragment时,则弹出该Fragement到栈顶上的所有actvity和fragment * * @param pageName Fragemnt 名,在在configure.zip 的pageContext.txt中配置。 * @param bundle 页面跳转时传递的参数 * @param coreAnim 指定的动画理性 none/slide(左右平移)/present(由下向上)/fade(fade 动画) * @param newActivity 该页面是否新建一个Activity * @return */ public Fragment gotoPage(String pageName, Bundle bundle, CoreAnim coreAnim, boolean newActivity) { CoreSwitcher pageCoreSwitcher = this.getSwitcher(); if(pageCoreSwitcher != null) { CoreSwitchBean page = newCoreSwitchBean(pageName, bundle, coreAnim, true, newActivity); return pageCoreSwitcher.gotoPage(page); } else{ Log.d(TAG, "pageSwitcher is null"); return null; } } /** * 打开fragment并请求获得返回值 * @param pageName * @param bundle * @param coreAnim * @param requestCode 请求码 * @return */ public final Fragment openPageForResult(String pageName, Bundle bundle, CoreAnim coreAnim, int requestCode) { return this.openPageForResult(false, pageName, bundle, coreAnim, requestCode); } /** * 打开fragment并请求获得返回值,并设置是否在新activity中打开 * @param newActivity * @param pageName * @param bundle * @param coreAnim * @param requestCode * @return */ public final Fragment openPageForResult(boolean newActivity, String pageName, Bundle bundle, CoreAnim coreAnim, int requestCode) { CoreSwitcher pageCoreSwitcher = this.getSwitcher(); if(pageCoreSwitcher != null) { CoreSwitchBean page = newCoreSwitchBean(pageName, bundle, coreAnim, true, newActivity); page.setRequestCode(requestCode); return pageCoreSwitcher.openPageForResult(page, this); } else{ Log.d(TAG, "pageSwitcher is null"); return null; } } @Override public void onAttach(Activity activity) { super.onAttach(activity); mActivity = activity; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(getPageName() != null) { Log.d(TAG, "====Fragment.onCreate===="+ getPageName()); } } public String getPageName() { return mPageName; } public void setPageName(String pageName) { mPageName = pageName; } @Override public void onDetach() { super.onDetach(); mActivity = null; } //页面跳转接口 public interface OnFragmentFinishListener { void onFragmentResult(int requestCode, int resultCode, Intent intent); } }
其实无论BaseActivity还是BaseFragment的原理都是一样的,都是通过接口中的函数进行切换,最终都是调用了我们前面所说的两个核心函数。所谓的难点,其实就是openPageForResult的函数。如果调整函数中指定了新开activity,则直接调用startActivityForResult函数进行跳转,目标Activity中为BaseActivity,传递一些参数用于识别。
Intent intent = new Intent(this, BaseActivity.class); intent.putExtra("SwitchBean", page); intent.putExtra("startActivityForResult", "true");然后再onCreate中获得intent
Intent mNewIntent = getIntent(); init(mNewIntent);调用了init函数,在里面获得传递的两个参数,如果是startActivityForResult,则对fragment设置回调函数,当我们手动设置了setFragmentResult函数后回调就会被调用,即onFragmentResult函数回调
private void init(Intent mNewIntent) { try{ CoreSwitchBean page = mNewIntent.getParcelableExtra("SwitchBean"); String startActivityForResult = mNewIntent.getStringExtra("startActivityForResult"); this.mFirstCoreSwitchBean = page; if(page != null) { BaseFragment fragment = null; boolean addToBackStack = page.isAddToBackStack(); String pageName = page.getPageName(); Bundle bundle = page.getBundle(); fragment = (BaseFragment) CorePageManager.getInstance().openPageWithNewFragmentManager(getSupportFragmentManager(), pageName, bundle, null, addToBackStack); if(fragment != null) { if("true".equalsIgnoreCase(startActivityForResult)) { fragment.setRequestCode(page.getRequestCode()); fragment.setFragmentFinishListener(new BaseFragment.OnFragmentFinishListener() { @Override public voidonFragmentResult(int requestCode, int resultCode, Intent intent) { BaseActivity.this.setResult(resultCode, intent); } }); } } else{ this.finish(); } } } catch(Exception e) { e.printStackTrace(); Log.d(TAG, e.getMessage()); this.finish(); } }
最后的最后,也就是整个Fragment跳转框架的初始化了,继承Application编写一个应用程序类完成初始化。
/** * * User:Hank(1466181491@qq.com) */ public class BaseApplication extends Application { private static LocalBroadcastManager mLocalBroadcatManager; private static Context mContext; private static BaseApplication instance; public static Context getContext() { return mContext; } @Override public void onCreate() { super.onCreate(); instance = this; mContext = this.getApplicationContext(); CorePageManager.getInstance().init(this); } /** * 发送本地广播退出程序 */ public void exitApp() { Intent intent = new Intent(); intent.setAction(Config.ACTION_EXIT_APP); intent.addCategory(Intent.CATEGORY_DEFAULT); BaseApplication.getLocalBroadcastManager().sendBroadcast(intent); BaseActivity.unInit(); } public static LocalBroadcastManager getLocalBroadcastManager() { if(mLocalBroadcatManager == null) { mLocalBroadcatManager = LocalBroadcastManager.getInstance(mContext); } return mLocalBroadcatManager; } }完成声明
<manifest package="cn.edu.zafu.corepage" xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowBackup="true" android:label="@string/app_name" > <activity android:name="cn.edu.zafu.corepage.base.BaseActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:exported="false" android:launchMode="standard" android:screenOrientation="portrait" android:theme="@style/BaseActivityTheme" android:windowSoftInputMode="adjustUnspecified|stateHidden"> </activity> </application> </manifest>
之后的一切就会变得特别简单,调用即可。由于我是用android studio建的module,因此直接引用该module即可,然后提供一个程序入口Activity,该类继承BaseActivity,将该Activity声明在manifest文件中,然后我们再也不用新建Activity了,后续的页面跳转全都使用Fragment来完成。并且可以设置动画类型等一系列的参数。
openPage("test1",null, CoreAnim.slide); //打开一个页面,不传递参数第二个传null,第三个参数为动画类型,此方法有重载方法,第四个参数表示是否添加到返回栈,第五个参数表示是否新开activity,一般情况下,只需传递前三个参数即可,而动画类型,处理传递枚举类,还支持自定义的动画,对应的文件参考res/anim目录下的相应文件 </code> <code>openPageForResult("test2",bundle,CoreAnim.fade,requestCode);
//打开一个页面并获得返回结果,之后调用setFragmentResult和popToBack设置结果 setFragmentResult(500, intent); popToBack(); 重写onFragmentResult函数获取返回结果 @Override public voidonFragmentResult(int requestCode, int resultCode, Intent data) { } //这个使用过程同startActivityFor的整个过程。
使用非常简单
来一张样例动图。
相关文章推荐
- Android学习笔记:简易五子棋(上)
- Android使用Fragment打造万能页面切换框架(二)
- ArcGIS for Android地图控件的5大常见操作
- MTK6577+Android之按键(key)修改
- Android压缩图片到100K以下同时保持不失真
- Android使用Fragment打造万能页面切换框架(一)
- android快速实现毛玻璃效果
- Android 打开本地的手机软件市场评分
- Android 的线程跟线程池
- android drawable importer的使用
- Android Studio2.0以上反射$change属性问题
- Android 实现4MB以上大图片压缩不失真方法
- Android之Fragment(一)
- 关于android 图片加载优化
- Android 屏幕适配-图片
- 开发Android,记录一些琐碎的知识
- Android EditText的设置
- Android Studio 2.0 正式版发布啦 (首次中文翻译)
- Android的EditText中添加ImageButton
- ListView缓存优化