安卓Fragment基础

目录


前言

Fragment基础使用笔记

一、基础使用

Activity布局和文件

xml 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false">

    <fragment
        android:id="@+id/fragment1"
        android:name="com.henry.FragmentTest.test1.Fragment1"
        android:layout_width="0dip"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <fragment
        android:id="@+id/fragment2"
        android:name="com.henry.FragmentTest.test1.Fragment2"
        android:layout_width="0dip"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>
java 复制代码
public class fragmentactivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments);
    }
}

两个Fragment布局文件

xml 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ff00" >
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is fragment 1"
        android:textColor="#000000"
        android:textSize="25sp" />
 
</LinearLayout>
xml 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffff00" >
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is fragment 2"
        android:textColor="#000000"
        android:textSize="25sp" />
 
</LinearLayout>

Fragment文件

java 复制代码
public class Fragment1 extends Fragment {
 
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		return inflater.inflate(R.layout.fragment1, container, false);
	}
 
}
java 复制代码
public class Fragment2 extends Fragment {
 
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		return inflater.inflate(R.layout.fragment2, container, false);
	}
 
}

显示:一个Activity很融洽地包含了两个Fragment,这两个Fragment平分了整个屏幕,效果如下:


二、动态添加Fragment

activity修改布局

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.henry.PreferenceTest.FragmentActivity"
    android:orientation="horizontal">
</LinearLayout>

activity动态获取fragment

java 复制代码
public class fragmentactivity extends AppCompatActivity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments);
        Display display = getWindowManager().getDefaultDisplay();
        if (display.getWidth() > display.getHeight()) {
            Fragment1 fragment1 = new Fragment1();
            getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment1).commit();
        } else {
            Fragment2 fragment2 = new Fragment2();
            getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment2).commit();
        }
    }

}

步骤如下:

获取到FragmentManager,在Activity中可以直接通过getFragmentManager得到。

开启一个事务,通过调用beginTransaction方法开启。

向容器内加入Fragment,一般使用replace方法实现,需要传入容器的id和Fragment的实例。

提交事务,调用commit方法提交。

三、Fragment的生命周期

Fragment 的生命周期包括以下方法:

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

onCreate(): 当 Fragment 创建时调用。

onCreateView(): 创建 Fragment 的视图层次结构时调用。

onActivityCreated(): 当与 Fragment 相关联的 Activity 完成 onCreate() 方法后调用。

onStart(): 当 Fragment 可见时调用。

onResume(): 当 Fragment 可交互时调用。

onPause(): 当 Fragment 失去焦点但仍可见时调用。

onStop(): 当 Fragment 不再可见时调用。

onDestroyView(): 当 Fragment 的视图层次结构被销毁时调用。

onDestroy(): 当 Fragment 被销毁时调用。

onDetach(): 当 Fragment 与 Activity 解除关联时调用。

下面是 Fragment 生命周期方法的执行顺序:

当 Fragment 被添加到 Activity 时,依次执行 onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()、onResume()。

当 Activity 进入后台或另一个 Fragment 覆盖当前 Fragment 时,依次执行 onPause()、onStop()。

当 Activity 回到前台或当前 Fragment 重新获得焦点时,依次执行 onStart()、onResume()。

当 Fragment 被移除或 Activity 被销毁时,依次执行 onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()。

四、Fragment之间进行通信

activity回到示例一中,包含两个fragment。

修改fragment2.xml,添加一个按钮:

xml 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ffff00" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is fragment 2"
        android:textColor="#000000"
        android:textSize="25sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Get fragment1 text"
        />

</LinearLayout>

fragment1.xml,为TextView添加一个id

xml 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ff00" >

    <TextView
        android:id="@+id/fragment1_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is fragment 1"
        android:textColor="#000000"
        android:textSize="25sp" />

</LinearLayout>

修改Fragment2.java,添加onActivityCreated方法,并处理按钮的点击事件:

java 复制代码
public class Fragment2 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment2, container, false);
    }

    @Override
    public void onActivityCreated(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.fragment1_text);
                Toast.makeText(getActivity(), textView.getText(), Toast.LENGTH_LONG).show();
            }
        });
    }
}

运行程序,点击一下fragment2上的按钮,效果如下

getActivity方法可以让Fragment获取到关联的Activity,然后再调用Activity的findViewById方法,就可以获取到和这个Activity关联的其它Fragment的视图了。

Fragment 之间还可以通过以下几种方式进行通信:

  • 通过 Activity:Fragment 可以通过与 Activity 通信来实现 Fragment 之间的通信。Fragment 可以通过 getActivity() 方法获取关联的 Activity,并通过 Activity 的方法或接口来传递数据或事件。
  • 直接调用其他 Fragment 的方法:如果一个 Fragment 持有对另一个 Fragment 的引用,可以直接调用另一个 Fragment 的公共方法来进行通信。这种方式适用于两个 Fragment 之间存在直接的关联关系的情况。
  • 使用 Bundle:可以通过设置 Fragment 的参数(通过 setArguments() 方法)来传递数据,在另一个 Fragment 中通过 getArguments() 方法获取数据。这种方式适用于需要在 Fragment 创建时传递数据的情况。
  • 使用接口回调:定义一个接口,在一个 Fragment 中实现该接口并在另一个 Fragment 中持有该接口的引用。通过接口回调的方式,一个 Fragment 可以调用另一个 Fragment 实现的接口方法来进行通信。
  • 使用广播:通过发送广播来实现 Fragment 之间的通信。一个 Fragment 发送广播,另一个 Fragment 注册广播接收器来接收广播消息。这种方式适用于需要跨组件通信的情况。
  • 使用共享 ViewModel:使用 Architecture Components 中的 ViewModel 来实现 Fragment 之间的通信。多个 Fragment 可以通过共享同一个 ViewModel 实例来共享数据和状态。

