一. Fragment的简介
Fragment在Android 3.0( API 11)引入,是为了支持在大屏上显示更加动态、灵活的UI,比如在平板和电视上。Fragment可以看作是嵌套的Activity,类似ActivityGroup,但是开销肯定没有ActivityGroup那么大,每一个Fragment管理着一个View,Fragment彼此之间相互独立,有自己的生命周期,这个生命周期是在Activity生命周期中的。Fragment可以用来解决屏幕适配和动态创建View的问题。
二.Fragment的生命周期
Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。
可以看到Fragment比Activity多了几个额外的生命周期回调方法:
onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater,ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用
注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现!
三.Fragment常用的API
Fragment常用的三个类:
android.app.Fragment主要用于定义Fragment
android.app.FragmentManager主要用于在Activity中操作Fragment
(1)获取FragmentManage的方式:getFragmentManager()// v4中,getSupportFragmentManager
android.app.FragmentTransaction每一个事务都是同时要执行的一套变化.可以在一个给定的事务中设置你想执行的所有变化,
FragmentTransaction的主要的操作方法
FragmentTransactiontransaction = fm.benginTransatcion();//开启一个事务
transaction.add()
往Activity中添加一个Fragment
transaction.remove()
从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。
transaction.replace()
使用另一个Fragment替换当前的,其实就是remove()然后add()
transaction.hide()
隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
transaction.show()
显示之前隐藏的Fragment
detach()
会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。
attach()
重建view视图,附加到UI上并显示。
transatcion.commit()//提交一个事务
注意:常用Fragment的哥们,可能会经常遇到这样Activity状态不一致:State loss这样的错误。主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。还有就是在一个事务开启到提交可以进行多个的添加、移除、替换等操作。
四.Fragment的使用
静态使用Fragment
1.继承Fragment,重写onCreateView决定Fragemnt的布局(加载Fragment的布局)
2.在Activity中声明此Fragment,就当和普通的View一样
( 注意:要给Fragment设置ID,要不无法初始化报错)
先看看布局:
、
静态使用Fragment的下载地址:http://download.csdn.net/detail/two_water/9279253
动态使用Fragment
1.效果图:
.
代码上主界面的代码,其他的想看就下载来看看:
<span style="font-size:12px;"><pre name="code" class="java">package com.liangdianshui.fragment2;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
public class MainActivity extends Activity implements OnClickListener {
private Button mBtNews;
private Button mBtEntertainment;
private Button mBtSports;
private Button mBtInternational;
private FrameLayout mContent;
private MyFragmentNews frNews;
private MyFragmentEntertainment myFragmentEntertainment;
private MyFragmentInternational myFragmentInternational;
private MyFragmentSports myFragmentSports;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
mContent = (FrameLayout) findViewById(R.id.fm_content);
mBtNews = (Button) findViewById(R.id.bt_news);
mBtEntertainment = (Button) findViewById(R.id.bt_entertainment);
mBtSports = (Button) findViewById(R.id.bt_sports);
mBtInternational = (Button) findViewById(R.id.bt_International);
mBtNews.setOnClickListener(this);
mBtEntertainment.setOnClickListener(this);
mBtSports.setOnClickListener(this);
mBtInternational.setOnClickListener(this);
setDefaultContent();
}
private void setDefaultContent() {
FragmentManager fm = getFragmentManager();
FragmentTransaction beginTransaction = fm.beginTransaction();
frNews = new MyFragmentNews();
beginTransaction.replace(R.id.fm_content, frNews);
beginTransaction.commit();
}
public void onClick(View view) {
FragmentManager fm = getFragmentManager();
FragmentTransaction beginTransaction = fm.beginTransaction();
switch (view.getId()) {
case R.id.bt_news:
if (frNews == null) {
frNews = new MyFragmentNews();
}
beginTransaction.replace(R.id.fm_content, frNews);
beginTransaction.commit();
break;
case R.id.bt_entertainment:
if (myFragmentEntertainment == null) {
myFragmentEntertainment = new MyFragmentEntertainment();
}
beginTransaction.replace(R.id.fm_content, myFragmentEntertainment);
beginTransaction.commit();
break;
case R.id.bt_sports:
if (myFragmentSports == null) {
myFragmentSports = new MyFragmentSports();
}
beginTransaction.replace(R.id.fm_content, myFragmentSports);
beginTransaction.commit();
break;
case R.id.bt_International:
if (myFragmentInternational == null) {
myFragmentInternational = new MyFragmentInternational();
}
beginTransaction.replace(R.id.fm_content, myFragmentInternational);
beginTransaction.commit();
break;
default:
break;
}
}
}
</span>
动态使用Fragment的Demo:http://download.csdn.net/detail/two_water/9279255
五.Fragment和Activity之间的通信
效果图和上面的都是一样的!只是考虑Fragment的重复使用,所以必须降低Fragment与Activity的耦合!虽然Fragment和Activity可以通过getActivity与findFragmentByTag或者findFragmentById,进行任何操作,甚至在Fragment里面操作另外的Fragment,但是没有特殊理由是不提倡的。Activity担任的是Fragment间类似总线一样的角色,应当由它决定Fragment如何操作。
因为效果图和上面的动态使用Fragment的效果图差不多!所以不上图了!
贴几个关键的代码:
package com.liangdianshui.fragment2;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
public class MyFragmentSports extends Fragment implements OnClickListener {
private Button bt_enter_news;
public interface enterNewsListener {
void enterNewsOnClick();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater
.inflate(R.layout.fragment_sports, container, false);
bt_enter_news = (Button) view.findViewById(R.id.bt_enter_news);
bt_enter_news.setOnClickListener(this);
return view;
}
@Override
public void onClick(View view) {
if (getActivity() instanceof enterNewsListener) {
((enterNewsListener) getActivity()).enterNewsOnClick();
}
}
}
package com.liangdianshui.fragment2;
import com.liangdianshui.fragment2.MyFragmentSports.enterNewsListener;
import com.liangdianshui.fragment2.MyFragmentTitle.titleBtListener;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
public class MainActivity extends Activity implements titleBtListener,
enterNewsListener {
private FrameLayout mContent;
private MyFragmentNews frNews;
private MyFragmentEntertainment myFragmentEntertainment;
private MyFragmentInternational myFragmentInternational;
private MyFragmentSports myFragmentSports;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setDefaultContent();
}
private void setDefaultContent() {
FragmentManager fm = getFragmentManager();
FragmentTransaction beginTransaction = fm.beginTransaction();
frNews = new MyFragmentNews();
beginTransaction.replace(R.id.fm_content, frNews);
beginTransaction.commit();
}
@Override
public void titleOnClick(View view) {
FragmentManager fm = getFragmentManager();
FragmentTransaction beginTransaction = fm.beginTransaction();
switch (view.getId()) {
case R.id.bt_news:
if (frNews == null) {
frNews = new MyFragmentNews();
}
beginTransaction.replace(R.id.fm_content, frNews);
beginTransaction.commit();
break;
case R.id.bt_entertainment:
if (myFragmentEntertainment == null) {
myFragmentEntertainment = new MyFragmentEntertainment();
}
beginTransaction.replace(R.id.fm_content, myFragmentEntertainment);
beginTransaction.commit();
break;
case R.id.bt_sports:
if (myFragmentSports == null) {
myFragmentSports = new MyFragmentSports();
}
beginTransaction.replace(R.id.fm_content, myFragmentSports);
beginTransaction.commit();
break;
case R.id.bt_International:
if (myFragmentInternational == null) {
myFragmentInternational = new MyFragmentInternational();
}
beginTransaction.replace(R.id.fm_content, myFragmentInternational);
beginTransaction.commit();
break;
default:
break;
}
}
@Override
public void enterNewsOnClick() {
if (frNews == null) {
frNews = new MyFragmentNews();
}
FragmentManager fm = getFragmentManager();
FragmentTransaction beginTransaction = fm.beginTransaction();
beginTransaction.replace(R.id.fm_content, frNews);
beginTransaction.commit();
}
}
package com.liangdianshui.fragment2;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
public class MyFragmentTitle extends Fragment implements OnClickListener {
private Button mBtNews;
private Button mBtEntertainment;
private Button mBtSports;
private Button mBtInternational;
public interface titleBtListener {
void titleOnClick(View view);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_title, container, false);
init(view);
return view;
}
private void init(View view) {
mBtNews = (Button) view.findViewById(R.id.bt_news);
mBtEntertainment = (Button) view.findViewById(R.id.bt_entertainment);
mBtSports = (Button) view.findViewById(R.id.bt_sports);
mBtInternational = (Button) view.findViewById(R.id.bt_International);
mBtNews.setOnClickListener(this);
mBtEntertainment.setOnClickListener(this);
mBtSports.setOnClickListener(this);
mBtInternational.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (getActivity() instanceof titleBtListener) {
((titleBtListener) getActivity()).titleOnClick(view);
}
}
}
其中点击事件中的if(getActivity() instanceof titleBtListener)判断当前的activity是否实现了该接口~
Fragment和Activity通信Demo: http://download.csdn.net/detail/two_water/9279261