构建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

0 1
原创粉丝点击