01-理解碎片Fragment
课程介绍
本课程需要大家有android基础
如果没有基础 无法往下学习的。
Fragment 翻译为碎片或者片段。
其实片段更正确。
它是一种嵌入在活动中的UI片段
能让程序更加合理和充分利用大屏幕空间
所以非常适合在平板上面使用。
它和活动很类似。同样包含布局 同样有自己的生命周期
可以把它理解为mini型的活动。
当我们要开发一个新闻应用的时候
如果是手机屏幕 我们可能设计成这样
一个列表活动 点击进去是新闻详情活动
但是如果是平板的 我们可能就不这样 否则会导致大片空白的 这样不好
更好的设计方案是 列表和内容详情分部在一个活动的两个碎片中
创建平板模拟器
为了更好测试我们的平板应用,我们要继续创建一个平板模拟器。

02-碎片的第一个例子
在一个活动中添加两个碎片 然后让两个碎片平分活动空间。
添加一个FragmentFirst新的项目
添加两个布局一个是作为左侧是碎片
newlist.xml
一个是右侧是碎片布局newdetail .xml
左侧碎片
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/buttondialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="中国和美国进行贸易战2018年" />
</LinearLayout>Code language: HTML, XML (xml)
右侧碎片
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0ddb97"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="新闻内容新闻内容"
/>
</LinearLayout>Code language: HTML, XML (xml)
添加碎片类
添加一个NewListFragment
从android.support.v4.app.Fragment中继承
然后重写onCreateView方法 让这个碎片使用newlist的xml
public class NewListFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.newlist,container,false);
return view;
}
}Code language: PHP (php)
同样的方式添加新闻详情碎片
NewDetailFragment 也是继承
android.support.v4.app.Fragment
public class NewDetailFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.newdetail,container,false);
return view;
}
}Code language: PHP (php)
主活动视图中调用碎片
使用android:name=”com.foxdevelop.“属性来设置使用哪个碎片
主视图中添加碎片视图 id不能少

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/newlist_fragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:name="com.foxdevelop.www.fragmentfirst.NewListFragment"
/>
<fragment
android:id="@+id/newdetail_fragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:name="com.foxdevelop.www.fragmentfirst.NewDetailFragment"
/>
</LinearLayout>Code language: HTML, XML (xml)
03-动态添加碎片
碎片真正强大的地方是它可以在程序运行的时候,动态地添加到活动当中。
根据具体活动动态地添加碎片,我们就可以在程序界面中定制更加多样化了。
比如我们的新闻 有些是图片新闻 有些是文字新闻 有些是视频新闻。这个时候可以更加不同的视频类型使用不同的碎片视图。
我们添加一个new_picture的视图。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/birdsee"
/>
</LinearLayout>Code language: HTML, XML (xml)
为了区别 它是显示一张图片的
添加图片的碎片类
public class NewImageFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.new_picture,container,false);
return view;
}
}Code language: PHP (php)
主视图中使用FrameLayout
我们这里使用一个帧布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/newlist_fragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:name="com.foxdevelop.www.fragmentfirst.NewListFragment"
/>
<FrameLayout
android:id="@+id/framelayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
></FrameLayout>
</LinearLayout>Code language: HTML, XML (xml)
左侧添加两个按钮
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/buttondialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="中国和美国进行贸易战2018年" />
<Button
android:id="@+id/buttonpicture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="图片新闻" />
</LinearLayout>Code language: HTML, XML (xml)
主活动中给按钮添加事件
通过给按钮添加事件 然后在事件里面 根据不同的按钮 动态添加不同的碎片
package com.foxdevelop.www.fragmentfirst;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//给两个按钮绑定事件
Button b1 = (Button)findViewById(R.id.buttonarticle);
b1.setOnClickListener(this);
Button b2 = (Button)findViewById(R.id.buttonpicture);
b1.setOnClickListener(this);
}
@Override
public void onClick(View view) {
//根据不同的按钮 设置不同的碎片
switch (view.getId())
{
case R.id.buttonarticle:
setFragement(new NewDetailFragment());
break;
case R.id.buttonpicture:
setFragement(new NewImageFragment());
break;
default:
break;
}
}
//该方法用来设置帧布局的碎片
public void setFragement(Fragment fragement) {
FragmentManager fragementManager = getSupportFragmentManager();
//开启事务
android.support.v4.app.FragmentTransaction fragmentTransaction = fragementManager.beginTransaction();
fragmentTransaction.replace(R.id.framelayout,fragement);// 设置帧布局使用传入的碎片
fragmentTransaction.commit();
}
}Code language: JavaScript (javascript)

