Android-Fragment详解

1 Fragment简介
现在手机、平板有各种尺寸,特别是平板尺寸比较大,因此在呈现界面时可以呈现更多的内容。因此,我们可以将界面呈现动态地改变内容。
Fragment可以很好的实现这一点
Fragment又称为碎片,可以嵌套在Activity中使用,也有自己的生命周期(当然也与Activity的生命周期有关) 他可以很好的解决大屏幕的适配问题

2 Fragment生命周期

与Activity生命周期对照:
Android-Fragment详解_第1张图片

过程:
先与Activity 连接 (OnAttach()),再创建Fragment(OnCreate()),再创建Fragment的视图(OnCreateView()) 当Activity的Oncreate返回时调用(OnActivityCreate())

onStart()
onResume()
onPause()
onPause()
onDestroy()
和Activity原理类似 只是换成了Fragment

destroy时,先 销毁视图(onDestroyView()) 再销毁Fragment (onDestroy()) 最后解除与Activity的连接(onDetach())

所有Fragment和Activity生命周期绑定,ACtivity回调啥所有Fragment就会回调啥


从该Fragment切换到其他Fragment:
onPause()
onStop()
onDestroyView()


切换回本身的Fragment:

onCreateView()
onActivityCreated()
onStart()
onResume()


Fragment不可见(屏幕熄灭或回到桌面,或者跳转其他界面)
回调Activity的onPause() onStop()
回调所有Fragment的onPause() onStop()

Fragment所在的Activity从不可见到可见
回调Activity的onStart()和onResume()
回调所有Fragment的onStart() 和 onResume()


3 常见使用
1 如首次开启软件的动画,左右滑动看软件相关内容
2 广告 切换不同的广告内容
3 滑动切换界面


Fragment管理

fragmentManager 管理fragment栈

// 加入栈顶 tag可为空   调用commit()可以返回id
addToBackStack(tag)
// 出栈顶 
popBackStack()
// 出某个tag/id的栈
// 其中id表示提交变更时commit()的返回值。
popBackStack(int id, int flags)
// 其中name是addToBackStack(String tag)中的tag值。
// flag: 0不包括该栈 POP_BACK_STACK_INCLUSIVE包括该栈
popBackStack(String name, int flags)

4 Fragment创建

1 直接去右键 new 一个 Fragment的布局
这里有3个可勾选项:
① create layout xml? 是否创建XML文件 一般为勾选
② include fragment factory methods? 是否创建工厂方法 (用于fragment方法的调用) 根据情况勾选
③ include interface callbacks? 是否为Fragment创建回调接口 根据情况勾选

2 这时会生成一个继承Fragment的类
并且重写了 onCreateView()方法


5 Fragment使用
Fragment可以加入到Activity中使用,并且对Fragment内容的操作在Fragment.java文件中,这样可以减少Activity的复杂度,并且可以更好的重用Fragment
1 静态方式
直接在想加入fragment的Activity的布局的XML文件中加入< fragment>标签即可
记得加name属性

android:name=fragment的完整包路径

2 动态方式
在Activity的java代码中

// 1 创建 你创建的Fragment对象
MyFragment myFragment = new MyFragment();
// 2 创建 FragmentManager对象
FragmentManager fm = getFragmentManager();
// 3 创建 FragmentTransaction对象
FragmentTransaction ft= fm.FragmentTransaction();
// 4 建立连接
ft.add(要加入的资源id名, myFragment );
ft.commit();

结束当前fragment所在Activity

getActivity().finish();

要建立与XML的连接(findViewById)

//在自动生成的 onViewCreate()中:
 return inflater.inflate(R.layout.fragment_fragment4, container, false);
//改成:
   View view = inflater.inflate(R.layout.fragment_fragment4, null, false);
 TextView fragment4textView0 = view.findViewById(R.id.fragment4textView0);
//后面就可以写 findViewById了 (要加view.)
//最后再 
return view;

Fragment-> Activity

  Intent intent_1 = new Intent(getActivity(),LoginActivity.class);
                        startActivity(intent_1);

Activity->Fragment

