Android Fragment 完全解析(上)

【k8s面试】超详细kubernetes面试题总结,面试必问!(附200道K8s Docker面试真题+答案详解 最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家! 阅读详情

       Fragment(碎片),被称为 Andorid 第五大组件,也是继 Activity、Service、BroadcastReceiver、ContentProvider 四大组件之后有一个非常重要的组件,今天我们就来学习一下碎片 Fragment





一、概述


       Fragment 表示 Activity 中的行为或用户界面部分,你可以将多个碎片组合在一个 Activity 中来构建多窗格 UI,以及在多个 Activity 中重复使用某个碎片,你也可以将碎片视为 Activity 的模块化组成部分,它具有自己的生命周期,能够接受自己的输入事件,并且可以在 Activity 运行时添加或移除碎片,

       碎片必须始终嵌入在 Activity 中,其生命周期直接受到宿主 Activity 生命周期的影响,例如,当 Activity 暂停时,其中所有的片段也会暂停,当 Activity 被销毁时,所有片段也会被销毁,不过,当 Activity 正在运行(处于已恢复生命周期状态)时,你可以独立操纵每个碎片,如添加或删除它们,当你执行此类碎片事务时,你也可以将其添加到由 Activity 管理的返回栈(Activity 中的每个返回栈条目都是一条已发生碎片事务的记录),返回栈让用户可以通过按返回按钮撤销碎片事务


二、设计原理


       Android 在 Android 3.0 (API 级别 11)中引入了碎片,主要是为了给大屏幕(如平板电脑)上更加动态的和灵活的 UI 设计提供支持,由于平板电脑的屏幕比手机屏幕大太多,因此可用于组合和交换 UI 组件的空间更大,利用碎片实现此类设计时,你无需管理对视图层次结构的复杂更改,通过将 Activity 布局分成碎片,你可以在运行时修改 Activity 的外观,并在由 Activity 管理的返回栈中保留这些更改


       例如,新闻应用可以使用一个碎片在左侧显示文章列表,使用另一个碎片在右侧显示文章(这样两个碎片并排显示在一个 Activity 中)每个碎片都具有自己的一套生命周期回调方法,并且各自处理自己的用户输入事件,因此用户不需要使用一个 Activity 来选择文章,然后使用另一个 Activity 来阅读文章,而是可以在同一个 Activity 内选择文章进行阅读,如下图所示: 




       你应该将每个碎片都设计为可重复使用的模块化 Activity 组件,也就是所,由于每个碎片都会通过各自的生命周期方法回调来定义其自己的布局和行为,你可以将一个碎片加入多个 Activity,因此我们的应用应该采用可复用式设计,避免从某个碎片直接操纵另一个碎片,这个特别重要,因为模块化碎片让您可以通过更改碎片的组合方式来适应不同屏幕的尺寸,在设计可同时支持平板电脑和应用时,我们可以在不同的布局配置中复用我们的碎片,以根据可用的屏幕空间优化用户体验,例如,在手机上,如果不能再同一个 Activity 内放多个放多个碎片 Fragment,可能必须利用单独碎片来实现单窗格 UI


三、如何创建 Fragment


1)静态创建 Fragment


       直接把 Fragment 当作一个普通的控件,在 Activity 的布局文件中声明,这里我们写一个简单的实例来演绎,在一个活动当中添加两个 Fragment


新建一个 ContentFragment 布局文件,fragment_content.xml,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Content"
        android:background="#059df7"
        android:textSize="20sp"
        android:textStyle="bold" />
</LinearLayout>

然后我们再新建一个底部 BottomFragment 布局文件,fragment_bottom.xml,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#686e68"
        android:gravity="center"
        android:text="Button"
        android:textAllCaps="false"
        android:textColor="#faf4f4"
        android:textSize="20sp" />
</LinearLayout>

