8 Fragment基础概述
8-1 Fragment的设计哲学
Android在3.0中引入了Fragments的概念,主要目的是用在大屏幕设备上,例如平板电脑上,支持跟家动态和灵活的UI设计,平板电脑的屏幕要比在手机的大得多,有更多的控件来放更多的ui组件,并且这些组件之间会产生更多的交互。
Fragment在你的应用中应当是一个模块化和可重用的组件,因为Fragment定义了它自己的布局,以及通过使用它自己的生命周期回调方法定义了它自己的行为,你可以将Fragment包含到多个Activity中
8-2 静态加载Fragment(一)
Layout布局文件转换为View对象
LayoutInflater inflater;
inflater.inflate(resource需要加载的布局文件,root加载layout的父ViewGroup,attachTORoot=false不返回父ViewGroup)
//layout布局文件转换成View对象
/**
* resource:Fragment需要加载的布局文件
* root:加载layout的父ViewGroup
* attactToRoot:false,不返回父ViewGroup
*/
View view = inflater.inflate(R.layout.fragment, container, false);
Fragment知识概要
1.Fragment可以作为Activity界面的一部分组成出现
动态加载中,是我管理者FragmentManager的事务对象FragmentTransaction中的 add(ViewId,fragment)将fragment作为一个组件添加到布局文件ViewId中
2.可以在一个Activity中同事出现多个Fragment,并且一个Fragment也可以在多个Activity中使用
3.在Activity运行过程中,可以添加,移除和替换Fragment
通过事务管理者
4.Fragment可以相应自己的输入事件,并且有司机的生命周期,它们的生命周期会受宿主Activity生命周期的影响
OnCreateView()方法
Fragment第一次调绘制它的用户界面的时候,系统会调用此方法,为了绘制Fragement的UI,此方法必须返回一个View,如果不显示UI,返回null即可。
Fragment加载方式
静态加载 动态加载
静态加载
在Activity的layout文件中声明Fragment,需要特别注意的是<Fragment>中的android:name属性指定了layout中实例化的Fragment类
标识Fragment的方法:
android:id属性提供一个唯一ID
android:tag属性提供一个唯一字符串
8-3 静态加载Fragment(二)
MainActivity.java
package com.example.android2_fragment; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; public class MainActivity extends Activity implements OnCheckedChangeListener { private RadioGroup group; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); group = (RadioGroup) findViewById(R.id.radiogroup); group.setOnCheckedChangeListener(this); } @Override public void onCheckedChanged(RadioGroup group, int checkedId) { // TODO Auto-generated method stub switch (checkedId) { case R.id.first: { Intent intent = new Intent(this, MainActivity2.class); startActivity(intent);[跳转] break; } case R.id.second: { break; } case R.id.thrid: { break; } case R.id.fourth: { break; } } } }
Main.xml
<?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" > <LinearLayout android:id="@+id/frame" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > </LinearLayout> <RadioGroup android:id="@+id/radiogroup" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:gravity="center_horizontal" android:orientation="horizontal" > <RadioButton android:id="@+id/first" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/radio_pressed" android:button="@null" android:drawableTop="@drawable/ic_launcher" android:gravity="center_horizontal" android:text="静态加载" /> <RadioButton android:id="@+id/second" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/radio_pressed" android:button="@null" android:drawableTop="@drawable/ic_launcher" android:gravity="center_horizontal" android:text="动态加载" /> <RadioButton android:id="@+id/thrid" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/radio_pressed" android:button="@null" android:drawableTop="@drawable/ic_launcher" android:gravity="center_horizontal" android:text="生命周期" /> <RadioButton android:id="@+id/fourth" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/radio_pressed" android:button="@null" android:drawableTop="@drawable/ic_launcher" android:gravity="center_horizontal" android:text="传值通信" /> </RadioGroup> </RelativeLayout>
MainActivity2.java
package com.example.android2_fragment; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.RadioGroup; import android.widget.TextView; import android.widget.RadioGroup.OnCheckedChangeListener; public class MainActivity2 extends Activity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main2); Button button = (Button) findViewById(R.id.button); textView = (TextView) findViewById(R.id.text); button.setText("改变"); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub textView.setText("TextView改变了"); } }); } }
Main2.xml
<?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" > <fragment android:id="@+id/fragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:name="com.example.android2_fragment.MyFragment" /> </LinearLayout>
MyFragment.java
package com.example.android2_fragment; import android.R.layout; import android.os.Bundle; import android.app.Activity; import android.app.Fragment; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.TextView; public class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub // layout布局文件转化为View对象 /* * inflate(resource, root, attachToRoot); * resource:Fragment需要加载的布局文件 * root:加载layout的父ViewGroup * attactToRoot:false,不返回父ViewGroup */ View view=inflater.inflate(R.layout.fragment, container, false); TextView textView=(TextView)view.findViewById(R.id.text); textView.setText("静态加载Fragment"); return view; } }
fragment.xml
<?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" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:text="改变" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/button" /> </LinearLayout>
这节课的思路是现有的一个MainActivity(主界面),它的布局文件是Main.xml(RadioGroup,RadioButton)之后老师创建了一个MainActivity2(静态加载Fragment的界面),它对应的布局文件是Main2.xml(这个布局里添加了一个Fragment标签->静态加载),并在这个xml文件中为Fragment标签定义了:name="MyFragment"属性,这个属性对应了Fragment标签对应的包和类-->这个MyFragment.java(继承Fragment),并重写onCreatView(),这个方法返回一个view对象。并为这个类声明创建了一个布局文件(fragment.xml)。并添加了一个TextView和Button,通过inflate.infalte()将布局文件添加在到这个MyFragment中。-->回到MainActivity2通过setContextView()将main2.xml加载。
最后回到MainActivity.java为第一个RadioButton添加点击事件(通过intent意图,跳转到MainActivity2)
老师在MainActivity2中直接通过findViewById();将fragment.xml文件中的Button加载,这是因为通过层层加载,这个button已经在于main2.xml中了。
最后在清单文件中添加MainActivity2,并在main2.xml中为Fragment标签添加一个id或tag
当一个布局文件通过静态加载的方式将fragment加载到Activity2的文件中来,对于fragment的布局文件对于Activity2来说也是共享它里面的UI控件.
8-4 动态加载Fragment
动态加载:
写代码将Fragment添加到一个Activity layout中
add():添加一个Fragment(指定要添加的Fragment和插入的View
与此类似的还有remove()、replace()
处理Fragment事务:
根据用户的交互情况,对Fragment进行添加、移除、替换,以及其他动作,提交给Activity的每一套变化被称为一个事务。
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
每一个事务都是同事执行一套变化,可以在一个事务中设置你所有想执行的变化,包括add()、remove()、replace(),然后提交给Activity,必须调用commit()方法
如果允许用户通过按下返回键返回到前一个Fragment状态,调用commit()之前可以加入addToBackStack()方法
MainActivity.java
package com.example.android2_fragment; import android.os.Bundle; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.Intent; import android.view.Menu; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; public class MainActivity extends Activity implements OnCheckedChangeListener { private RadioGroup group; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); group = (RadioGroup) findViewById(R.id.radiogroup); group.setOnCheckedChangeListener(this); } @Override public void onCheckedChanged(RadioGroup group, int checkedId) { // TODO Auto-generated method stub switch (checkedId) { case R.id.first: { Intent intent = new Intent(this, MainActivity2.class); startActivity(intent); break; } case R.id.second: { MyFragment2 myFragment2 = new MyFragment2();//new出一个fragment对象 FragmentManager fragmentManager = getFragmentManager();//得到fragment管理者 FragmentTransaction beginTransaction = fragmentManager.beginTransaction();//开始一个事物 beginTransaction.add(R.id.frame, myFragment2);//fragment事物添加一个fragment, //R.id.fragment为fragment显示的位置id,fragment2为需要添加的fragment; beginTransaction.addToBackStack(null); //增加回退效果,手机物理返回按键可以回退到上一个界面而不是直接退出 beginTransaction.commit();//最后提交 break; } case R.id.thrid: { break; } case R.id.fourth: { break; } } } }
MyFragment2.java
package com.example.android2_fragment; import android.os.Bundle; import android.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class MyFragment2 extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub // layout布局文件转化为View对象 /* * inflate(resource, root, attachToRoot); * resource:Fragment需要加载的布局文件 * root:加载layout的父ViewGroup * attactToRoot:false,不返回父ViewGroup */ View view=inflater.inflate(R.layout.fragment, container, false); TextView textView=(TextView)view.findViewById(R.id.GB_text); textView.setText("动态加载Fragment"); return view; } }