Fragment的粗浅理解

Fragment:

1.它是对于Activity界面实现的一种途径,相对于已经绑定的Layout,他更轻便,更灵活,更具有自由度和可设计性。

2.Fragment的功能正如他的正文意思所言,他是一个片段,不同于Layout的整体界面设计,Layout是一个整体,而Fragment相当于Layout的一部分

3.Activity只能绑定一个Layout界面,但一个Activity可以添加很多个Fragment界面。

4.Fragment拥有类似于Activity的生命周期,用以配合界面显示和交互

优势:相比于Activity跟轻量级,更加地高效和方便,无需在manifests文件中注册信息

劣势:设计的界面无法像Activity一样,通过网络和包名调用,也就是说,它只能应用于本地开发

Fragment的生命周期与Activity的生命周期对比:

注:此图来自网络

Fragment的方法执行顺序:

1.在Activity执行onCreate()的时候,添加此Fragment界面,此时进入Fragment的生命周期

2.生命周期执行顺序:(如图所示,以下是对于每个函数的调用时机和函数的作用)

1.初始化阶段:

onAttach(Activity)(当Fragment关联Activity时调用)>>>onCreate()>>>onCreateView(){此方法用来设计Fragment的界面}>>>onActivityCreated(){当Activity的onCreate()方法执行后返回时调用}
2.运行阶段:

基本与Activity一致,但Fragment的生命周期受制于Activity的周期:只有当Activity的生命周期处于onResumed()时,Fragment才能正常运行

3.摧毁阶段:

onDestoryedView(){摧毁Fragment的界面视图}>>>onDestoryed()>>>onDattch(){和Activity断开关联的时候调用此方法}

Fragment的使用方法:

1.在现在的Andtoid Studio中有默认的Fragment新建方法,

2.也可以自行创立Fragment方法,完成绑定,方法基本一致,默认的新建方法已经自行添加了对应的重写方法和界面绑定。

而自定义Fragment的步骤一般如下:

1.新建一个自定义的class类,继承Frament类,在Layout文件夹下新建一个XML界面文件;

(注:继承的Fragment来自的包邮几种,v4/app,当你使用你自己定义的Fragment的时候,一定要在使用的Activity中导入对应的Fragment包,否则会报错!)

2.在自定义的class类中重写onCreateView()方法,找到新建的xml界面文件,绘制Fragment的界面,并且对于此Fragment中控件的监听也在这里设置,其他的方法根据需求重写(如果继承的是v4的Fragment,那么你还需要申明onFragmentInterActionListener接口,留待调用的Activity实现)

3.在调用的Activity中添加此Fragment界面,并实现onFragmentInterActionListener接口(此接口可以空着不必书写任何内容,而具体他是用来干什么的,也并未弄清,以后看到此处,不懂去看,懂了补充)

注:这个自定义的步骤过程,使用默认的Fragment创建,会自动添加和绑定,很是方便,即使新建的结果并不符合要求,也可以很轻松的修改。

以上步骤的具体代码体现:

package andrew.com.custompaintdemo;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;          //在此使用的是V4包的Fragment类
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class BlankFragment extends Fragment {
    
    private static final String ARG_PARAM1 = "param1";      //这两个参数还没有弄明白具体用途
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    public BlankFragment() {                      //使用自定义的Fragment必须要给出一个空的构造方法
        // Required empty public constructor
    }

    public static BlankFragment newInstance(String param1, String param2) {
        BlankFragment fragment = new BlankFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;              //这是返回Fragment对象的方法,这个方法将两个参数打包放入一个叫Argmentss属性中,
    }                         //此属性在源码中解释是construction Argments的bundle对象,但未发现与Fragment有何关联

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment               //这里用来绑定Fragment的界面和空间监听事件
        return inflater.inflate(R.layout.fragment_main, container, false);
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {      //此接口必须在调用此Fragment的界面的Activity中实现,但可以在实现时,不做任何处理
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}

Activity界面中的代码:

package andrew.com.custompaintdemo;

import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;        //这里使用的是V7包中的AppCompatActivity,貌似V7兼容V4包的Fragment
                //但需要注意的是,AppCompatActivity与一些控件存在版本差距,导致不兼容,如出现不兼容情况,可选择直接继承Activity
public class MainActivity extends AppCompatActivity implements BlankFragment.OnFragmentInteractionListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState ==null){   getSupportFragmentManager()            //V7包中为getFragmentManager(),获取Fragment的管理
                       .beginTransaction()  //开始Fragment操作
                       .add(R.id.container ,
new BlankFragment())  //从父容器添加Fragment界面,另一种方法是replace(),此方法包含了一个界面remove()和add()方法
                       .commit();                      //提交修改 } } @Override
public void onFragmentInteraction(Uri uri) {    //这是声明后对于Fragment方法中的接口实现                                  //可以完全不写任何内容 } }


 

以上是基本的Fragment实现方法,

在基本方法的实现基础上,对于Fragment开发后出现了两种非常实用和美观的界面:SliderMenu Activity(侧滑界面),Tabbed (横向拉动切换界面)Activity。

SliderMenuActivity 源代码组成解析:

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

public class SliderViewDemo extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_slider_view_demo);        //控件组成:背景容器
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);      //控件组成:toolBar()这是一个处于顶部的横条控件
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);    //控件组成:右下角的邮箱按钮,
        fab.setOnClickListener(new View.OnClickListener() {                  //该邮箱按钮的点击监听事件
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);      //这是SliderMenu的主界面,绑定后设置一个ActionBarDrawerToggle
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(              //这里设置的navigation_drawer_open/close用于在onBackPressed中判断
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();      //可能这里有反复调用的同步逻辑,尚未研究透彻

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);  //控件组成:左侧列表的选项视图
        navigationView.setNavigationItemSelectedListener(this);                //由于本Activity实现了本方法,所以可以直接使用this
    }

    @Override
    public void onBackPressed() {                                //此函数是当界面处于左侧菜单列表时,
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);     //用于按下返回键后,回到主界面的,其中具体的函数逻辑暂时不清楚
        if (drawer.isDrawerOpen(GravityCompat.START)) {                    
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {                     //这里绑定右上角设置的menu内容
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.slider_view_demo, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {                  //这里添加对右上角setting内容的监听事件
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {              //这里添加对左侧菜单选项的监听事件
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camera) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;              //经测试,这里设置为false则所有的选项监听不执行
    }
}

在以上的SliderMenu Activity中使用了很多Frament的碎片化布局相互配合,共同实现了整体的界面效果,接下来解析Fragment部分的运行方式。

在XML文档中设置的Fragment界面中,共有四个界面组成部分:

1.activity_slider_view_demo(这是左侧菜单栏的Fragment)

代码分析:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">
  // include是一种优化布局的方式,将app_bar_slider_view_demo这个界面在背后显示,产生层次效果 <include layout="@layout/app_bar_slider_view_demo" android:layout_width="match_parent" android:layout_height="match_parent" />    
//这是实际的左侧菜单栏的界面 <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true"
     
     //这段代码绑定了nav_header_slider_view_demo的Fragment内容,该内容设计了左侧菜单栏的个人信息内容  app:headerLayout
="@layout/nav_header_slider_view_demo"   //这段代码用于绑定menu中的activity_slider_view_demo_drawer界面,该界面设计了左侧菜单具体的选项内容
     app:menu
="@menu/activity_slider_view_demo_drawer" />       (注:为结构清晰明了,在res目录下新建了menu文件夹,在此文件夹下添加的Fragment界面内容)

</android.support.v4.widget.DrawerLayout>


2.app_bar_slider_view_demo

具体代码分析:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="andrew.com.custompaintdemo.SliderViewDemo">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar              //这是一段系统给出的自定义控件界面,其中只有一个ToolBar,用来显示标题
            android:id="@+id/toolbar"                 //此AppBarLayout仅仅占用了一个标题栏的内容
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>           <include layout="@layout/content_slider_view_demo" />    //在标题存在的情况下,使用include标签显示content_slider_view_demo界面中的内容            //此Fragment是作为正式的显示内容,默认为空,可以由我们自己设置,使用默认的建立方法后,若想设置自己的内容样式,就是在此Fragment中设计

  <android.support.design.widget.FloatingActionButton      //这是右下角的邮箱图标的控件 android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>

3.content_slider_view_demo

代码分析:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="andrew.com.custompaintdemo.SliderViewDemo"
    tools:showIn="@layout/app_bar_slider_view_demo">

  //这是默认的正文显示内容,新建的时候,默认为空白
  //可以当做这里就是Activity的绑定界面,自定义一切可用控件
  //整个SliderMenu Activity只是一个框架,他提供了一个相对美观和具有良好交互体验的一个界面模板,而我们真正的设计,在这个Fragment中开始 </RelativeLayout>

4.nav_header_slider_view_demo

代码分析:

<?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="@dimen/nav_header_height"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">
  

  //这里正式先前提到的左侧聊表的个人信息模块设计面板
  //其中包括了头像,名称,邮箱
  //若我们需要显示不同的信息内容,也可以在这里进行自定义开发 <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="@dimen/nav_header_vertical_spacing" android:src="@android:drawable/sym_def_app_icon" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/nav_header_vertical_spacing" android:text="Android Studio" android:textAppearance="@style/TextAppearance.AppCompat.Body1" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="android.studio@android.com" /> </LinearLayout>


另外在res目录下,默认创建的menu文件中存在两个辅助文件:

1.activity_slider_view_demo_drawer(这是左侧菜单栏的选项设计)

具体代码:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_camera"                
            android:icon="@drawable/ic_menu_camera"
            android:title="Import" />            //选项名称:import
        <item
            android:id="@+id/nav_gallery"
            android:icon="@drawable/ic_menu_gallery"
            android:title="Gallery" />          
        <item
            android:id="@+id/nav_slideshow"
            android:icon="@drawable/ic_menu_slideshow"
            android:title="Slideshow" />
        <item
            android:id="@+id/nav_manage"
            android:icon="@drawable/ic_menu_manage"
            android:title="Tools" />
    </group>

    <item android:title="Communicate">
        <menu>
            <item
                android:id="@+id/nav_share"
                android:icon="@drawable/ic_menu_share"
                android:title="Share" />
            <item
                android:id="@+id/nav_send"
                android:icon="@drawable/ic_menu_send"
                android:title="Send" />
        </menu>
    </item>

</menu>
//注:这里不再是Fragment的内容,而是资源文件


2.slider_view_demo(这里设计的是右上角的设置内容)

具体代码:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_settings"      //这里只设计了一个setting选项
        android:orderInCategory="100"
        android:title="@string/action_settings"
        app:showAsAction="never" />
</menu>


PS:

Tabbed Activity有时间或又需要再具体分析!

原文地址:https://www.cnblogs.com/thinfog/p/5707743.html