android的fragment作用,android使用FragmentActivity、Fragment实现tab切换的功能

目前主流的app都在下面有一排按钮来选择切换页面,可以使用Fragment来实现Tab效果来达到目的,要想用Fragment 功能必须先让activity继承FragmentActivity,其原因是里面包含了Fragment运作的FragmentManager接口的实现类 FragmentManagerImpl ,由这个类管理所有Fragment的显示、隐藏,下面我们实现一个有首页和设置两个界面的切换效果

重叠问题描述

在android中应用程序异常结束的可能性是非常大的,比如一键清理,省电功能等。它们会直接就把你的应用给关闭啦,应用非正常关闭后你的应用里的activity都会被回收,但是应用里的Fragment却还存在并没有回收掉,当你再次打开的时候activity会重新创建,创建的时候它会自动找到之前没有销毁的Fragment来加载直接显示到Tab里面。这个时候你的代码初始化里面还有一个创建Fragment的代码,会再创建一次fragment,之前的Fragment就是野的啦没法控制啦,一直就在那显示着。知道啦原因下面说处理方法。

解决重叠问题

重写Activity的onAttachFragment这个方法,它带啦一个参数Fragment就是加载之前已经存在的对象,我们判断下是不是我们对应的tab对象是的话就直接设置上去,然后在创建tab的初始化函数里判断下只在在tab对象是null的时候才去实例化Fragment对象

示例代码

请自己引入android.support.v4  支持库

首先创建两个界面的类继承Fragment,首页类HomeFragment和设置类SetFragment

HomeFragment.javapackage com.androidnodesocket;

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;

/**

* Created by Administrator on 2017-10-16.

*/

public class HomeFragment extends Fragment {

@Override

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

View view= inflater.inflate(R.layout.activity_home, container, false);

//取xml中的元素方法(跟activity中有一些不一样)

//        searchbtn = (TextView) view.findViewById(R.id.tv_top_title);

return view;

}

}

SetFragment.javapackage com.androidnodesocket;

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;

/**

* Created by Administrator on 2017-10-16.

*/

public class SetFragment extends Fragment {

@Override

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

View view= inflater.inflate(R.layout.activity_set, container, false);

return view;

}

}

布局文件 activity_home.xml和activity_set.xml这两个文件很简单就一个字符串就不贴代码啦自己创建好就行,然后就是创建一个主的框架类来加载这两个页面起个名字 MainFragmentActivitypackage com.androidnodesocket;

import android.os.Bundle;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentActivity;

import android.support.v4.app.FragmentManager;

import android.support.v4.app.FragmentTransaction;

import android.view.View;

import android.widget.Button;

/**

* Created by Administrator on 2017-10-16.

*/

public class MainFragmentActivity extends FragmentActivity {

private FragmentManager fmg;

private Fragment fmHome,fmSet;

private Button btnHome,btnSet;

@Override

public void onAttachFragment(android.app.Fragment fragment) {

super.onAttachFragment(fragment);

//下面代码处理系统因为省电或其它原因关闭activity后fragment没有关闭再次创建activity时fragment重叠的问题

if (fmHome == null && fragment instanceof HomeFragment) {

fmHome = (HomeFragment) fragment;

} else if (fmSet == null && fragment instanceof SetFragment) {

fmSet = (SetFragment) fragment;

}

}

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_mainfragment);

btnHome = (LinearLayout) findViewById(R.id.nav_home);

btnSet = (LinearLayout) findViewById(R.id.nav_set);

//初始化管理器

fmg = getSupportFragmentManager();

if(fmHome == null){

fmHome = new HomeFragment();

}

if(fmSet==null){

fmSet = new SetFragment();

}

//初始化的时候需要显示一个fragment,假设我们显示第二个fragment

//向容器中添加或者替换fragment时必须  开启事务  操作完成后   提交事务

FragmentTransaction ft = fmg.beginTransaction();