1 到指定的Fragment

Intent intent = new Intent(UserLoginActivity.this,MainActivity.class);
intent.putExtra("userloginflag", 1);
startActivity(intent);
先跳到 装载FragmentActivity上
再在Activity的onResume中
根据传过来的 值去跳转不同Fragment
protected void onResume() {
        int id = getIntent().getIntExtra("userloginflag", 0);

        if (id == 1 ) {
            mTabHost.setCurrentTab(3);
        
        }
        super.onResume();
    }

2 想从这个activity中再跳转回fragment
直接finish这个activity即可


获取别的界面的回传跳转到不同的Fragment(结合BottomNavigationBar使用)
BottomNavigationBar使用地址:http://blog.csdn.net/weixin_37577039/article/details/79058838

// 设置一个默认的 选择值 
private int FIRSTSELECTEDPOSITION=2;
// 获取回传值
Intent intent =getIntent();
FIRSTSELECTEDPOSITION=intent.getIntExtra("flag",2);//后一个数值为 前一个不存在时 指定的一个默认值

// 在bottomNavigationBar中设置
.setFirstSelectedPosition(FIRSTSELECTEDPOSITION)// 设置底部点击的初始位置


6 实际使用 —— 根据点击不同导航栏显示不同主体内容
参考博客:使用materia-design设计的底部导航栏BottomNavigationBar


Fragment实现触摸监听

public interface MyTouchListener {
        public void onTouchEvent(MotionEvent event);
    }

    // 保存MyTouchListener接口的列表
    private ArrayList<MyTouchListener> myTouchListeners = new ArrayList<MainActivity.MyTouchListener>();

    /**
     * 提供给Fragment通过getActivity()方法来注册自己的触摸事件的方法
     * @param listener
     */
    public void registerMyTouchListener(MyTouchListener listener) {
        myTouchListeners.add(listener);
    }

    /**
     * 提供给Fragment通过getActivity()方法来取消注册自己的触摸事件的方法
     * @param listener
     */
    public void unRegisterMyTouchListener(MyTouchListener listener) {
        myTouchListeners.remove( listener );
    }

    /**
     * 分发触摸事件给所有注册了MyTouchListener的接口
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        for (MyTouchListener listener : myTouchListeners) {
            listener.onTouchEvent(ev);
        }
        return super.dispatchTouchEvent(ev);
    }


Fragment中,implements MainActivity.MyTouchListener

@Override
Public  boolean  onTouch(MotionEvent event){
Log.d("test","ontouchevent!");
Return  detector.onTouchEvent(event);
}


onCreateView中:

 MainActivity.MyTouchListener myTouchListener = new MainActivity.MyTouchListener() {
            @Override
            public boolean onTouch(MotionEvent event) {
                // 处理手势事件
                return true;
            }
        };
        // 将myTouchListener注册到分发列表
        ((MainActivity)this.getActivity()).registerMyTouchListener(myTouchListener);
        return view;  

参考:
http://blog.csdn.net/seeytom/article/details/39294657


问题一、transaction.replace时 报错

'replace(int, android.app.Fragment)' in 'android.app.FragmentTransaction' cannot be applied 
to '(int, com.biniu.bottomnavigationbardemo.CRM.customerDetails.CustomerDetailsFragment1)'

因为fragment有两种 :

import android.support.v4.app.Fragment;
//或者
import android.app.Fragment;

这里的replace的第二个参数的fragment要为第二种 :app.Fragment形式的

问题二、
java.lang.RuntimeException: Unable to start activity ComponentInfo XXXXXX must implement OnFragmentInteractionListener

解决 加上接口

implements YourFragment.OnFragmentInteractionListener

问题三、IllegalStateException: Can not perform this action after onSaveInstanceState

原因:在这个onSaveInstance之后 执行fragment的commit方法 会导致Activity没有保存到fragment的状态而导致fragment状态丢失

解决:1 可以使用commitAllowingStateLoss //不管丢失还是执行commit操作
2 Activity显示情况下才进行fragment的修改

你可能感兴趣的:(android,Fragment,滑动切换界面)