上面的两个布局都非常简单,我们就不在赘述,接着新建一个 ContentFragment 类并让它继承 Fragment


       注意这里会有两个不同的包下的 Fragment 供我们选择,一个是系统内置的 andorid.app.Fragment,一个是 support - v4 库中的android.support.v4.app.Fragment,这里强烈建议大家使用 support - v4 库中的 Fragment ,因为它可以让 Fragment 在所有 Android系统版本中保持功能一致性,比如说 Fragment 中嵌套使用 Fragment,这个功能在 Android 4.2 系统中才开始支持,如果你使用的是系统内置的 Fragment,那么如果是 4.2 之前的设备运行你的程序就会崩溃,而使用 support - v4 库的 Fragment 就不会出现这个问题,另外我们并不需要在 build.gradle 中添加,因为 build.gradle 文件中已经添加了 appcompat - v7 库的依赖,而这个库会将 support - v4 库也一起引入进来


现在我们来编写 ContentFragment 中 的代码,如下:


public class ContentFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_content, container, false);
        return view;
    }
}

       这里仅仅重写了 Fragment 的 onCreateView() 方法,然后在这个方法中通过 LayoutInflater 的 inflate() 方法将我们刚才定义好的fragment_content 布局加载进来,接着我们用同样的方法新建 BottomFragment,代码如下:


public class BottomFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_bottom, container, false);
        return view;
    }
}

代码和上面基本都是相同的,接下来我们修改 activity_main.xml 中的代码,如下:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <fragment
        android:id="@+id/fragment_content"
        android:name="com.example.qiudengjiao.fragmenttest.ContentFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="7" />

    <fragment
        android:id="@+id/fragment_bottom"
        android:name="com.example.qiudengjiao.fragmenttest.BottomFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

       可以看到,我们使用了 <fragment> 标签在布局中添加了 Fragment,我们通过 android:name 属性来显式指明添加 Fragment 的类名,注意一定要类的包名也加上,这样一个最简答的 Fragment 静态加载示例就创建完成了,运行程序如下图:




2)动态创建 Fragment


       上面我们了解了在布局文件中静态创建 Fragment,但是其实碎片最强大的地方在于它可以在程序运行时动态的添加到活动当中,根据具体的使用情况动态的来添加 Fragment,接下来我们就来了解如何动态的添加碎片,我们在上刚才的代码基础上接着修改,新建 another_fragment_content.xml,代码如下:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#059df7"
        android:gravity="center"
        android:text="AnotherContent"
        android:textSize="20sp"
        android:textStyle="bold" />
</LinearLayout>

这个布局文件和刚才的基本一样,不做太多介绍,然后新建 AnotherContentFragment,代码如下所示:


public class AnotherContentFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.another_fragment_content, container, false);
        return view;
    }
}

修改 activity_main.xml 中的代码如下:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:id="@+id/frameLayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="7">

    </FrameLayout>

    <fragment
        android:id="@+id/fragment_bottom"
        android:name="com.example.qiudengjiao.fragmenttest.BottomFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

       可以看到,现在将上面的 fragment 替换成了一个 FrameLayout,由于这里只需要在布局中放入一个 Fragment 不需要任何定位,所以 FrameLayout 比较合适,下面我们将在代码中向 FrameLayout 里添加内容,从而实现动态添加 Fragment 功能,修改 MainActivity 中的代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);
        replaceFragment(new ContentFragment());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                replaceFragment(new AnotherContentFragment());
                break;
            default:
        }
    }

    private void replaceFragment(Fragment fragment) {
        //调用 getSupportFragmentManager() 方法获取 FragmentManager
        FragmentManager fragmentManager = getSupportFragmentManager();
        //通过 beginTransaction() 方法开启一个事务
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        //通过 replace() 方法向容器添加或替换 Fragment
        fragmentTransaction.replace(R.id.frameLayout, fragment);
        //通过 commit() 方法来提交事务
        fragmentTransaction.commit();
    }
}

       看一看到,首先我们给底部碎片(BottomFragment)中的按钮注册了一个点击事件,然后调用 replace() 方法动态添加上面部分的 Fragment,这样就完成了动态添加 Fragment 的功能,接下来我们来总结一下:

(1)创建待添加 Fragment 实例

(2)通过调用 getSupportFragmentManager() 方法获取 FragmentManager

(3)通过 beginTransaction() 方法开启一个事务

(4)通过使用 replace() 方法实现 Fragment 的替换,需要传入容器的 id 和待添加 Fragment 的实例

(5)调用 commit() 方法来提交事务

通过这么 5 步,我们就完成了动态添加 Fragment 功能


