您的位置:首页 > 移动开发 > Android开发

Android使用Fragment打造万能页面切换框架(三)

2016-04-08 14:25 661 查看
接下来就是处理基类BaseFragment的问题了,这里贴出该类所有代码,具体请参考注释。

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的整个过程。


使用非常简单

来一张样例动图。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: