一. 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