四、在碎片中模拟返回栈


       我们已经能动态的实现添加 Fragment 功能,不过我们发现通过点击按钮添加了一个 Fragment 之后,这时按下 Back 键程序就会直接退出,如果这里我们想模仿类似于返回栈的效果,点击按钮返回到上一个Fragment,该如何实现

       其实系统已经给我们提供了相关的 API,FragmentTransaction 中提供了一个 addToBackStack() 方法,可以用于将一个事务添加到返回栈中,修改 MainActivity 中的代码如下所示:


    private void replaceFragment(Fragment fragment) {
        //调用 getSupportFragmentManager() 方法获取 FragmentManager
        FragmentManager fragmentManager = getSupportFragmentManager();
        //通过 beginTransaction() 方法开启一个事务
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        //通过 replace() 方法向容器添加或替换 Fragment
        fragmentTransaction.replace(R.id.frameLayout, fragment);
        fragmentTransaction.addToBackStack(null);
        //通过 commit() 方法来提交事务
        fragmentTransaction.commit();
    }
       这里看到我们在提交事务之前添加了 addToBackStack() 方法,它可以接受一个名字用于描述返回栈的状态,一般传入 null 即可,这样就实现了程序的回退

五、Fragment 的生命周期


       和 Activity 一样,Fragment 也有自己的生命周期,它包含与 Activity 类似的回调方法,接下来我们也来看一下 Fragment 的生命周期图,来自 Google 官网:



       Fragment 必须依存于 Activity 而存在,所以 Activity 的生命周期直接影响到 Fragment 的生命周期,官网也有很好的图对此做了相应的说明,如下图:




综合上面的两张图让我们看到 Fragment 比 Activity 多了几个生命周期回调方法:


onAttach():当 Activity 与 Fragment 发生关联时调用

onCreateView():创建 Fragment 的视图

onActivityCreated():当 Activity 的 onCreate() 方法返回时调用,或者说当 Activity 的 onCreate() 方法执行完时调用

onDestroyView():与 onCreateView() 相对应,Fragment 中的布局被移除时调用

onDetach():与 onAttach() 相对应,当 Activity 与 Fragment 解除关联的时候调用


       这里其实还有一个 onViewCreated() 回调方法,在 onCreateView() 完成之后 onActivityCreated() 之前调用,会 对 Fragment 本身的视图进行一次初始化,使子类有机会初始化自己一次,并且不会附加到父类,也可以把保存的相应状态数据在视图恢复之前恢复

接下来我们来看看 Fragment 的生命周期回调方法,结合 Activity 来分析,和 Activity 一样,也有运行状态,暂停状态,停止状态和销毁状态这 4 种


1)运行状态


当一个碎片是可见的,并且它所关联的活动正处于运行状态,该碎片也处于运行状态


2)暂停状态


当一个活动进入暂停状体时(由于另一个未占满屏幕的活动被添加到了栈顶),与它相关联的可见碎片就会进入到暂停状态,


3)停止状态


       当一个活动进入停止状态时,与它相关联的碎片就会进入到停止状态,或者通过调用 FragmentTransaction 的 remove() 或replace() 方法将碎片从活动中移除,但是如果在提交事务之前调用 addToBackStack() 方法,这时碎片也会进入到停止状态,总的来说,进入到停滞状态的碎片,用户也是不可见的,有可能会被系统回收


4)销毁状态


Fragment 总是依附于活动存在的,因此当活动被销毁时,与它相关联的 Fragment 就会进入到销毁状态


接下来我们一起来体验 Fragment 的生命周期不同阶段的方法回调:

修改 ContentFragment 中的代码,如下所示:

public class ContentFragment extends Fragment {
    private static final String TAG = "ContentFragment";

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.e(TAG, "onAttach");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate");
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_content, container, false);
        Log.e(TAG, "onCreateView");
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.e(TAG, "onActivityCreated");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.e(TAG, "onStart");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.e(TAG, "onResume");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.e(TAG, "onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.e(TAG, "onStop");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.e(TAG, "onDestroyView");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.e(TAG, "onDetach");
    }
}

      我们在 ContentFragment 中的每一个生命周期方法里都加入了打印日志的代码,然后重新运行程序,这时 logcat 中的代码打印如下:




        可以看到,当 ContentFragment 第一次被加载到屏幕上时,会依次执行 onAttach( )-> onCreate() -> onCreateView() -> onActivityCreated() -> onStart() -> onResume() 方法然后点击底部的按钮,此时打印信息如下:



 

        由于 AnotherContentFragment 替换了 ContentFragment,所以此时的 ContentFragment 进入了停止状态,因此 onPause() -> onStop() -> onDestroyView() 方法得到执行,当然如果在替换的时候没有调用 addToBackStack() 方法,此时的 ContentFragment 就会进入销毁状态,onDestory() 和 onDetach() 方法就会得到执行