04-碎片中使用返回栈
关于什么是返回栈 我们在基础课程中有说明。
我们现在 在上节课的例子中 我们点击back键的时候 发现应用是直接退出主活动的 然后退出程序 但是这样并不是我们想要的效果,我们希望按返回键的时候 是返回上一个碎片。
要先让碎片支持返回栈 其实很简单
只需要给事务添加到返回栈中就可以
//该方法用来设置帧布局的碎片
public void setFragement(Fragment fragement) {
FragmentManager fragementManager = getSupportFragmentManager();
//开启事务
android.support.v4.app.FragmentTransaction fragmentTransaction = fragementManager.beginTransaction();
fragmentTransaction.replace(R.id.framelayout,fragement);// 设置帧布局使用传入的碎片
fragmentTransaction.addToBackStack(null);//把事务增加到栈
fragmentTransaction.commit();
}Code language: JavaScript (javascript)
05-碎片和活动的通信
碎片都是嵌入在活动中。但是实际上他们的关系并没有那么密切。
我们的碎片和活动 其实是各自处在一个独立的类当中。
他们之间没有明显的方式进行通信。
为了方便通信。
FragmentManager提供一个类似findViewById的方式 转用于在布局中获取碎片的实例。
getFragmentManager android.support.v4.app.Fragment
需要转换为这个 这里书本没说到
如果你导入的是android.support.v4.app.Fragment.包(即v4包)
import android.support.v4.app.Fragment;
那么在获得FragmentManager时,使用的应该是
FragmentManager fm = getSupportFragmentManager();
对应的fragment也要导入对应的包!
//在活动的oncreate方法中获取碎片实例
NewListFragment newListFragment = (NewListFragment)getSupportFragmentManager().findFragmentById(R.id.newlist_fragment);
Toast.makeText(this, newListFragment.getId()+"xxxx",Toast.LENGTH_LONG).show();Code language: JavaScript (javascript)

碎片中获取活动
//碎片中获取活动
MainActivity mainActivity = (MainActivity) getActivity();
Toast.makeText(getContext(), mainActivity.getTitle(),Toast.LENGTH_LONG).show();Code language: JavaScript (javascript)
可以调用 getActivity方法

06-碎片的生命周期
碎片的生命周期根活动基本一样。
碎片也有四种状态。
运行 暂停 停止 销毁
1 运行状态:碎片是可见的。并且所在的活动正处于运行状态,该碎片也是处于活动状态
2 暂停状态
当另一个未占满屏幕的活动呗添加到栈顶。与他管理的可见碎片就会进入到暂停状态。
3 停止状态。
当一个活动处于停止状态,它相关的碎片的页会进入停止状态。或者通过FragmentTransaction的remove或者replace方法将活动从碎片中移除。如果在实务提交前调用addToBackStack方法 则也会进入停止状态。
总之如果进入了停止状态的碎片 对于用于是不可见的 并且随时可能被系统回收。
4 销毁状态。
碎片总是依附于活动,因此活动呗销毁,相关的碎片也会进入到销毁状态。
或者通过FragmentTransaction的remove或者replace方法将碎片从活动中移除。如果在实务提交前没有调用addToBackStack方法 则也会进入销毁状态
跟活动一样,Fragment也提供了一系列的回调方法。以覆盖碎片的生命周期的每个环节。活动中有的 碎片中几乎都有。
同时 碎片也提供了一些附加的回调方法。