五、Fragment兼容手机和平板示例

核心在于实现两个activity_main布局文件,一个是res/layout,另一个在res/layout-land

Android系统又会根据当前的运行环境判断程序是否运行在大屏幕设备上,如果运行在大屏幕设备上,就加载layout-land目录下的activity_main.xml,否则就默认加载layout目录下的activity_main.xml。

res/layout/activity_main.xml

xml 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/menu_fragment"
        android:name="com.henry.FragmentTest.test1.MenuFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

res/layout-land/activity_main.xml

xml 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal"
    android:baselineAligned="false"
    tools:context=".MainActivity"
    >

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.henry.FragmentTest.test1.MenuFragment"
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        />

    <FrameLayout
        android:id="@+id/details_layout"
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="3"
        ></FrameLayout>

</LinearLayout>

fragmentactivity.java

java 复制代码
public class fragmentactivity extends AppCompatActivity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments);
    }

}

MenuFragment.java

java 复制代码
public class MenuFragment extends Fragment implements AdapterView.OnItemClickListener {

    /**
     * 菜单界面中只包含了一个ListView。
     */
    private ListView menuList;

    /**
     * ListView的适配器。
     */
    private ArrayAdapter<String> adapter;

    /**
     * 用于填充ListView的数据,这里就简单只用了两条数据。
     */
    private String[] menuItems = {"Sound", "Display"};

    /**
     * 是否是双页模式。如果一个Activity中包含了两个Fragment,就是双页模式。
     */
    private boolean isTwoPane;

    /**
     * 当Activity和Fragment建立关联时,初始化适配器中的数据。
     */
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        adapter = new ArrayAdapter<String>(activity, android.R.layout.simple_list_item_1, menuItems);
    }

    /**
     * 加载menu_fragment布局文件,为ListView绑定了适配器,并设置了监听事件。
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.menu_fragment, container, false);
        menuList = (ListView) view.findViewById(R.id.menu_list);
        menuList.setAdapter(adapter);
        menuList.setOnItemClickListener(this);
        return view;
    }

    /**
     * 当Activity创建完毕后,尝试获取一下布局文件中是否有details_layout这个元素,如果有说明当前
     * 是双页模式,如果没有说明当前是单页模式。
     */
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (getActivity().findViewById(R.id.details_layout) != null) {
            isTwoPane = true;
        } else {
            isTwoPane = false;
        }
    }

    /**
     * 处理ListView的点击事件,会根据当前是否是双页模式进行判断。如果是双页模式,则会动态添加Fragment。
     * 如果不是双页模式,则会打开新的Activity。
     */
    @Override
    public void onItemClick(AdapterView<?> arg0, View view, int index, long arg3) {
        if (isTwoPane) {
            Fragment fragment = null;
            if (index == 0) {
                fragment = new SoundFragment();
            } else if (index == 1) {
                fragment = new DisplayFragment();
            }
            getFragmentManager().beginTransaction().replace(R.id.details_layout, fragment).commit();
        } else {
            Intent intent = null;
            if (index == 0) {
                intent = new Intent(getActivity(), SoundActivity.class);
            } else if (index == 1) {
                intent = new Intent(getActivity(), DisplayActivity.class);
            }
            startActivity(intent);
        }
    }

}

使用了ArrayAdapter初始化ListView

menu_fragment.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ListView
        android:id="@+id/menu_list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

    </ListView>

</LinearLayout>

SoundFragment.java

java 复制代码
public class SoundFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.sound_fragment, container, false);
        return view;
    }

}

对应的布局文件

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ff00"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="28sp"
        android:textColor="#000000"
        android:text="This is sound view"
        />

</RelativeLayout>

DisplayFragment.java

java 复制代码
public class DisplayFragment extends Fragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.display_fragment, container, false);
        return view;
    }
}

对应的布局文件

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0000ff"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="28sp"
        android:textColor="#000000"
        android:text="This is display view"
        />
</RelativeLayout>

SoundActivity.java

java 复制代码
public class SoundActivity extends AppCompatActivity {

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

}

对应的布局,SoundFragment

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/sound_fragment"
    android:name="com.henry.FragmentTest.test1.SoundFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</fragment>

DisplayFragment

java 复制代码
public class DisplayFragment extends Fragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.display_fragment, container, false);
        return view;
    }
}

对应的布局,DisplayFragment

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0000ff"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="28sp"
        android:textColor="#000000"
        android:text="This is display view"
        />

</RelativeLayout>

手机上显示:

平板上显示:

相关推荐
安卓理事人4 小时前
安卓LinkedBlockingQueue消息队列
android
万能的小裴同学5 小时前
Android M3U8视频播放器
android·音视频
q***57745 小时前
MySql的慢查询(慢日志)
android·mysql·adb
JavaNoober6 小时前
Android 前台服务 "Bad Notification" 崩溃机制分析文档
android
城东米粉儿6 小时前
关于ObjectAnimator
android
zhangphil7 小时前
Android渲染线程Render Thread的RenderNode与DisplayList,引用Bitmap及Open GL纹理上传GPU
android
火柴就是我8 小时前
从头写一个自己的app
android·前端·flutter
lichong9519 小时前
XLog debug 开启打印日志,release 关闭打印日志
android·java·前端
用户693717500138410 小时前
14.Kotlin 类:类的形态(一):抽象类 (Abstract Class)
android·后端·kotlin
火柴就是我10 小时前
NekoBoxForAndroid 编译libcore.aar
android