按下 Back 键 ContentFragment 会重新回到屏幕,打印信息如下:


       

      由于 ContentFragment 重新回到了运行状态,因此 onCreateView() -> onActivityCreated() -> onStart() -> onResume() 方法会得到执行,注意此时 onCreate() 方法并不会执行,因为我们借助 addToBackStack() 方法使得 ContentFragment 并没有销毁

在按 Back 键退出程序,打印日志如下:



依次会执行 onPause()->onStop()->onDestroy()->onDestroy()->onDetach() 方法,最终碎片销毁,并解除和活动的关联


       现在我们重新进入程序,当进入 ContentFragment 界面后这次我们不点击 Back 键,而是点击 Home 键,我们来看看 logcat 打印情况:

点击打开程序 ContentFragment 被加载,上面的生命周期已经贴出,这里不再重复,我们看点击 Home 键:


       另外值得注意得的是,在碎片中我们也可以通过 onSaveInstanceState() 方法来保存数据,因为进入停止状态的碎片有可能在内存不足的情况下被回收,保存下来的数据在 onCreate()、onCreateView()、onActivityCreated() 这 3 个方法中都可以重新得到,它们都含有一个 Bundle 类型的 savedInstanceState 参数




重新进入,logcat 打印情况:



经过这些 logcat 的打印情况,相信大家也有了更深的认识,和我们的 Activity 是不是也很像,可以结合记忆


六、Fragment 和 Activity 之间通信


       因为 Fragment 都是嵌入在 Activity 中显示的,并且是依附于 Activity 的,可以看到 Activity 和 Fragment 都是个自存在于自己的一个独立的类中,他们之间并没有明显的方式来直接进行通信,如果要在 Activity 中调用 Fragment 里的方法,或者在 Fragment 中调用 Activity 中的方法,我们该如何实现


1)在 Activity 中调用 Fragment 中的方法


       为了方便 Fragment 和 Activity 之间的通信,FragmentManager 提供了一个类似于 findViewById() 的方法,专门用于从布局文件中获取 Fragment 的实例,代码如下:

 BottomFragment bottomFragment = (BottomFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_bottom);

       调用 getSupportFragmentManager() 的 findFragmentById() 方法,可以在活动中得到相应的 Fragment 实例,然后就可以调用 Fragment 中的 public 方法


2)在 Fragment 中调用 Acitivity 中的方法


       掌握如何在 Activity 中调用 Fragment 中的方法,我们来学习如何在 Fragment 中调用 Activity 中的方法,其实在每个 Fragment中都可以调用 getActivity() 方法来得到和当前 Fragment 相关联的 Activity 的实例,代码如下:


 MainActivity activity = (MainActivity) getActivity();

       有了 Activity 实例以后,在 Fragment 中就可以调用 Activity 中的 public 方法,另外当 Fragment 中需要使用 Context 对象时,也可以使用 getActivity() 方法,因为获取到的 Activity 本身就是一个 Context 对象,如果该 Context 需要在 Activity 销毁后还存在,则可以使用 getActivity().getApplicationContext()


3)Fragment 和 Activity 通信总结


1. 如果 Activity 中包含自己 Fragment 的引用,则可以通过引用直接访问 Fragment 中的 public 方法

2. 如果 Activity 中没有保存 Fragment 的引用,也没有关系,每个 Fragment 都有自己唯一的 tag 或 id,可以通过getSupporFragmentManager().findFragmentById() 或者 getSupporFragmentManager().findFragmentByTag() 获取到相应 Frament的实例进行操作

3. 在 Fragment 中可以通过 getActivity() 方法获取到当前关联的 Activity 的实例,然后进行相关操作


4)Fragment 和 Activity 通信实例演练


