碎片是什么
碎片 (Fragment) 是一种可以嵌入在 Activity 当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用的非常广泛。虽然碎片对你来说应该是个全新的概念,但我相信你学习起来应该毫不费力,因为它和 Activity 实在是太像了,同样都能包含布局,同样都有自己的生命周期。你甚至可以将碎片理解成一个迷你型的 Activity,虽然这个迷你型的 Activity 有可能和普通的 Activity 是一样大的。
那么究竟要如何使用碎片才能充分地利用平板屏幕的空间呢?想象我们正在开发一个新闻英语,其中一个界面使用 ListView 展示了一组新闻的标题,当点击了其中一个标题,就打开另一个界面显示新闻的详细内容。如果是在手机中设计,我们可以将新闻标题列表放在一个 Activity 中,将新闻的详细内容放在另一个 Activity 中。
碎片的使用方式
1、新建一个FragmentTest 项目
在一个活动当中添加两个碎片,并让这两个碎片平分活动空间。
新建一个左侧碎片布局left_fragment.xml,代码如下所示:
[html]view plaincopy
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Button"
/>
这个布局非常简单,只放置了一个按钮,并让它水平居中显示。
2、新建右侧碎片布局right_fragment.xml
[html]view plaincopy
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ff00"
android:orientation="vertical">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="This is right fragment"
/>
我们将这个布局的背景色设置成绿色,并放置了一个TextView 用于显示一段文本。
3、新建一个LeftFragment 类,继承自Fragment
注意,这里可能会有两个不同包下的Fragment 供你选择,
建议使用Android.app.Fragment,因为我们的程序是面向Android 4.0以上系统的,
另一个包下的Fragment 主要是用于兼容低版本的Android 系统。
LeftFragment的代码如下所示:
[java]view plaincopy
publicclassLeftFragmentextendsFragment
{
@Override
publicView onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.left_fragment, container,false);
returnview;
}
}
这里仅仅是重写了Fragment 的onCreateView()方法,
然后在这个方法中通过LayoutInflater的inflate()方法将刚才定义的left_fragment 布局动态加载进来,
整个方法简单明了。
4、用同样的方法再新建一个RightFragment
[java]view plaincopy
publicclassRightFragmentextendsFragment
{
@Override
publicView onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.right_fragment, container,false);
returnview;
}
}
基本上代码都是相同的,相信已经没有必要再做什么解释了。
5、修改activity_main.xml中的代码
[java]view plaincopy
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/left_fragment"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
android:id="@+id/right_fragment"
android:name="com.example.fragmenttest.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
可以看到,我们使用了标签在布局中添加碎片,其中指定的大多数属性都是熟悉的,
只不过这里还需要通过android:name 属性来显式指明要添加的碎片类名,注意一定要将类的包名也加上。
这样最简单的碎片示例就已经写好了。
6、运行程序
动态添加碎片
在上一节当中我们已经学会了在布局文件中添加碎片的方法,
不过碎片真正的强大之处在于,它可以在程序运行时动态地添加到活动当中。
根据具体情况来动态地添加碎片,就可以将程序界面定制得更加多样化。
我们还是在上一节代码的基础上继续完善:
1、新建another_right_fragment.xml
[html]view plaincopy
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffff00"
android:orientation="vertical">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="This is another right fragment"
/>
这个布局文件的代码和right_fragment.xml 中的代码基本相同,
只是将背景色改成了黄色,并改动了显示的文字。
2、新建AnotherRightFragment 作为另一个右侧碎片
[java]view plaincopy
publicclassAnotherRightFragmentextendsFragment
{
@Override
publicView onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.another_right_fragment,container,false);
returnview;
}
}
代码同样非常简单,在onCreateView()方法中加载了刚刚创建的another_right_fragment布局。
这样我们就准备好了另一个碎片。
3、将碎片动态地添加到活动当中
修改activity_main.xml,代码如下所示:
[html]view plaincopy
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/left_fragment"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
android:id="@+id/right_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
android:id="@+id/right_fragment"
android:name="com.example.fragmenttest.RightFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
可以看到,现在将右侧碎片放在了一个FrameLayout 中
在上一章中我们学过,这是Android中最简单的一种布局,它没有任何的定位方式,所有的控件都会摆放在布局的左上角。
由于这里仅需要在布局里放入一个碎片,因此非常适合使用FrameLayout。
4、在代码中替换FrameLayout 里的内容从而实现动态添加碎片的功能。
修改MainActivity 中的代码,如下所示:
[html]view plaincopy
public class MainActivity extends Activity implements OnClickListener
{
@Overrideprotected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Buttonbutton= (Button) findViewById(R.id.button);
button.setOnClickListener(this);
}
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.button:
AnotherRightFragmentfragment=newAnotherRightFragment();
FragmentManagerfragmentManager=getFragmentManager();
FragmentTransactiontransaction=fragmentManager.
beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.commit();
break;
default:
break;
}
}
}
首先我们给左侧碎片中的按钮注册了一个点击事件,
然后将动态添加碎片的逻辑都放在了点击事件里进行。
结合代码可以看出,动态添加碎片主要分为5 步。
1. 创建待添加的碎片实例。
2. 获取到FragmentManager,在活动中可以直接调用getFragmentManager()方法得到。
3. 开启一个事务,通过调用beginTransaction()方法开启。
4. 向容器内加入碎片,一般使用replace()方法实现,需要传入容器的id 和待添加的碎片实例。
5. 提交事务,调用commit()方法来完成。
这样就完成了在活动中动态添加碎片的功能,重新运行程序,
可以看到和之前相同的界面
在碎片中模拟返回栈
FragmentTransaction 中提供了一个addToBackStack()方法,
可以用于将一个事务添加到返回栈中,修改MainActivity 中的代码,如下所示:
publicclassMainActivityextendsActivityimplementsOnClickListener
{
……
@Override
publicvoidonClick(View v)
{
switch(v.getId())
{
caseR.id.button:
AnotherRightFragment fragment =newAnotherRightFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.
beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.addToBackStack(null);
transaction.commit();
break;
default:
break;
}
}
}
这里我们在事务提交之前调用了FragmentTransaction 的addToBackStack()方法,
它可以接收一个名字用于描述返回栈的状态,一般传入null 即可。
现在重新运行程序,并点击按钮将AnotherRightFragment 添加到活动中,然后按下Back 键,
你会发现程序并没有退出,而是回到了RightFragment 界面,再次按下Back 键程序才会退出。
为了方便碎片和活动之间进行通信,FragmentManager提供了一个类似于findViewById()的方法,如下所示:
//在活动中调用碎片的方法:
RightFragment rightFragment = (RightFragment)getFragmentManager().
findFragmentById(R.id.right_fragment);//在碎片中调用活动:
MainActivity activity = (MainActivity)getActivity();//碎片通信其他碎片:(首先获取与当前碎片关联的活动,再通过这个活动获取另一个碎片的实例
LeftFragment leftFragment = (LeftFragment)activity.getFragmentManager().
findFragmentById(R.id.left_fragment);
网友评论