Android之fragment的学习

Fragment

  1. 一个Activity可有多个fragment,fragment不能脱离Activity而存在; Activity是屏幕的主体,而fragment是Activity的一个组成元素。
  2. 有两种方式通过Activity加载fragment,动态和静态方法
静态加载fragment

在布局文件中写出fragment的布局,并且绑定一个fragment文件,通过一个Activity加载这个fragment,在activity中写入fragment,就可以显示出fragment的界面。
案例:
点击MainActivity中的字符,跳转到staticFragmentActivity,staticFragmentActivity加载出fragment。这个fragment是事先写好的,直接通过Activity就可以显示出来。
MainActivity的界面:
这里写图片描述

显示fragment的内容:
这里写图片描述

代码在通过staticFragmentActivity加载出fragment,我们在staticFragmentActivity的布局文件中加载了两个fragment,都是一样的内容:

这里写图片描述

最终的效果图为:
这里写图片描述

接下来我们看代码:
首先通过MainActivity跳转到staticFragmentActivity。

package com.example.apple.fragment;

import android.content.Context;
import android.content.Intent;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MainActivity extends AppCompatActivity {

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

        findViewById(R.id.textView).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //静态加载
                startActivity(new Intent(MainActivity.this,StaticFragmentActivity.class));
            }
        });
    }


}

接下来我们写出fragment及其布局文件,将二者绑定,注意fragment有多个生命周期,最主要的是onCreateView,在这个方法里面绑定布局

package com.example.apple.fragment;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * Created by apple on 2018/5/12.
 */ //创建列表fragemnt
public class listFragment extends Fragment {
    //fragemnt有多个生命周期


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    }

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

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

    //创建视图,最主要的生命周期
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_list, container, false);//是否绑定,因为已经绑定,所以false

        TextView textView=view.findViewById(R.id.textView1);
        return view;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onStop() {
        super.onStop();
    }

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

我们在通过staticFragmentActivity加载出fragment

package com.example.apple.fragment;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class StaticFragmentActivity extends AppCompatActivity {

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

StaticFragmentActivity的布局文件里引入fragment

<?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:background="#eab6b6"
    >

    <fragment
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/listFragment"
        android:layout_centerInParent="true"
        android:name="com.example.apple.fragment.listFragment"/>

    <fragment
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/listFragment2"
        android:layout_alignParentBottom="true"
        android:name="com.example.apple.fragment.listFragment"/>

</RelativeLayout>

fragment的布局:

<?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="#77b2e2">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:id="@+id/textView1"
        android:textColor="#e7bfbf"
        android:textSize="20sp"
        android:text="text1"
        android:gravity="center"
        />

</RelativeLayout>

好了大功告成。

动态加载fragment

1.即通过代码实现activity加载fragment。首先我们还是要写出fragment的布局,并且写出fragment的容器,容器是用来放置fragment的。我们在MainActivity的布局中写了两个平行的放置fragment的容器。id分别为“listContainer”和“listContainer2”。

 <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="150dp"
            android:layout_height="match_parent"
            android:id="@+id/listContainer"
            android:orientation="vertical"
            android:layout_margin="1dp"
            >

        </LinearLayout>
        <LinearLayout
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:id="@+id/listContainer2"
            android:orientation="vertical"
            android:layout_margin="1dp">
        </LinearLayout>


    </LinearLayout>

2.在MainActivity中,动态加载fragment,让fragment的内容显示在Main Activity的两个平行布局中。getSupportFragmentManager()是属于framgnetActivity的方法,而AppCompatActivity继承自fragmentActivity。
在add方法中,第一个参数是fragment放置容器的id,第二个参数是fragment,注意fragment在每次添加都要new一次,或者提前建立好,并且不能传入同一个fragment对象,否则报错:

Caused by: java.lang.IllegalStateException: Can't change container ID of fragment listFragment{27152b2 id=0x7f07003c}: was 2131165244 now 2131165245

代码为:

getSupportFragmentManager()
                .beginTransaction()//开启事务
                .add(R.id.listContainer,new listFragment())//将fragment布局放在listContainer中
                .commit();//提交
getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.listContainer2,new listFragment())
                .commit();