除了上面所说的通信方式外,我们还可以通过接口回调的方式来进行 Fragment 和 Activity 之间通信

现在我们修改 BottomFragment 中的代码如下:


public class BottomFragment extends Fragment implements View.OnClickListener {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_bottom, container, false);
        Button button = (Button) view.findViewById(R.id.button);
        button.setOnClickListener(this);
        return view;
    }

    /**
     * 设置点击按钮的回调
     */
    public interface BFbtnOnclickListener {
        void onBottomFragmentClick();
    }

    /**
     * 交给宿主Activity处理,如果它需要处理
     *
     * @param v
     */
    @Override
    public void onClick(View v) {
        if (getActivity() instanceof BFbtnOnclickListener) {
            ((BFbtnOnclickListener) getActivity()).onBottomFragmentClick();
        }
    }
}

       这里看到我们在 BottomFragment 中直接直接实现了按钮的点击事件,这样现在的 Fragment 不和任何 Activity 耦合,任何Activity 都可以使用,并且我们声明了一个接口来回调其点击事件,想要管理其点击事件的 Activity 实现此接口就可以,我们在onClick() 方法中首先判断了当前绑定 Activity 是否实现了该接口,如果实现了则调用

接下来我们来看 MainActivity 中的代码:


public class MainActivity extends AppCompatActivity implements BottomFragment.BFbtnOnclickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        replaceFragment(new ContentFragment());
    }

    @Override
    public void onBottomFragmentClick() {
        replaceFragment(new AnotherContentFragment());
    }
    
    private void replaceFragment(Fragment fragment) {
        //调用 getSupportFragmentManager() 方法获取 FragmentManager
        FragmentManager fragmentManager = getSupportFragmentManager();
        //通过 beginTransaction() 方法开启一个事务
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        //通过 replace() 方法向容器添加或替换 Fragment
        fragmentTransaction.replace(R.id.frameLayout, fragment);
        fragmentTransaction.addToBackStack(null);
        //通过 commit() 方法来提交事务
        fragmentTransaction.commit();
    }
}

大家可以结合我们之前的实现方式,看看我们现在这样的实现有什么好处,这样我们点击按钮,实现了和之前一样的点击切换效果


七、Fragment 和 Fragment 通信


       通常情况下,我们在项目的实际开发中,一个 Activity 中可能会包含多个 Fragment,这时多个 Fragment 之间有时也需要进行信息传递的应用场景,这时 Fragment 和 Fragment 之间的通信就显得特别重要,其实通过我们上面 Fragment 和 Activity 之间的通信分析,我们应该可以想到,首先一个 Fragment 可以得到与它相关联的 Activity,然后再通过这个 Activity 去获取另一个 Fragment的实例,演示如下,我们在 BottomFragment 中去访问 ContentFragment 中的视图:

我们修改 ContentFragment 的布局文件 fragment_content.xml 如下:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/contentFragment_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#059df7"
        android:gravity="center"
        android:text="Content"
        android:textSize="20sp"
        android:textStyle="bold" />
</LinearLayout>

       这里我们给 TextView 添加了 id,其他的还和原来的一样,没有什么改变,接下来我们就要演示如何在 BottomFragment 中获取到 fragment_content.xml 中的控件,修改 BottomFragment 代码如下:


public class BottomFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_bottom, container, false);
        return view;
    }


    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        Button button = (Button) getActivity().findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                TextView textView = (TextView) getActivity().findViewById(R.id.contentFragment_text);
                Toast.makeText(getActivity(), textView.getText(), Toast.LENGTH_LONG).show();
            }
        });
    }
}

       这里看到,我们重写了 onActivityCreated() 生命周期方法的回调,通过 getActivity() 这个方法成功获取到了 ContentFragment 中的视图,getActivity() 方法可以让 BottomFragment 获取到关联的 Activity,然后再调用 Activity 的 findViewById() 方法,就可以获取到和这个 Activity 关联的其他 Fragment 的视图了


       如果还想了解更多的 Fragment 的用法 请看 Android Fragment 完全解析(下) 这里对 Fragment 使用的相关 API,如何解耦 Fragment 和 Activity 耦合度,复用 Fragment,以及 startActivityForResult 在 Fragment 中的用法等做了详细的介绍


