• Android Fragment


    Android Fragment

    01 Fragment 的产生

    我们一般认为 Fragment 是小的 activity

    3.0 产生 Fragment

    手机 底部 Item 点一个 Item 出现一个 Fragment

    什么是 Fragment

    和其他view 不同

    • 具备生命周期
      • 在一个activity中组合使用多个 Fragment ,从而构造多窗格的界面。
      • 在多个activity中重复使用,重复利用
      • 可以自己去接受输入事件,同样可以动态的增加和移除某一些Fragment
    • 必须委托在activity中才能运行 。
      • fragment 生命周期依赖于 activity activity暂停,fragment也暂停
      • activity运行的时候,fragment可以独立的运行和操作

    可以将 Fragment 片段 视为activity 模块化组成部分 ,变成一个部分(子activity)。

    Fragment 使用方法

    • 新建一个Fragment

      • public class BlankFragment1 extends Fragment 
        
    • 定义一个 Fragment xaml

      • <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:text="@string/hello_blank_fragment" />
        
        <Button
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:text="how are you?"
            android:id="@+id/btn"
            />
        
    • fragment 并不和 activity 一样

      • 通过inflater 解析成一个 view

      • activity 通过 setContentView 解析

        • //生命周期函数
          @Override
          public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                   Bundle savedInstanceState) {
              if (root == null) {
                  root = inflater.inflate(R.layout.fragment_blank_fragment1, container, false);
              }
          
      • Fragment 就是小型 activity 可以直接操作组件

        • textView = root.findViewById(R.id.tv);
          button = root.findViewById(R.id.btn);
          
          button.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  textView.setText("good,how u  doing?");
              }
          });
          
      • 把 创建好的 fragment 放进 mainactivity

        • 必须 加 id,

        • <fragment
              android:name="com.example.myapplication.BlankFragment1"
              android:layout_width = "match_parent"
              android:layout_height = "match_parent"
              android:id="@+id/fragment1"/>
          

    在 activity 增加两个 fragment

    <fragment android:name="com.example.myapplication.BlankFragment1"
        android:layout_width = "match_parent"
        android:layout_height = "match_parent"
        android:layout_weight = "1"
        android:id="@+id/fragment1"/>
    
    <fragment android:name="com.example.myapplication.BlankFragment2"
        android:layout_width = "match_parent"
        android:layout_height = "match_parent"
        android:layout_weight = "1"
        android:id="@+id/fragment2"/>
    

    动态添加 Fragment

    1. 创建一个待处理的fragement
    2. 获取FragmentManger,一般都是通过getSupportfragmentManager()
    3. 开启一个事务transaction,一般调用fragmentManger 的 beginTransaction
    4. 使用transaction 进行 fragment 的替换
    5. 提交事务
    • 创建 两个 Button 和 FrameLayout(点击按钮,fragment 替换 Frame Layout)

      • main_activity 布局

        • <Button
                  android:id="@+id/btn1"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="@string/change" />
          
              <Button
                  android:id="@+id/btn2"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="@string/replace"/>
          
              <FrameLayout
                  android:id="@+id/frameLayout"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:background="@color/colorAccent"/>
          
      • 设置按钮点击事件

        • 实现按钮点击事件有两种

          • 匿名内部类(就像前面实现的那样,传输 new View.OnClickListener 对象 )

          • 实现接口

            • public class MainActivity extends AppCompatActivity implements View.OnClickListener
              
        • Button button = findViewById(R.id.btn1);
                  button.setOnClickListener(this);
          
                  Button button2 = findViewById(R.id.btn2);
                  button2.setOnClickListener(this);
          
           @Override
              public void onClick(View view) {
                  switch (view.getId()){
                      case R.id.btn1:
                          replaceFragment(new BlankFragment());
                          break;
                      case R.id.btn2:
                          replaceFragment(new ItemFragment());
                  }
              }
          
      • 实现 动态切换 fragment

        • //获得 fragment 管理类
                  FragmentManager fragmentManager = getSupportFragmentManager();
          // 获得事务
          FragmentTransaction transaction = fragmentManager.beginTransaction();
                 transaction.replace(R.id.frameLayout,fragment);
          // fragment 压入栈,返回的时候,一个一个弹出
          transaction.addToBackStack(null);
          // 提交之后才能运行
          transaction.commit();
          
          • beginTransaction 开始事务

    Activity 与 Fragment 通信

    • 两个相互独立的类

    • 都是用来展示 UI的

    • 独立的类 怎么进行 通信呢?

      • Activity 与 Fragment 通信
      • Activity 与 Activity 通信
      • Fragment 与 Activity 通信
      • Fragment 与 Fragment 通信
    • 先学习 Activity 与 Fragment 通信

      • 原生方案 Bundle n. 束;捆

        • 创建 Bundle 对象

          • Bundle bundle = new Bundle();
                           bundle.putString("message","你好呀Fragment,我是activity,");
            BlankFragment blankFragment = new BlankFragment();
                           blankFragment.setArguments(bundle);
            replaceFragment(blankFragment);
            
        • 你可以在 fragement 任何地方获取 message,以生命周期为例

          • public void onCreate(Bundle savedInstanceState) {
                   super.onCreate(savedInstanceState);
                   // 返回 activity传进去的 bundle
                   Bundle bundle = this.getArguments();
                   String string = bundle.getString("message");
                   Log.e("leo","传进来的string:"+string);
                   if (getArguments() != null) {
                       mParam1 = getArguments().getString(ARG_PARAM1);
                       mParam2 = getArguments().getString(ARG_PARAM2);
                   }
               }
            
    • 另一种通信方案 : 接口(Java 语言中类与类自己通信的方案)

      1. 定义一个接口类(面向对象原则:面向接口编程)

        • public interface IFragmentCallback {
              void sentMsgToActivity(String string);
              String getMsgFromActivity(String msg);
          }
          
        • 通过接口 对象 实现弱关联

    1. 在 Fragment里面定义一个承接 接口类型对象的函数,接口类型对象的值来自 Avtivity,在Activity 里面创建 Fragment对象,调用Fragment 里面的接口方法里 new 接口类型对象(匿名内部类),把值赋值给 Fragment 里面的变量

      • Fragment

        • //定义一个callback函数  activity 给他赋值
              private IFragmentCallback fragmentCallback;
              // activity 调用这个函数赋值
              public void setFragmentCallback(IFragmentCallback callback){
                  fragmentCallback = callback;
              }
          
      • Activity

        • // 通过对象 调用 callback 方法赋值
                          //调用接口对象,new 匿名内部类
                          blankFragment.setFragmentCallback(new IFragmentCallback() {
                              @Override
                              public void sentMsgToActivity(String string) {
          
                              }
          
                              @Override
                              public String getMsgFromActivity(String msg) {
                                  return null;
                              }
                          });
          
        • mainactivity里面

          • // 通过对象 调用 callback 方法赋值
                            //调用接口对象,new 匿名内部类
                            blankFragment.setFragmentCallback(new IFragmentCallback() {
                                @Override
                                public void sentMsgToActivity(String msg) {
                                    Toast.makeText(MainActivity.this,msg,Toast.LENGTH_LONG).show();
            
                                }
            
    2. 实现fragment 发布消息 给 activity

      • fragment 里面

        • @Override
          public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                   Bundle savedInstanceState) {
              if(rootView == null) {
                  rootView = inflater.inflate(R.layout.fragment_blank, container, false);
              }
              Button button = rootView.findViewById(R.id.btn3);
              button.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      fragmentCallback.sentMsgToActivity("hello,I'm from fragment");
                  }
              });
              // Inflate the layout for this fragment
              return rootView;
          }
          

    观察者设计模式,发布订阅

    fragment 可以 观测activity 的变化,activity发布的消息是我感兴趣的消息,我就接受到

    封装好的方案 : eventBus, LiveData

    Fragment 生命周期

    fragment 执行 依托 activity 执行。

    • onAttach() 和 activity 捆绑

    • onCreat() fragment 创建 对 activity 传来的bundle进行解析就要在oncreat里面进行

    • onCreatView 对fragmentUI的设计

    • onActivityCreated() Activity 创建

    • onStart

    • onResume 重新开始,继续;重新回到

    • onPause 暂停;间歇 UI 状态复位

    • onStop

    • onDestoryView

    • onDestory fragment 销毁

    • onDetach() 和 activity 解绑

    难点 每次调用并不严格按照顺序

    1. 打开界面
      • onCreate() -> onCreateView -> onActivityCreated() -> onStart -> onResume
    2. 按下主屏键
      • onPause -> onStop
    3. 重新打开界面
      • onStart -> onResume()
    4. 按下退键
      • onPause() -> onStart -> onDestoryView -> onDestory -> onDetach()

    生命周期总结

    • 将来开发者会围绕fragment生命周期花很多时间来解决问题

    • Fragment 的使用一定需要在生命周期函数onAttach 和 onDetach之间

    • Fragment 的使用一定要遵守生命周期管理的规划,在正确的地方写恰当的代码

    Fragment 与 ViewPager的联合应用

    ViewPager + Fragment 形成翻页效果

    减少用户的操作:点击层面越少越好

    viewPager1 和 viewPager2 的区别

    • viewpager1 是使用完全自定义的 group

    • viewPager2 也是group 对 recycleView 的封装 说白了就是 recyleview 自带 懒加载 功能

    • 设置viewpager 布局

      • <androidx.viewpager.widget.ViewPager
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/viewPager"
                android:background="@color/colorAccent"/>
        
    • viewpager 是一个容器,需要适配很多不同的参数,所以在 activity 创建 viewpager对象还需要setAdapter()

      • ViewPager2 viewPager = findViewById(R.id.viewPager);
        ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter();
        viewPager.setAdapter(viewPagerAdapter);
        
    • 创建Adaptor类

      • class ViewPagerAdapter extends RecyclerView.Adapter {
        
            @NonNull
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                return null;
            }
        
            @Override
            public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        
            }
        
            @Override
            public int getItemCount() {
                return 0;
            }
        }
        
    • 适配的内容是一个单独界面,创建界面

      • <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/action_container">
        
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/tvTitle"
                android:layout_centerInParent="true"
                android:textColor="#ff4532"
                android:textSize="32dp"
                android:text="Hello"/>
        
        </RelativeLayout>
        
    • adapter 解析item_pager 组件

      • // 解析 item_pager
            class ViewPagerViewHolder extends RecyclerView.ViewHolder{
        
                TextView mtv;
                RelativeLayout mContainer;
                public ViewPagerViewHolder(@NonNull View itemView) {
                    super(itemView);
                    mContainer = itemView.findViewById(R.id.container);
                    mtv = itemView.findViewById(R.id.tvTitle);
                }
            }
        
    • 把 组件加到 view上 先解析 Item_pager .xml 成 一个 view

      public ViewPagerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
          //解析 xml 返回 view
          return new ViewPagerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_pager,parent,false));
      }
      
    • 设置文字和颜色

      • public ViewPagerAdapter(){
                titles.add("Hello");
                titles.add("Kity");
                titles.add("A");
                titles.add("B");
                titles.add("C");
                titles.add("D");
                titles.add("E");
                titles.add("F");
                titles.add("G");
                titles.add("H");
            }
        colors.add(R.color.white);
                colors.add(R.color.red);
                colors.add(R.color.colorAccent);
                colors.add(R.color.colorPrimary);
                colors.add(R.color.balck);
                colors.add(R.color.colorPrimary);
                colors.add(R.color.red);
                colors.add(R.color.white);
                colors.add(R.color.balck);
        
    • 设置页数

      • @Override
        public int getItemCount() {
            return 10;
        }
        
    • 传入文字和颜色

      • @Override
        public void onBindViewHolder(@NonNull ViewPagerViewHolder holder, int position) {
        
            holder.mtv.setText(titles.get(position));
        
        }
        holder.mContainer.setBackgroundResource(colors.get(position));
        

    总结

    一般流程:

    • 定义 ViewPager
    • 为Viewpager 构建 Adapter
    • 创建Adapter 并继承RecyclerView.Adapter
    • 构建ViewPager 要展示页面的 ViewHolder
    • 实现必须的方法

    Fragment 与 ViewPager 的联合应用

    ViewPager + Fragment 形成翻页效果‘

    • activity是数组,fragment是数组之上的结构

    MV VM : jetpack 扩展

    模拟微信页面

    方案1 :ButtomNavigationView

  • 相关阅读:
    差分约束系统详解
    AC自动机详解
    KMP算法详解
    ST算法详解
    Trie详解
    欧拉路径详解
    树上差分详解
    LCA详解
    树链剖分详解
    树的直径详解
  • 原文地址:https://www.cnblogs.com/AronJudge/p/14621179.html
Copyright © 2020-2023  润新知