[TOC]
1. 什么是碎片
碎片,是Android 3.0(API 11)提出的,为了兼容低版本,support-v4库中也开发了一套Fragment API,最低兼容Android 1.6。
过去support-v4库是一个jar包,24.2.0版本开始,将support-v4库模块化为多个jar包,包含:support-fragment, support-ui, support-media-compat等,这么做是为了减少APK包大小,你需要用哪个模块就引入哪个模块。
如果想引入整个support-v4库,则compile
'com.android.support:support-v4:24.2.1',
如果只想引入support-fragment库,则com.android.support:support-fragment:24.2.1。
1. Fragment是依赖于Activity的,不能独立存在的。
2. 一个Activity里可以有多个Fragment。
3. 一个Fragment可以被多个Activity重用。
4. Fragment有自己的生命周期,并能接收输入事件。
5. 我们能在Activity运行时动态地添加或删除Fragment。 复制代码
Fragment核心的类有:
- Fragment:Fragment的基类,任何创建的Fragment都需要继承该类。
- FragmentManager:管理和维护Fragment。他是抽象类,具体的实现类是FragmentManagerImpl。
- FragmentTransaction:对Fragment的添加、删除等操作都需要通过事务方式进行。他是抽象类,具体的实现类是BackStackRecord。
- Nested Fragment(Fragment内部嵌套Fragment的能力)是Android 4.2提出的,support-fragment库可以兼容到1.6。通过
getChildFragmentManager()
能够获得管理子Fragment的FragmentManager,在子Fragment中可以通过getParentFragment()
获得父Fragment。
优点:碎片的出现就是为了解决在正常3-6寸手机上显示正常,而到了某些大尺寸屏幕的设备上有些控件会过分拉长 元素之间空隙过大等情况,从而导致应用界面的不美观.
2. 碎片的使用方式
2.1 基本的使用方式
首先定义一个碎片的布局,然后再java文件中通过findview....id()的方式找到这个布局
//xml资源布局
xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#0000ff"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="3dp" />
android.support.constraint.ConstraintLayout>
复制代码
package example.h.fragment_demo2;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* code...
* Created by H on 2018/4/30.
*/
public class frag1 extends Fragment {
private String TAG="Fragment1的调试信息";
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle
savedInstanceState) {
View vie = LayoutInflater.from(getContext()).inflate(R.layout.f_layout1, container, false);
MainActivity mainActivity= (MainActivity) getActivity();
mainActivity.test();
return vie;
}
}
复制代码
自此已经成功的定义了一个碎片了.
那么如何使用这个碎片呢? 这只需要在活动的布局中添加控件就可以使用了 name属性指定要显示的碎片的名称(****.java) 其中必须设置每一个碎片的id 否者的话会产生一个致命错误导致程序蹦掉
2.2 碎片与Activity或碎片之间的通信
在活动中与碎片通信:
package example.h.fragment_demo2;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import static android.content.ContentValues.TAG;
/**
* code...
* Created by H on 2018/5/2.
*/
public class Fragment1 extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle
savedInstanceState) {
View v = LayoutInflater.from(getContext()).inflate(R.layout.f_layout1, container, false);
return v;
}
public void test(){
Log.d(TAG, "test: 碎片中的方法被调用了");
}
}
复制代码
Fragment1 fragment1= (Fragment1) getSupportFragmentManager().findFragmentById(R.id.ddd);
fragment1.test();
复制代码
在活动中只需要简单的调用这两行代码就可以与碎片进行通信了.
在碎片中与活动通信:
MainActivity mainActivity= (MainActivity) getActivity();
mainActivity.test();
复制代码
只需要在碎片中获取这个活动的实例就可以与活动进行通信了.
2.3 在碎片中模拟返回栈
当在一个碎片的基础上启动另外一个碎片的时候,点击back键这个程序直接退出了,如果想让它返回上一个碎片的话,需要在启动新的碎片前,把当前的碎片添加进返回栈
private void replace(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
//获取碎片的管理类
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//开启一个事务
fragmentTransaction.replace(R.id.right_layout, fragment);
//向容器内添加或替换碎片,这里时替换
fragmentTransaction.addToBackStack(null);
//事务提交之前 调用这个方法它可以接收一个名字用于描述返回栈的状态,一般传入null
//这样默认点返回键就不会马上退出程序了.
fragmentTransaction.commit();
//提交事务
}
复制代码
3. 碎片的生命周期
onAttach() 当碎片和活动建立关联的时候调用
onCreate() 当碎片被创建的时候调用
onCreateView(); 当碎片创建视图的时候调用 一般都i只实现这个方法
onActivityCreated() 确保与碎片相关联的的活动一定已经创建完毕的时候调用
onStart() 当碎片可见的时候调用
onResume() 当碎片可见且可交互时调用
碎皮已激活
onPause() 当碎片可见但不可交互的时候调用
onStop() 当碎片不可见时调用
onDestroyView() 当碎片的UI从视图结构中移除时调用
onDestroy() 当碎片被销毁时调用
onDetach() 当碎片和活动解除关联时调用
碎片销毁
4. 动态加载布局的技巧
通常一个应用如果没有给大尺寸的屏幕适配的话,这个App在这个手机上的显示效果就很差,有的控件会被过分拉长,或者间隙过大等等...如果你不想重新写一个app来适配平板的话,就可以在res文件夹中新建一个文件夹layout-large (限定符) 要在里面创建和layout同名的布局文件 app在运行的时候就会自动选择适合的布局
限定符(屏幕大小) 描述
small 提供给小屏幕设备的资源
normal 提供给中等屏幕设备的资源
large 提供给大屏幕设备的资源
xlarge 提供给超大屏幕设备的资源
限定符(分辨率)
ldpi 提供给低分辨率设备的资源(120dpi以下)
mdpi 提供给中等分辨率设备的资源(120dpi~160dpi)
hdpi 提供给高分辨率设备的资源(160dpi~240dpi)
xhdpi 提供给超高分辨率设备的资源(240dpi~320dpi)
xxhdpi 提供给超超高分辨率设备的资源(320dpi~480dpi)
限定符(方向)
land 提供给横屏设备的资源
port 提供给竖屏设备的资源
如果创建了一个 layout-sw600dp(最小宽度限定符)文件夹,那么当屏幕的宽度小于600dp的时候它默认使用原来的布局资源,但是如果大于600dp则会使用layout-sw600dp文件夹中的布局资源