今天就分享到这里,又是周五了,大家周末愉快

参考:Google 官网,郭神第一行代码


MyBatis示例 MyBatis示例 基本示例 环境准备 jdk : 1.8.0 MyEclipse MySQL MyBatis-3.4.6.jar 新建JavaWeb Project 命名:mybatis 导入JAR包或添加POM.xml中添加依赖 MyBatis_config.xml &amp;amp;amp;amp;amp;lt;?xml version=&amp;amp;amp;amp;quot;1.0&amp;amp;amp;amp;quot; encoding=&a 阅读详情

相关推荐

音视频开发—H264相关概念和压缩原理详解(GOP、宏块、帧内压缩、帧间压缩)

本文讲述了H264相关概念和原理——GOP概念,SPS与PPS,帧内压缩原理,帧间压缩原理,解释了什么是运动补偿,什么运动矢量等等概念

weixin_46999174的博客 3978

Fragment的使用(Android实现底部导航栏)

  一、布局页面添加 1.添加四个切换页面的布局 (1)四个切换页面的布局(四个页面相同): &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_wid...

Sir.迷航 6832

别再浪费HDRI了!D5渲染器环境光设置避坑指南(附天空球调试参数)

本文深入解析D5渲染器中HDRI环境光的高阶调试技巧,揭示90%渲染师常犯的错误认知。通过参数联动黄金法则、特殊材质应对方案及动态场景优化策略,帮助用户精准控制光子能量分布,实现建筑玻璃反射云层过渡等专业级效果。附赠天空球调试参数和商业项目验证案例,助您彻底释放HDRI潜力。

weixin_29216049的博客 495

Android中的颜色设置

原文地址:http://www.cnblogs.com/bluestorm/p/3644669.html 1、在android中经常看到设置的颜色为八位的十六进制的颜色值,例如: 1 2 3 public static final class color {     public static final int lightb

buyanSH的码农学习笔记 1167

【软件安装系列】Ubuntu+mysql5.7.27+Jira8.3.1+邮箱服务器配置+Confluence6.15.7安装经验和采坑总结

文章目录一、软件准备(百度云易被吞,就不放了)1.1 官网下载的新鲜的Jira和Confluence1.2 linux的jdk一份1.3 Jira和Confluence的破解程序或者破解包一份1.4 java的连接器一份二、安装过程1--java环境配置2.1 将下载下来的jdk包解压在/usr/local/java目录中2.2 写入环境变量三、安装过程2--mysql5.7.27环境配置3.1 ...

xiaosha_的博客 6892

微信小程序推送微信服务号模板消息

微信小程序中发送微信服务号模板消息,无需用户手动确认订阅,无需绑定开放平台,无需使用UnionId。

qq_20751269的博客 1556

Android(1) Fragment静态使用

1.Fragment介绍 Fragment可以解决App同时适应手机和平板 布局 的问题。 Fragment当成Activity的一个界面的一个组成部分,Activity的界面也可以由不同的Fragment组成, Fragment拥有自己的生命周期和接收、处理用户的事件,于是我们就不必在Activity里面写一堆控件的事件处理的代码 更重要的是,我们可以动态的添加,替换和移除某个Fragm...

郑清 1780

我用两个月时间,终于把优快云付费资源项目玩明白了!

关于项目的定位,这是一个知识付费项目,根据市场研究机构的数据显示,到2023年,全球知识付费市场规模将达到2000亿美元,所以说知识付费的前景是十分广阔的,当下互联网时代信息大爆炸,80后、90后、00后群体对知识付费的认可度也大幅提升,同时这群作为知识付费的主流人群已经具备了更强的消费能力,而且对于知识付费的需求更高。目前整个知识付费领域仍然在发展起步的初期,尽快在知识付费领域布局可以帮助我们在这波红利中获得一份不错的收益。而且个人认为,

白话机器学习 2万+

设置按峰值带宽计费_分布式直播系统(十)【一条配置搞定流量计费】

转载请注明出处:https://blog.youkuaiyun.com/impingo 项目地址:https://github.com/im-pingo/pingos官网地址:https://pingos.io流量计费方式在直播系统中最暴力直接的计费方式莫过于记录下每段时间内客户的流量了,然后根据流量总值进行收费,而CDN行业则流传着一种被称作95峰值计费的方案。 我们以网宿和阿里的95峰值计费方式为例介绍这...