ft.add(R.id.main_container, fmHome).commit();

}

/**

* 单击导航调用此方法

*

* @param v

*/

public void clickNav(View v) {

int id = v.getId();

FragmentTransaction ft = fmg.beginTransaction();

switch (id) {

case R.id.nav_home:

if (!fmHome.isAdded()) {

ft.hide(fmSet).show(fmHome).add(R.id.main_container, fmHome).commit();

} else {

ft.hide(fmSet).show(fmHome).commit();

}

break;

case R.id.nav_set:

if (!fmSet.isAdded()) {

ft.hide(fmHome).show(fmSet).add(R.id.main_container, fmSet).commit();

} else {

ft.hide(fmHome).show(fmSet).commit();

}

break;

}

}

}

布局文件 activity_mainfragment.xml,里面设计好导航的位置,并且还有一个加载界面的容器id为main_container

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:background="#FFFFFF">

android:id="@+id/main_container"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:layout_above="@+id/menu_line">

android:id="@+id/menu_line"

android:layout_width="fill_parent"

android:layout_height="1dp"

android:layout_above="@+id/menu_bottom"

android:background="@color/bg_Gray"

/>

android:id="@+id/menu_bottom"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:orientation="horizontal"

android:paddingTop="8dp">

android:id="@+id/nav_home"

android:layout_width="0dp"

android:layout_weight="1"

android:layout_height="wrap_content"

android:onClick="clickNav"

android:text="首页" />

android:id="@+id/nav_set"

android:layout_width="0dp"

android:layout_weight="1"

android:layout_height="wrap_content"

android:onClick="clickNav"

android:text="设置" />

可以啦,下面是效果图

a9606612deb0dedf10e35b3456898d2c.png

加一个过滤的动画,首先要定义进出的xml特效文件,把这些文件放言 入res/anim文件夹中

in_from_left.xml<?xml  version="1.0" encoding="utf-8"?>

android:interpolator="@android:anim/accelerate_interpolator">

android:fromXDelta="-100%p"

android:toXDelta="0%p"

android:duration="200" />

in_from_right.xml<?xml  version="1.0" encoding="utf-8"?>

android:interpolator="@android:anim/accelerate_interpolator">

android:fromXDelta="100%p"

android:toXDelta="0%p"

android:duration="200" />

out_from_left.xml<?xml  version="1.0" encoding="utf-8"?>

android:interpolator="@android:anim/accelerate_interpolator">

android:fromXDelta="0%p"

android:toXDelta="-100%p"

android:duration="200" />

out_from_right.xml<?xml  version="1.0" encoding="utf-8"?>

android:interpolator="@android:anim/accelerate_interpolator">

android:fromXDelta="0%p"

android:toXDelta="100%p"

android:duration="200" />

修改事件处理代码/**

* 单击导航调用此方法

*

* @param v

*/

public void clickNav(View v) {

int id = v.getId();

FragmentTransaction ft = fmg.beginTransaction();

switch (id) {

case R.id.nav_home:

ft.setCustomAnimations(R.anim.in_from_left,0, 0, R.anim.out_from_left);

if (!fmHome.isAdded()) {

ft.hide(fmSet).show(fmHome).add(R.id.main_container, fmHome).commit();

} else {

ft.hide(fmSet).show(fmHome).commit();

}

break;

case R.id.nav_set:

ft.setCustomAnimations(R.anim.in_from_right,0,0, R.anim.out_from_right);

if (!fmSet.isAdded()) {

ft.hide(fmHome).show(fmSet).add(R.id.main_container, fmSet).commit();

} else {

ft.hide(fmHome).show(fmSet).commit();

}

break;

}

}

3a259c13a039222c0f1f7ee841a5c884.png

ft.setCustomAnimations 关于这个函数的参数传递中间的两个直接传0 ,传其它值的话动画就会错乱(是个坑弄啦好久都没弄好)。关于原因请自行百度,谷歌查询