构建Activity Fragment+设计app页面
来源:互联网 发布:剑三男神捏脸数据下载 编辑:程序博客网 时间:2024/04/28 08:29
Fragment+
通过activity管理fragment,主要解决事件分配,fragment页面的进入进出,fragment传递大数据引起的页面卡顿、空白闪烁(EventBus传递数据,activity暂存数据),fragmentManager队列在内存回收时错乱,fragment中嵌套viewpager+fragment进行数据展示共用同一个数据源,并对其进行CRUD,fragment内存优化,页面展示共用fragment,改变数据源切换数据引起的ui延迟。
事件分配在activity监听触摸操作,在主容器activity中通过对edittext监听view location来实现键盘显示或隐藏,使用回调建立联系,需要注意的是,fragment中内嵌fragment时,需要再做一次嵌套来响应,例如相机拍照图片返回onFragmentResult
fragment页面切换最大的问题就是数据传递,数据过大会引起切换动画不稳定,在这里有一个思路,在new Fragment的时候赋值,或是通过主容器暂存数据,在页面绘制完成后取数据,或是Eventbus传递,如果要使用复杂的切换效果,需等待页面绘制完成,再在主容器中使用fragment中contentview执行animation
fragmentManager队列,内存溢出回收引起app launch,这里可以重写主容器的onRestoreInstanceState/onSaveInstanceState,不保存临时数据,可以避免fragmentManager的arrayList错乱
activity fragment+的设计架构,activity作为主容器的代码实例:
public class MainActivity extends FragmentActivity implements YSOnListListener, EventHandlerContainer { public static final String TAG = MainActivity.class.getName(); /* fragment */ protected FragmentManager mFragmentManager; protected FragmentTransaction mCurTransaction; @Override public void addComponent(EventHandler component) { this.mComponentContainer.addComponent(component); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { //按下的如果是BACK,同时没有重复 if (mContent != null && mContent instanceof YSAbstractMainFragment) { if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { return super.onKeyDown(keyCode, event); } else { ((YSAbstractMainFragment) mContent).onKeyPress(keyCode, event); } } return true; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mFragmentManager = getSupportFragmentManager(); mPromptView = (PromptImageView) findViewById(R.id.iv_prompt_view); initSDKView(); initView(); // 添加Activity到堆栈 AppManager.getAppManager().addActivity(this); } /* 初始化视图 */ protected void initSDKView() {} /* 初始化视图监听 */ protected void initView() {} /* 点击事件传递 */ public void onClick(View v) { if (mContent != null && mContent instanceof YSAbstractMainFragment) { ((YSAbstractMainFragment) mContent).onClick(v); } } /* 切换fragment */ @Override public void switchContent(int id) { if (mContent instanceof MainFragment) { ((MainFragment) mContent).setCurrentFragment(id); } } @Override public void replaceContent(Fragment fragment) { try { if (fragment == null || mContent.getId() == 0 || mContent == fragment) { return; } //替换新页面 if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } mCurTransaction.replace(R.id.content_fragment, fragment, fragment.getClass().getName()); if (fragment != mContent) { ((YSAbstractMainFragment) mContent).setFragmentVisibleHint(false); ((YSAbstractMainFragment) fragment).setFragmentVisibleHint(true); } mCurTransaction.commitAllowingStateLoss(); mCurTransaction = null; mContent = fragment; } catch (Exception e) { e.printStackTrace(); } } @Override public void addContent(Fragment fragment, int animRes) { try { //输入法现实的时候不能跳转 View v = getCurrentFocus(); if (v instanceof EditText && v.isFocused()) { if (v.getWindowToken() != null) { v.clearFocus(); InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); return; } } if (fragment == null || mContent.getId() == 0 || mContent == fragment) { return; } //同一类型的页面中打开相同的页面 if (mContent instanceof YSAbstractMainFragment && fragment instanceof YSAbstractMainFragment) { if (((YSAbstractMainFragment) fragment).getFragmentTag().equals(((YSAbstractMainFragment) mContent).getFragmentTag())) { return; } } //防止页面重复加载 Fragment mFragment = mFragmentManager.findFragmentByTag(fragment.getClass().getName()); if (mFragment != null) { //新曾页面 Bundle bundle = fragment.getArguments(); int entity_id = -100; if (bundle != null) { entity_id = bundle.getInt("entity_id"); } //之前的entity int m_entity_id = ((YSAbstractMainFragment) mFragment).entity_id; if (entity_id > 0 && entity_id - m_entity_id == 0) { onBack(R.anim.next_right_out); return; } } //添加新页面 if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } //是否要添加切换动画 if (animRes != 0) { mCurTransaction.setCustomAnimations(animRes, R.anim.next_null, animRes, R.anim.next_null); } mCurTransaction.add(R.id.content_fragment, fragment, fragment.getClass().getName()); if (fragment != mContent) { ((YSAbstractMainFragment) mContent).setFragmentVisibleHint(false); ((YSAbstractMainFragment) fragment).setFragmentVisibleHint(true); } mCurTransaction.addToBackStack(null); mCurTransaction.commitAllowingStateLoss(); mCurTransaction = null; mFragmentManager.executePendingTransactions(); mContent = fragment; } catch (Exception e) { e.printStackTrace(); } } /** * activity fragment 后退机制 * * @param animRes 返回动画,小于0时,认为是要返回的页面数 */ @Override public void onBack(int animRes) { int count = mFragmentManager.getBackStackEntryCount(); YSLog.i(TAG, TAG + "------------>count=" + count); onBack(count, animRes); } private void onBack(final int count, final int animRes) { if (count > 0) { //显示隐藏的fragment,设置fragment返回参数 ((YSAbstractMainFragment) mFragmentManager.getFragments().get(count - 1)).setFragmentVisibleHint(true); ((YSAbstractMainFragment) mFragmentManager.getFragments().get(count)).setKeyBack(); //弹出fragment if (animRes > 0 && backAnim(animRes)) { handler.postDelayed(new Runnable() { @Override public void run() { //fragment返回 mFragmentManager.popBackStack(); handler.postDelayed(new Runnable() { @Override public void run() { mContent = mFragmentManager.findFragmentById(R.id.content_fragment); ((YSAbstractMainFragment) mContent).setFragmentVisibleHint(true); mContent.onResume(); } }, 250); } }, 200); } else if (animRes < 0) { //弹出animRes个页面 for (int j = 0; j < Math.abs(animRes); j++) { ((YSAbstractMainFragment) mFragmentManager.getFragments().get(count - j - 1)).setFragmentVisibleHint(true); ((YSAbstractMainFragment) mFragmentManager.getFragments().get(count - j - 1)).setKeyBack(); mFragmentManager.popBackStack(); } handler.postDelayed(new Runnable() { @Override public void run() { mContent = mFragmentManager.findFragmentById(R.id.content_fragment); ((YSAbstractMainFragment) mContent).setFragmentVisibleHint(true); mContent.onResume(); } }, 250); } } else if (mContent instanceof MainFragment) { System.exit(0); } } protected boolean backAnim(int animRes) { if (mContent.getView() != null) { if (animRes == R.anim.next_right_out) { ObjectAnimator tranX = ObjectAnimator.ofFloat(mContent.getView(), "x", 0f, CommonConstant.MOBSCREENWIDTH).setDuration(200); tranX.start(); } else if (animRes == R.anim.next_bottom_out) { ObjectAnimator tranY = ObjectAnimator.ofFloat(mContent.getView(), "y", 0f, CommonConstant.MOBSCREENHEIGHT).setDuration(200); tranY.start(); } else if (animRes == R.anim.next_left_out) { ObjectAnimator tranX = ObjectAnimator.ofFloat(mContent.getView(), "x", 0f, -CommonConstant.MOBSCREENWIDTH).setDuration(200); tranX.start(); } return true; } return false; } /** * ************************************************************************************************************************** */ /* 显示引导页面 */ @Override public void showPromptView(String tag) {} /* 回调函数 */ @Override public void onCallBack(int action) {} /* fragment监听 */ @Override public void onFragmentTouchEvent(MotionEvent event) { if (mContent != null && mContent instanceof YSAbstractMainFragment) { ((YSAbstractMainFragment) mContent).onFragmentTouchEvent(event); } } /* 触摸屏幕,输入法键盘隐藏 */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { //监听touch事件 onFragmentTouchEvent(ev); //监听键盘 if (ev.getAction() == MotionEvent.ACTION_DOWN) { View v = getCurrentFocus(); if (isShouldHideInput(v, ev)) { if (v.getWindowToken() != null) { v.clearFocus(); InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); return true; } } return super.dispatchTouchEvent(ev); } // 必不可少,否则所有的组件都不会有TouchEvent了 if (getWindow().superDispatchTouchEvent(ev)) { return true; } return onTouchEvent(ev); } /* 实时判断是否需要重写input隐藏机制 */ @Override public boolean isShouldHideInput(View v, MotionEvent event) { if (mContent != null && mContent instanceof YSAbstractMainFragment) { return ((YSAbstractMainFragment) mContent).isShouldHideInput(v, event); } return false; } /* 获得当前fragment在fragmentManager中的位置在 */ public int getFragmentPosition() { return mFragmentManager.getBackStackEntryCount(); } /* 获取当前的fragment的name */ @Override public String getFragmentTag() { return TAG; } /* onResume onPause */ @Override public void onResume() { super.onResume(); onResetDialog(); } /* 重置dialog,从特定activity返回的时候要重置dialog */ protected void onResetDialog() { } @Override public void onPause() { super.onPause(); } @Override protected void onDestroy() { super.onDestroy(); onActivityDestroy(); } /* 防止app被回收之后,fragment重叠 */ @Override protected void onRestoreInstanceState(Bundle savedInstanceState) {} @Override protected void onSaveInstanceState(Bundle outState) {} /* 结束Activity的动作 */ protected void onActivityDestroy() {}}
fragment+中,fragment的代码实例:
public class YSAbstractMainFragment extends Fragment implements YSOnListListener, View.OnClickListener, Runnable { /* constant */ protected boolean keyBack = false; /* variable */ protected YSOnListListener mCallback; protected FragmentActivity mContext; protected LayoutInflater mInflater; protected EventHandler eventHandler; protected View contentView; @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mCallback = (YSOnListListener) (mContext = (FragmentActivity) activity); } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnHeadlineSelectedListener"); } catch (Exception e) { e.printStackTrace(); } } @Override public void onClick(View v) { } /* 获取当前view */ public View getContentView() { return contentView; } /* 播放app开头动画 */ public void startAppRevealAnimator(} /* 导航栏重设,加上通知栏高度 */ public void resetNavHeight(int res_id) { } /* 按钮按下的事件响应 */ public void onKeyPress(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 && !keyBack) { onBack(R.anim.next_right_out); } } /* fragment切换视图 */ @Override public void switchContent(int id) { if (mCallback != null) { mCallback.switchContent(id); } } /* 替换fragment */ @Override public void replaceContent(Fragment fragment) { if (mCallback != null) { mCallback.replaceContent(fragment); } } /* fragment添加视图(pop push)*/ @Override public void addContent(Fragment fragment, int animRes) { if (mCallback != null) { mCallback.addContent(fragment, animRes); } } @Override public void onBack(int animRes) { if (mCallback != null && !keyBack) { mCallback.onBack(animRes); } } @Override public void showPromptView(String tag) { if (mCallback != null) { mCallback.showPromptView(tag); } } /* 回调函数 */ @Override public void onCallBack(int action) { } /* 获取当前的fragment的name */ @Override public String getFragmentTag() { return "error"; } /* 设置当前fragment已经返回 */ public void setKeyBack() { keyBack = true; } /* 获得当前fragment在fragmentManager中的位置在 */ public int getFragmentPosition() { if (mCallback != null) { return mCallback.getFragmentPosition(); } return -1; } /* 隐藏当前的输入框 */ public void hideKeyInput() { if (mContext != null) { View v = mContext.getCurrentFocus(); if (v != null && (v instanceof EditText)) { if (v.getWindowToken() != null) { v.clearFocus(); InputMethodManager imm = (InputMethodManager) mContext.getSystemService(mContext.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } } } /* 实时判断是否需要重写input隐藏机制 */ @Override public boolean isShouldHideInput(View v, MotionEvent event) { if (v != null && (v instanceof EditText)) { int[] leftTop = {0, 0}; //获取输入框当前的location位置 v.getLocationInWindow(leftTop); int left = leftTop[0]; int top = leftTop[1]; int bottom = top + v.getHeight(); int right = left + v.getWidth(); if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) { // 点击的是输入框区域,保留点击EditText的事件 return false; } else { return true; } } return false; } @Override public void onFragmentTouchEvent(MotionEvent event) { } /* 隐藏未显示的fragment */ public void setFragmentVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (contentView != null) { if (isVisibleToUser) { contentView.removeCallbacks(this); contentView.setVisibility(View.VISIBLE); } else { contentView.postDelayed(this, 700); } } } /* 执行隐藏contentView */ @Override public void run() { contentView.setVisibility(View.GONE); } @Override public void onDestroyView() { super.onDestroyView(); try { if (getFragmentPosition() >= 1) { //unregister eventhandler if (eventHandler != null) { eventHandler.tryToUnregister(); } //close child fragment manger Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager"); childFragmentManager.setAccessible(true); childFragmentManager.set(this, null); } } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } @Override public void onDestroy() { super.onDestroy(); if (eventHandler != null) { eventHandler.tryToUnregister(); } } /* onResume onPause */ @Override public void onResume() { super.onResume(); MobclickAgent.onPageStart(getFragmentTag()); //统计页面 } @Override public void onPause() { super.onPause(); MobclickAgent.onPageEnd(getFragmentTag()); }}
优化点
切换的流畅、自然不如activity
在内存优化这一块还需要改进
app不在窗口时,容易产生一些error
- 构建Activity Fragment+设计app页面
- 单Activity多Fragment模式快速构建一个App
- 单Activity多Fragment模式快速构建一个App
- 单Activity多Fragment模式快速构建一个App
- 单Activity多Fragment模式快速构建一个App
- 实战使用Axure设计App,使用WebStorm开发(2) – 构建页面架构
- 实战使用Axure设计App,使用WebStorm开发(3) – 构建页面架构
- Android中Activity和Fragment页面跳转
- 从activity跳转至fragment页面
- 从fragment跳转到activity , 返回到指定fragment页面
- Android的activity里fragment切换到下一个fragment页面
- Fragment跳转到activity,然后返回到fragment并且刷新该页面(activity跳转Fragment)
- Android activity跳转到另一个activity的指定fragment页面
- Web App 页面构建的一般性规律
- 如何从activity页面跳转到fragment页面?
- 多个Activity,app多个页面
- 如何使用viewpager与fragment写一个app导航activity
- APP开发实战79-Fragment和Activity比较
- 《引爆点》读书心得
- ossim5.0安装
- 299企业帐号 打包上传蒲公英 In House打包流程
- maven pom.xml详解
- CMake 学习笔记整理(1)
- 构建Activity Fragment+设计app页面
- cvte——android面试必懂
- 数据预处理之归一化
- 2014年奇虎360研发类笔试题 乔布简历
- Fiddler抓包
- 关于Fragment的底部被软键盘上移动及软键盘的详解
- S5PV210 sys_clock编程流程 系统时钟功能模块操作
- Install Open MPI in Ubuntu
- linux命令:mv命令