让android应用实现只有一个activity的fragmentOnlySupportActivity
来源:互联网 发布:4621三星网络打印设置 编辑:程序博客网 时间:2024/06/07 18:19
自从fragment出现以来,很多app都开始使用fragment做界面,由于fragment的生命周期比activity丰富,如果管理不好fragment,就是增加开发难度,如果对fragment的生命周期管理到位就会事半功倍,按我的理解,fragment的生命周期其实就是activity生命周期的加强版,很多生命周期的方法和activity生命周期的方法是一个效果的,如果你的应用design不是android的那种design,很多都是自定义的,那么你可以尝试使用只有一个activity的编码(其实一般来说,在普通的开发中并没有什么卵用,但如果你使用插件技术吧fragment做出插件,界面跳转无需什么,可以增加删除,那意义就重大了)。
如何管理fragment的回退栈
一般的,你会想到使用popbackstack,其实popbackstack只是fragment的事务回退操作,注意了是事务,fragment的事务回退包括了fragment状态的回退,事务处理在处理自定义的复杂fragment跳转就会变得很繁琐,甚至不明白会应为不明白他的原理而研究他的源码!
在这里,我用的方法是hide,show,remove等方法对fragment经常自定义的管理。
假设你要启动一个fragment,那么将它实例化后add进来,add之前要对所有的fragment都做hide处理,不然底部会出现上一个fragment的背景,甚至能够点击。
假如你按了返回键,回到上一个fragment,那么从fragmentManger里面获取fragmentList(请勿对它操作,不然会出问题),注意了,这个fragmentList的顺序不一定跟你add的顺序一致,而且部分fragment销毁掉的,在这个list里面会空,对于没有顺序的fragmentList,我们需要对fragment设置Tag标记fragment是第几个add进去的,按返回键的时候,枚举一次fragmentList,按照tag,取到上一个界面的fragment,然后remove当前fragment,show出上一个fragment。
如何像activity那样finish掉指定界面?
如果你拿到他的实例,直接remove掉,如果你只有fragment的Class,那么枚举fragmentList,判断className相同后删除。
如果给fragment添加载入退出动画
抛开fragment动画,你一定会知道app中不一定全部activity载入动画是相同的,那么这个一个让fragmentOnlySupport一定也要能知道不同fragment对应不同的动画,此时,如何给fragment设置对应的动画?还是给fragment设置Tag,上面讲到fragment设置加载的index,那么index和动画一起加起来,可以用json作为字符串,把index和对应的动画都绑定在一起。
博客出处
创建实体与之对应:
public class FragmentTagVo { public FragmentTagVo(){}; public FragmentTagVo(int index, String animType) { this.index = index; this.animType = animType; } public String animType; public int index; public static FragmentTagVo build(String json) { FragmentTagVo tagVo = new FragmentTagVo(); try { JSONObject jsonObject = new JSONObject(json); tagVo.index = jsonObject.getInt("index"); tagVo.animType = jsonObject.getString("animType"); } catch (Exception e) { e.printStackTrace(); } return tagVo; } @Override public String toString() { JSONObject jsonObject = new JSONObject(); try { jsonObject.put("index",index); jsonObject.put("animType",animType); } catch (Exception e) { e.printStackTrace(); } return jsonObject.toString(); }}
在加载fragment的时候设置tag:
fragmentIndex++; FragmentTagVo tagVo = new FragmentTagVo(fragmentIndex,animType==null?AnimType.NONE.toString():animType.toString()); try { mFragmentTransaction.add(containerId, tagfragment, tagVo.toString()); } catch (Exception e) { e.printStackTrace(); } mFragmentTransaction.show(tagfragment); mFragmentTransaction.commitAllowingStateLoss(); KeyboradUtil.hideSoftKeyboard(this);
返回时找到上一个fragment的方法:
PLog.i("list:" + fragmentlist); for (int i = fragmentlist.size()-1; i >= 0 ; i--) { Fragment fragment = fragmentlist.get(i); if (!(fragment == null || !fragment.isVisible())) {//可视且不是没有设置view的fragment //这里可以写应用自己的返回逻辑 // Fragment backFragment = null; PLog.d("tag:" + fragment.getTag()); FragmentTagVo tagVo = JSONObject.parseObject(fragment.getTag(),FragmentTagVo.class); int fragIndex = tagVo.index-1; Looper: while (fragIndex >= 0) {//从list后面开始找,高效查找方法 FindByTag: for (AnimType animType:AnimType.values()) { tagVo = new FragmentTagVo(fragIndex,animType.toString()); backFragment = fragmentManager.findFragmentByTag(JSONObject.toJSONString(tagVo)); if (backFragment!=null) { break FindByTag; } } PLog.d("backFragment:" + backFragment); if (backFragment != null) { PLog.d("backFragment add?:" + backFragment.isAdded()); PLog.d("backFragment removing?:" + backFragment.isRemoving()); } if (backFragment == null || !backFragment.isAdded() || backFragment.isRemoving()) { --fragIndex; } else { break Looper; } } PLog.d("currFragment:" + fragment.getClass().getSimpleName()); PLog.d("backFragment:" + backFragment); } }
处理完动画绑定在fragment的逻辑,开始往fragment添加动画。
先声明一个动画枚举类,包括以下动画:
public enum AnimType { NONE,//没有动画 LeftInRightOut,//左进右出 BottomInTopOut,//上进,往下出 ZoomShow//fragment默认缩放 ; public static int[] getAnimRes (AnimType animType){ switch (animType) { case LeftInRightOut: return new int[]{R.anim.push_left_in,R.anim.push_left_out,R.anim.back_left_in, R.anim.back_right_out}; case BottomInTopOut: return new int[]{R.anim.push_bottom_in,R.anim.push_top_out,R.anim.push_bottom_in,R.anim.push_top_out}; default: return new int[]{0,0,0,0}; } }}
add之前添加动画:
public void loadFragment(Fragment tagfragment, FragmentTransaction mFragmentTransaction,@NonNull AnimType animType) { if (mFragmentTransaction == null) { mFragmentTransaction = getSupportFragmentManager().beginTransaction(); } //動畫 if (animType==AnimType.ZoomShow) { mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); } else if (animType== AnimType.LeftInRightOut) { mFragmentTransaction.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out,R.anim.back_left_in,R.anim.back_right_out); } else if (animType== AnimType.BottomInTopOut) { mFragmentTransaction.setCustomAnimations(R.anim.push_bottom_in,R.anim.push_top_out,R.anim.push_bottom_in,R.anim.push_top_out); } else { //NONE } }
退出时设置对于退出动画:
public void backPressed () {......code for find back Fragmentif (backFragment != null) { tagVo = JSONObject.parseObject(fragment.getTag(),FragmentTagVo.class); AnimType exitAnim = null; if(tagVo!=null) for (AnimType animType:AnimType.values()) { if (animType.toString().equals(tagVo.animType.toString())) { exitAnim = animType; } } final Fragment animShowFragment = backFragment; final Fragment animHideFragment = fragment; if (exitAnim==null || exitAnim==AnimType.NONE) { FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction(); mFragmentTransaction.show(animShowFragment); mFragmentTransaction.remove(animHideFragment); mFragmentTransaction.commitAllowingStateLoss(); } else if (exitAnim==AnimType.ZoomShow) { FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction(); mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); mFragmentTransaction.show(animShowFragment); mFragmentTransaction.remove(animHideFragment); mFragmentTransaction.commitAllowingStateLoss(); } else { int[] animRes = AnimType.getAnimRes(exitAnim); Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), animRes[3]); animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction(); mFragmentTransaction.show(animShowFragment); mFragmentTransaction.remove(animHideFragment); mFragmentTransaction.commitAllowingStateLoss(); fragmentChangeing = false; } @Override public void onAnimationRepeat(Animation animation) { } }); fragment.getView().startAnimation(animation); backFragment.getView().setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), animRes[2])); } } else { finish(); } }//end if (!(fragment == null || !fragment.isVisible())) {//可视的 .......code for do other}
如果让fragment拦截返回事件,或实现带条件的返回?
重写activity的onBackPressed返回方法,加入以下代码,让fragment调用就Ok了:
public void setCanBackPress(boolean can) { this.mCanBackPress = can; } protected boolean mCanBackPress = true; protected OnBackPressedListener onBackPressedListener; public void setOnBackPressedListener(OnBackPressedListener listener) { this.onBackPressedListener = listener; } @Override public void onBackPressed() { if (onBackPressedListener != null) { onBackPressedListener.OnBackKeyDown(); return; } if (!mCanBackPress) { return; } backPressed();//该方法用于返回上一个fragment,如果没上一个界面了,最终执行finish }
如果打通这些fragments通信通道?实现像activity的onActivityResult方法一样
类似于广播者模式,每个fragment都可以是观察者和被观察者,用onActivityResult充当Observer接口,用枚举fragmentList的Fragment调用onActivityResult方法充当被观察者。有以下代码:
博客出处
public void pushMsgToSubFragments (boolean needShow,int pushCode,Intent pushData) { pushMsgToSubFragments(getSupportFragmentManager(), needShow,pushCode, Activity.RESULT_OK, pushData); } public void pushMsgToSubFragments (@NonNull FragmentManager fragmentManager,boolean needShow,int requestCode,int resultCode, Intent data) { List<Fragment> fragmentlist = fragmentManager.getFragments(); if (fragmentlist!=null) for (Fragment fragment:fragmentlist) { if (fragment==null) { continue; } if (fragment.isAdded()) { if (needShow) { if (!fragment.isHidden()) { PLog.i("send to:" + fragment); fragment.onActivityResult(requestCode, resultCode, data); } } else { PLog.i("send to:" + fragment); fragment.onActivityResult(requestCode, resultCode, data); } //如果fragment里面还嵌套了fragment,继续观察 pushMsgToSubFragments(fragment.getChildFragmentManager(),needShow,requestCode,resultCode,data); } } } //Fragment里面重写onActivityResult接送观察类型和数据
如果activity调用其他activity,返回数据,继续重新onactivityresult方法:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { PLog.i("onActivityResult:" + requestCode); try { super.onActivityResult(requestCode, resultCode, data); } catch (Exception e) { e.printStackTrace(); } pushMsgToSubFragments(getSupportFragmentManager(), false, requestCode, resultCode, data); }
最后献上完整代码:
import android.app.Activity;import android.content.Intent;import android.os.Build;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentTransaction;import android.util.Log;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import java.util.ArrayList;import java.util.List;/** * Created by george.yang on 15/11/18. */public abstract class FragmentOnlySupportActivity extends PlugBaseActivity { public abstract int getContainerId(); private int containerId = getContainerId(); public static boolean fragmentChangeing = false; public <T extends Fragment> T getFragment(@Nullable FragmentManager manager, Class clazz) { return getFragment(manager, false, clazz); } public <T extends Fragment> T getFragment(@Nullable FragmentManager manager, boolean showing, Class clazz) { if (clazz == null) { return null; } if (manager == null) { manager = getSupportFragmentManager(); } List<Fragment> fragmentlist = manager.getFragments(); if (fragmentlist != null) { for (Fragment fragment : fragmentlist) { if (fragment == null || fragment.isRemoving() || !fragment.isAdded() || (showing && fragment.isHidden())) { continue; } if (clazz.getName().equals(fragment.getClass().getName())) { return (T) fragment; } else { Fragment fragmentInner = getFragment(fragment.getChildFragmentManager(), showing, clazz); if (fragmentInner != null) { return (T) fragmentInner; } } } } return null; } public void loadFragment(Fragment tagfragment, FragmentTransaction mFragmentTransaction) { loadFragment(tagfragment,mFragmentTransaction, AnimType.LeftInRightOut); } public void loadFragment(Fragment tagfragment) { loadFragment(tagfragment,AnimType.LeftInRightOut); } public void loadFragment(String fragmenName) { try { loadFragment((Class<? extends Fragment>) Class.forName(fragmenName)); } catch (Exception e) { e.printStackTrace(); } } public void loadFragment(Class<? extends Fragment> fragmentClass) { try { loadFragment((Fragment) fragmentClass.newInstance()); } catch (Exception e) { e.printStackTrace(); } } public void loadFragment(Fragment tagfragment,@NonNull AnimType animType) { loadFragment(tagfragment, null, animType); } private int fragmentIndex; public void loadFragment(Fragment tagfragment, FragmentTransaction mFragmentTransaction,@NonNull AnimType animType) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (isDestroyed()) { return; } } if (isFinishing()) { return; } PLog.i("load:" + tagfragment); if (!fragmentChangeing) { fragmentChangeing = true; if (tagfragment!=null) { if (mFragmentTransaction == null) { mFragmentTransaction = getSupportFragmentManager().beginTransaction(); } //動畫 if (animType==AnimType.ZoomShow) { mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); } else if (animType== AnimType.LeftInRightOut) { mFragmentTransaction.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out,R.anim.back_left_in,R.anim.back_right_out); } else if (animType== AnimType.BottomInTopOut) { mFragmentTransaction.setCustomAnimations(R.anim.push_bottom_in,R.anim.push_top_out,R.anim.push_bottom_in,R.anim.push_top_out); } else { //NONE } List<Fragment> fragmentlist = getSupportFragmentManager().getFragments(); if (fragmentlist != null) for (int i = 0; i < fragmentlist.size(); i++) { Fragment fragment = fragmentlist.get(i); if (fragment != null) { mFragmentTransaction.hide(fragment); } } fragmentIndex++; FragmentTagVo tagVo = new FragmentTagVo(fragmentIndex,animType==null?AnimType.NONE.toString():animType.toString()); try { mFragmentTransaction.add(containerId, tagfragment, JSONObject.toJSONString(tagVo)); } catch (Exception e) { e.printStackTrace(); } mFragmentTransaction.show(tagfragment); mFragmentTransaction.commitAllowingStateLoss(); KeyboradUtil.hideSoftKeyboard(this); } fragmentChangeing = false; } } public void pushMsgToSubFragments (boolean needShow,int pushCode,Intent pushData) { pushMsgToSubFragments(getSupportFragmentManager(), needShow,pushCode, Activity.RESULT_OK, pushData); } public void pushMsgToSubFragments (@NonNull FragmentManager fragmentManager,boolean needShow,int requestCode,int resultCode, Intent data) { List<Fragment> fragmentlist = fragmentManager.getFragments(); if (fragmentlist!=null) for (Fragment fragment:fragmentlist) { if (fragment==null) { continue; } if (fragment.isAdded()) { if (needShow) { if (!fragment.isHidden()) { PLog.i("send to:" + fragment); fragment.onActivityResult(requestCode, resultCode, data); } } else { PLog.i("send to:" + fragment); fragment.onActivityResult(requestCode, resultCode, data); } pushMsgToSubFragments(fragment.getChildFragmentManager(),needShow,requestCode,resultCode,data); } } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { PLog.i("onActivityResult0:" + requestCode); try { super.onActivityResult(requestCode, resultCode, data); } catch (Exception e) { e.printStackTrace(); } pushMsgToSubFragments(getSupportFragmentManager(), false, requestCode, resultCode, data); } final List<Fragment> removeFragment = new ArrayList<>(); public boolean removeFragment(Class clazz) { if (clazz == null) { return false; } synchronized (removeFragment) { List<Fragment> fragmentlist = getSupportFragmentManager().getFragments(); if (fragmentlist != null) { for (Fragment fragment : fragmentlist) { if (fragment == null) { continue; } if (clazz.getName().equals(fragment.getClass().getName())) { PLog.i("remove:" + clazz.getName()); removeFragment.add(fragment); } } FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); for (Fragment fragment : removeFragment) { ft.remove(fragment); } ft.commitAllowingStateLoss(); removeFragment.clear(); } // } } return true; } public void setCanBackPress(boolean can) { this.mCanBackPress = can; } protected boolean mCanBackPress = true; protected OnBackPressedListener onBackPressedListener; public void setOnBackPressedListener(OnBackPressedListener listener) { this.onBackPressedListener = listener; } @Override public void onBackPressed() { if (onBackPressedListener != null) { onBackPressedListener.OnBackKeyDown(); return; } if (!mCanBackPress) { return; } backPressed(); } //[博客出处](http://georgeyang.cn) public void backPressed () { boolean waitAnimEndUnLock = false; if (!fragmentChangeing) { fragmentChangeing = true; try { FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.executePendingTransactions();//同步结束 List<Fragment> fragmentlist = fragmentManager.getFragments(); if (fragmentlist==null) { finish(); } PLog.i("list:" + fragmentlist); for (int i = fragmentlist.size()-1; i >= 0 ; i--) { Fragment fragment = fragmentlist.get(i); if (!(fragment == null || !fragment.isVisible())) {//可视且不是没有设置view的fragment //这里可以写应用自己的返回逻辑 // Fragment backFragment = null; PLog.d("tag:" + fragment.getTag()); FragmentTagVo tagVo = JSONObject.parseObject(fragment.getTag(),FragmentTagVo.class); int fragIndex = tagVo.index-1; Looper: while (fragIndex >= 0) { FindByTag: for (AnimType animType:AnimType.values()) { tagVo = new FragmentTagVo(fragIndex,animType.toString()); backFragment = fragmentManager.findFragmentByTag(JSONObject.toJSONString(tagVo)); if (backFragment!=null) { break FindByTag; } } PLog.d("backFragment:" + backFragment); if (backFragment != null) { PLog.d("backFragment add?:" + backFragment.isAdded()); PLog.d("backFragment removing?:" + backFragment.isRemoving()); } if (backFragment == null || !backFragment.isAdded() || backFragment.isRemoving()) { --fragIndex; } else { break Looper; } } PLog.d("currFragment:" + fragment.getClass().getSimpleName()); PLog.d("backFragment:" + backFragment); if (backFragment != null) { tagVo = JSONObject.parseObject(fragment.getTag(),FragmentTagVo.class); AnimType exitAnim = null; if(tagVo!=null) for (AnimType animType:AnimType.values()) { if (animType.toString().equals(tagVo.animType.toString())) { exitAnim = animType; } } final Fragment animShowFragment = backFragment; final Fragment animHideFragment = fragment; if (exitAnim==null || exitAnim==AnimType.NONE) { FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction(); mFragmentTransaction.show(animShowFragment); mFragmentTransaction.remove(animHideFragment); mFragmentTransaction.commitAllowingStateLoss(); } else if (exitAnim==AnimType.ZoomShow) { FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction(); mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); mFragmentTransaction.show(animShowFragment); mFragmentTransaction.remove(animHideFragment); mFragmentTransaction.commitAllowingStateLoss(); } else { int[] animRes = AnimType.getAnimRes(exitAnim); Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), animRes[3]); animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction(); mFragmentTransaction.show(animShowFragment); mFragmentTransaction.remove(animHideFragment); mFragmentTransaction.commitAllowingStateLoss(); fragmentChangeing = false; } @Override public void onAnimationRepeat(Animation animation) { } }); fragment.getView().startAnimation(animation); backFragment.getView().setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), animRes[2])); } } else { finish(); } }//end if (!(fragment == null || !fragment.isVisible())) {//可视的 } } catch (Exception e) { e.printStackTrace(); } KeyboradUtil.hideSoftKeyboard(this); if (!waitAnimEndUnLock) { PLog.i("unlock:338"); fragmentChangeing = false; } } }}
- 让android应用实现只有一个activity的fragmentOnlySupportActivity
- 如何实现一个只有广播和service的android应用没有activity
- Android应用:使用Activity实现一个对话框
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?【转】
- android一个应用的activity调用另一个应用的activity
- 只有一个Service或Broadcast Reciver的android应用
- android 接收到云推送,跳转到对应的activity,且一直都只有一个activity
- 只有一个EditView的半透明activity
- Android 打开另外一个应用的activity
- 在mybatis的xml文件中,应用更改状态让只有一个值生效
- android 让自己的Activity只创建一个实例
- 如何让一个Web App实现一个全屏的应用
- 接口和抽象类浅析
- 创建单元素tuple
- Android@id和@+id的区别
- Ruby语言基础学习三:Ruby变量、运算
- 【JQuery】使用one()方法绑定元素的一次性事件
- 让android应用实现只有一个activity的fragmentOnlySupportActivity
- 三角形类布尔型
- Android关于定时器Timer的定义及用法
- 搭建nginx+tomcat+Java的负载均衡环境
- Objective-c 对象与类 继承
- 【笔记】 《js权威指南》- 第5章 语句
- Xcode如何使用<>来引用静态库
- 链接数据库验证表单登陆
- STM32 USB 上位机程序实现