碎片(Fragment)使用指南

[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核心的类有:

  1. Fragment:Fragment的基类,任何创建的Fragment都需要继承该类。
  2. FragmentManager:管理和维护Fragment。他是抽象类,具体的实现类是FragmentManagerImpl。
  3. FragmentTransaction:对Fragment的添加、删除等操作都需要通过事务方式进行。他是抽象类,具体的实现类是BackStackRecord。
  4. 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文件夹中的布局资源

你可能感兴趣的:(碎片(Fragment)使用指南)