我们看一下显示效果:
这里写图片描述
3.除了动态的添加fragment碎片,我们也能删除碎片(remove)或者更改碎片(replace)
首先我们remove左边的碎片:
因为remove方法传入的参数是fragment,我们指定删除左边的,所以要对代码进行修改,新建一个fragment对象,在add到左边的布局

 listFragment listFragment=new listFragment();
        getSupportFragmentManager()
                .beginTransaction()//开启事务
                .add(R.id.listContainer,listFragment)//将fragment布局放在listContainer中
                .commit();//提交
        getSupportFragmentManager()
                .beginTransaction()
                .remove(listFragment)
                .commit();

显示效果为:
这里写图片描述

同样,我们也能修改碎片,在左右两边碎片都同时存在的基础上,我们对右边的碎片进行修改。这里我们新建一个fragment,并且将布局文件与fragment绑定。将右边的fragment替换。
新的fragment的布局文件:

<?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"
    android:gravity="center">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello"
        android:textSize="40sp"
        android:textColor="#ef4c4c"/>

</LinearLayout>

替换fragment:

getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.listContainer2,new listFragment2())
                .commit();

结果为:
这里写图片描述
4.我们也可以在activity和fragment之间进行传值,包括activity向fragment传值,fragment向activity传值,framgent向fragment传值。

activity向fragment传值

这里我们使用bundle传值。

 public static final String BUNDLE_TITLE = "bundle_title";//提取成静态常量
public static listFragment newInstance(String title){
        listFragment listFragment=new listFragment();
        Bundle bundle=new Bundle();
        bundle.putString(BUNDLE_TITLE,title);//将数据传递给bundle,在把bundle当作arguments传给fragment,最后返回fragment
        listFragment.setArguments(bundle);
        return listFragment;
    } 

再通过fragment的onCreate方法获取argument的值

private String mTitle=null;
@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(getArguments()!=null){
            mTitle=getArguments().getString(BUNDLE_TITLE);//提取成全局变量,
        }
    }

在初始化fragment时并对text初始化,赋值

View view = inflater.inflate(R.layout.fragment_list, container, false);//是否绑定,因为已经绑定,所以false
        TextView textView=view.findViewById(R.id.textView1);
        textView.setText(mTitle);

最后在MainActivity中通过代码设置framgent里面的text值

getSupportFragmentManager()
                .beginTransaction()//开启事务
                .add(R.id.listContainer,listFragment.newInstance("list1"))//将fragment布局放在listContainer中
                .commit();//提交

getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.listContainer2,listFragment.newInstance("listlist2"))
                .commit();

结果显示为
这里写图片描述
以上便是activity向fragment传值。

fragment向activity传值

这里我们使用回调的方法,即Callback。我们使用接口回调。
我们点击fragments里面的text如list1,listlist2就可以改变activity的内容,比如说在界面里显示的fragment的项目名。activity接收了fragment的传入的值后,就将名称改变。
首先我们在fragment文件里定义一个点击事件的接口:

//1.定义接口
    public interface  onTitleCLickListener{
        void onClick(String title);
    }

接下来是定义接口的全局变量

//2。定义全局变量
    private  onTitleCLickListener mOnTitleCLickListener;

第三步是设置接口的方法(类似于点击事件调用接口)

//3。设置接口的方法
    public void setOnTitleCLickListener(onTitleCLickListener onTitleCLickListener) {
        mOnTitleCLickListener = onTitleCLickListener;
    }

因为我们是对text设置点击事件,所以textView要设置监听事件,调用onClick方法,点击后就可以调用mOnTitleCLickListener的点击事件,把fragment的值传递给activity

textView.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               if(mOnTitleCLickListener!=null){
                   mOnTitleCLickListener.onClick(mTitle);
               }
           }
       });

在MainActivity里面,对mOnTitleCLickListener的onClick方法进行定义
即改变activity的title值

@Override
    public void onClick(String title) {
        setTitle(title);//点击fragment,将值回调给activity并且改变activity的名字
    }

最后加载每一个fragment,设置text的值并设置点击事件

listFragment listFragment= com.example.apple.fragment.listFragment.newInstance("list1");
        getSupportFragmentManager()
                .beginTransaction()//开启事务
                .add(R.id.listContainer,listFragment)//将fragment布局放在listContainer中
                .commit();//提交
        listFragment.setOnTitleCLickListener(this);
        listFragment listFragment2= com.example.apple.fragment.listFragment.newInstance("list2");
        getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.listContainer2,listFragment2)
                .commit();
        listFragment2.setOnTitleCLickListener(this);

效果图为:(这是点击左边的效果)
这里写图片描述

猜你喜欢

转载自blog.csdn.net/ayangann915/article/details/80291069