weixin_39909366的博客 672

用PY32F003F18的PWM互补输出驱动无刷电机,保姆级配置流程(含代码)

本文详细介绍了如何利用PY32F003F18微控制器的TIM1定时器配置PWM互补输出功能来驱动三相无刷电机,涵盖硬件设计、代码实现及六步换相算法。通过保姆级配置流程和实用代码示例,帮助开发者快速掌握无刷电机驱动技术,适用于工业自动化和消费电子等领域。

weixin_26905487的博客 379

【Java核心高阶进阶】44-Java8核心新特性

模块十:Java新特性演进 · 第 1 篇Java 8 是 Java 语言历史上最重要的一次发布,它引入的函数式编程范式从根本上改变了 Java 的编码方式。即便到了 JDK 21 的今天,Lambda、Stream、Optional 仍是日常开发的高频工具。本篇将深入这些特性的语法、原理与底层机制,帮助你不仅会用,更知其所以然。

gaochufukanyongren的博客 24

Android Fragment 真正的完全解析(上)

自从Fragment出现,曾经有段时间,感觉大家谈什么都能跟Fragment谈上关系,做什么都要问下Fragment能实现不~~~哈哈,是不是有点过~~~ 本篇博客力求为大家说明Fragment如何产生,什么是Fragment,Fragment生命周期,如何静态和动态的使用Fragment,Fragment回退栈,Fragment事务;以及Fragment的一些特殊用途,例如:没有布局的Frag

Hongyang 90万+

手把手教你学Simulink——逆变器场景:基于PR控制器的单相逆变器并网控制策略仿真

摘要:本文详细介绍基于PR控制器的单相逆变器并网控制策略的Simulink仿真实现。首先分析PR控制器在单相逆变应用中的优势,然后逐步讲解模型搭建过程,包括主电路设计(直流电源、全桥逆变器、L滤波器)、控制回路实现(参考电流生成、坐标变换、PR控制器设计)以及关键参数设置。通过仿真验证了PR控制器对电网频率的精确跟踪能力,并网电流THD<3%。最后提出优化建议,如加入状态观测器、自适应参数整定等改进方向。该建模方法为可再生能源系统中的逆变器控制提供了有效验证手段。

MHD0815的博客 497

Android Fragment完全解析

Android Fragment完全解析

qq_37159335的博客 1054

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Android Fragment 真正的完全解析

日后遇见好的文章还会不断更新,所有的fragment都会汇集到这篇文章下 我这行为就相当于什么呢,淘宝的导购网站吧,哈哈 说到fragment,必须要奉上鸿洋大神,写的太好了、太生动、太透彻了, 实在无法超越,我就引用啦哈哈。必须存着,android知识太多了,一阵子不用就会忘记。温故而知新。鸿洋大神:Android Fragment 真正的完全解析(上) http://blog.csdn.n

记录,如果有幸能帮到你,是我的荣幸 787

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Android Fragment 真正的完全解析(下)

本篇将介绍上篇博客提到的:如何管理Fragment回退栈,Fragment如何与Activity交互,Fragment与Activity交互的最佳实践,没有视图的Fragment的用处,使用Fragment创建对话框,如何与ActionBar,MenuItem集成等~~

2501_90255873的博客 961

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android Fragment 真正的完全解析 下

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 转载请标明出处:htt

sdfwcc的博客 272

Android studio 中fragment的完全解析

转载请注明出处:http://blog.youkuaiyun.com/guolin_blog/article/details/8881711 我们都知道,Android上的界面展示都是通过Activity实现的,Activity实在是太常用了,我相信大家都已经非常熟悉了,这里就不再赘述。 但是Activity也有它的局限性,同样的界面在手机上显示可能很好看,在平板上就未必了,因为平板的屏幕非常大,手机的界面放在平板上可能会...

weixin_44798044的博客 5360

Android Fragment 真正的完全解析 上

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 转载请标明出处:htt

sdfwcc的博客 303
上一篇: Android Activity 完全解析(下)
下一篇: Android Fragment 完全解析(下)
QDJdeveloper
博客等级 码龄11年 108粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值