本帖最后由 就业部_安卓组 于 2016-12-6 16:05 编辑
Fragment 的使用 Fragment 的使用分为两种,分别是静态和动态,静态的使用是最简单的一种方式,就是将 Fragment 当做普通的一种控件,直接写在 Activity 的布局里面就可以了。而动态的使用相对而言比较复杂,下面会一一介绍。
静态的使用
静态的使用 Fragment ,包括两个步骤: 1.继承 Fragment,重写 onCreateView 并填充一个 view 用于显示 Fragment 的布局 2.在 Activity 中声明此 Fragment 多说无益,直接写代码展示,在此我要实现这样的界面,上面是一个内容布局,下面是一个底部布局。如果用 Activity 来写,无非就是两个 TextView 就可以了,上面一个下面一个。但是我要用 Fragment 来实现就不一样了,代码如下: 首先我先定义上面的内容布局文件 fragment_content.xml: [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/tv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#333333"
android:gravity="center"
android:text="我是上面的内容 Fragment"
android:textColor="#ffffff"
android:textSize="20sp" />
</LinearLayout>
然后快速的书写内容布局的 Fragment
[Java] 纯文本查看 复制代码 package com.mesmerize.helloworld;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by mesmerize on 2016/11/17.
* 内容 Fragment
*/
public class ContentFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_content, null);
TextView tv_content = (TextView) view.findViewById(R.id.tv_content);
tv_content.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(), "你点击了上面的内容 Fragment ", Toast.LENGTH_SHORT).show();
}
});
return view;
}
} 这段代码就是在做第一步,我创建了一个 ContentFragment 并继承自 Fragment,重写 onCreateView 方法,然后填充 fragment_content.xml 这个布局文件作为该 Fragment 的 view。 同时我查找出了当前布局文件里面的那个 TextView 控件并给该控件设置了一个点击事件,点击这个 TextView 会弹出来一个 Toast。 接下来我们按照上述的代码形式快速的写出底层的 Fragment。
fragment_bottom.xml [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/tv_bottom"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:text="我是底部的 Fragment"
android:textSize="20sp" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/ic_launcher" />
</LinearLayout>
这个 xml 文件,上面是一个 TextView 文本,下面是一个 ImageView 显示一张小机器人的图片。
该 xml 布局文件对应的 Fragment 代码如下: BottomFragment [Java] 纯文本查看 复制代码 package com.mesmerize.helloworld;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by mesmerize on 2016/11/17.
* 底部的 Fragment
*/
public class BottomFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_bottom, null);
TextView tv_content = (TextView) view.findViewById(R.id.tv_bottom);
tv_content.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(), "你点击了底部的内容 Fragment ", Toast.LENGTH_SHORT).show();
}
});
return view;
}
}
跟内容的 ContentFragment 代码差不多,只是填充的布局文件不一样,弹出的 Toast 内容不一样。 以上做的就是我们所说的第一步,接下来做第二步,在 Activity 布局文件中声明。首先我们书写 Activity 的 xml 布局: activity_main.xml [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_content"
android:name="com.mesmerize.helloworld.ContentFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></fragment>
<fragment
android:id="@+id/fragment_bottom"
android:name="com.mesmerize.helloworld.BottomFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></fragment>
</LinearLayout>
布局很简单,其中用到了 weight 权重这个属性,它的意思就是所占的比例,比如在该布局里面,我写了两个weight,那这两个 weight 加一起就是 2 ,这是总的数。而每一个 fragment 都占了 1,也就是占总数的 1/2 。因此它们两个 fragment 平均分配了这个手机屏幕的大小,也就是上下各占一半。 MainActivity [Java] 纯文本查看 复制代码 package com.mesmerize.helloworld;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
至此,就大功告成了,速度运行一下,看看结果。
尝试一下点击上面的 “我是上面的内容 Fragment”这句话,看看会不会弹出来一句话。
没有问题。那再点一下下面的试试。
也没有问题! 可以看到,我们的弹出 Toast 以及查找控件等控件的事件处理的代码都由各自的 Fragment 去处理了,而我们的 Activity 什么都不用写,仅仅显示一下就行了。这就是我们常说的“高内聚低耦合”,赶紧去试试吧!
动态的使用
通过上面的演示相信现在你已经学会了静态使用的方式了,但是这仅仅只是 Fragment 最简单的功能而已。接下来我将介绍如何动态的添加、更新以及删除 Fragment。 平时我们所使用 app 比如 QQ、微信、微博、淘宝、京东,都是类似这样的结构:
也就是下面几个按钮,然后中间是内容区域,点击下面的按钮,可以动态替换上面的内容区域,而今天我们就来写一个类似这种架构的小小的 Demo
效果图如下:
很简单的需求,就是下面几个文字,上面是内容区域,点击下面的文字,动态替换上面的文本区域里面的文字内容,这怎么来做呢? 其实,这一块就要涉及到 Fragment 的动态替换了,话不多说了,直接上代码。 首先是 activity_main.xml 文件,根据效果图,我们分析,上面的内容区域可以用一个 FrameLayout 来填充,待会可以动态的用不同的 Fragment 来替换即可,而下面用简单的四个 TextView 就行了。我们快速的编写代码: [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">
<FrameLayout
android:id="@+id/fl_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="40dp"></FrameLayout>
<LinearLayout
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<TextView
android:gravity="center"
android:id="@+id/tv_chat"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="聊天"
android:textColor="#288CFB"
android:textSize="16sp" />
<TextView
android:gravity="center"
android:id="@+id/tv_address"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="通讯录"
android:textColor="#288CFB"
android:textSize="16sp" />
<TextView
android:gravity="center"
android:id="@+id/tv_find"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="发现"
android:textColor="#288CFB"
android:textSize="16sp" />
<TextView
android:gravity="center"
android:id="@+id/tv_me"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="我"
android:textColor="#288CFB"
android:textSize="16sp" />
</LinearLayout>
</RelativeLayout>
中间一个 FrameLayout ,下面四个 TextView , 显示效果如下:
可以看到下面有四个选项,我们的需求是每次点击一个选项的时候将上面的 FrameLayout 内容更换,而在这里,我们的 FrameLayout 由 Fragment 来填充,因此,我们首先要创建好四个 Fragment ,待会点击的时候动态的去替换不同的 Fragment。 所以在这里,我们快速创建四个 Fragment 以及他们的布局文件。
首先是聊天 (ChatFragment): [Java] 纯文本查看 复制代码 package com.mesmerize.helloworld;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* 聊天 Fragment
*/
public class ChatFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chat, null);
return view;
}
}
fragment_chat.xml 如下: [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:background="#ff0000"
android:orientation="vertical">
<TextView
android:text="我是聊天Fragment"
android:textColor="#ffffff"
android:textSize="20sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
显示效果如下:
可以看到是一个红色背景的文本内容。这是聊天的 Fragment。 接下来是通讯录(AddressFragment)的代码: [Java] 纯文本查看 复制代码 package com.mesmerize.helloworld;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* 通讯录 Fragment
*/
public class AddressFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_address, null);
return view;
}
} fragment_address.xml 如下: [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:background="#00f0f0"
android:orientation="vertical">
<TextView
android:text="我是通讯录Fragment"
android:textColor="#ffffff"
android:textSize="20sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
效果如下:
接下来同样的方式创建另外两个 Fragment,发现(FindFragment)以及我(MeFragment): FindFragment: [Java] 纯文本查看 复制代码 package com.mesmerize.helloworld;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* 发现 Fragment
*/
public class FindFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_find, null);
return view;
}
}
fragment_find.xml [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:background="#ff00ff"
android:orientation="vertical">
<TextView
android:text="我是发现Fragment"
android:textColor="#ffffff"
android:textSize="20sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
效果:
MeFragment: [Java] 纯文本查看 复制代码 package com.mesmerize.helloworld;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* 我 Fragment
*/
public class MeFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_me, null);
return view;
}
}
fragment_me.xml [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:background="#0f0f0f"
android:orientation="vertical">
<TextView
android:text="我是我Fragment"
android:textColor="#ffffff"
android:textSize="20sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout> 效果:
到这里,四个 Fragment 已经创建完成,那接下来开始在 MainActivity 里面填充,并且处理一些业务逻辑,比如点击下面的选项,动态切换上面的 FrameLayout 内容。注释我都加在代码里面,代码如下: [Java] 纯文本查看 复制代码 package com.mesmerize.helloworld;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView tv_chat;
private TextView tv_address;
private TextView tv_find;
private TextView tv_me;
private ChatFragment mChatFragment;
private AddressFragment mAddressFragment;
private FindFragment mFindFragment;
private MeFragment mMeFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initListener();
initDefaultFragment();
}
/**
* 初始化 View 控件
*/
private void initView(){
tv_chat = (TextView) findViewById(R.id.tv_chat);
tv_address = (TextView) findViewById(R.id.tv_address);
tv_find = (TextView) findViewById(R.id.tv_find);
tv_me = (TextView) findViewById(R.id.tv_me);
}
/**
* 初始化 事件监听事件
*/
private void initListener(){
tv_chat.setOnClickListener(this);
tv_address.setOnClickListener(this);
tv_find.setOnClickListener(this);
tv_me.setOnClickListener(this);
}
/**
* 初始化 默认显示的 Fragment
*/
private void initDefaultFragment(){
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.fl_content, new ChatFragment());
transaction.commit();
}
/**
* 点击事件
*/
@Override
public void onClick(View v) {
FragmentManager fm = getFragmentManager();
// 开启事务
FragmentTransaction transaction = fm.beginTransaction();
switch (v.getId()){
case R.id.tv_chat:
if (mChatFragment == null) {
mChatFragment = new ChatFragment();
}
// 替换
transaction.replace(R.id.fl_content, mChatFragment);
break;
case R.id.tv_address:
if (mAddressFragment == null) {
mAddressFragment = new AddressFragment();
}
// 替换
transaction.replace(R.id.fl_content, mAddressFragment);
break;
case R.id.tv_find:
if (mFindFragment == null) {
mFindFragment = new FindFragment();
}
// 替换
transaction.replace(R.id.fl_content, mFindFragment);
break;
case R.id.tv_me:
if (mMeFragment == null) {
mMeFragment = new MeFragment();
}
// 替换
transaction.replace(R.id.fl_content, mMeFragment);
break;
}
// 提交事务
transaction.commit();
}
} 在 onCreate 里面调用了 initView、initListener、initDefaultFragment,分别是初始化 View 控件、设置点击事件以及初始化默认显示的 Fragment,在这里我们初始化的 Fragment 是聊天 Fragment,即 ChatFragment。可以看到我们需要开启一个事务,通过 FragmentManager 对象得到,然后调用 replace() 方法进行替换,参数1的意思为被替换的文本内容,参数2是用谁来替换,最后调用 commit() 方法提交,到此,一个动态替换 Fragment 的逻辑完成了。 然后我们在 onClick 点击事件里面进行业务逻辑处理,根据点击的控件 id 进行 switch 判断,并动态替换每一个 Fragment 。 以上就是一个简单的逻辑处理。 在这里需要注意 FragmentManager,如果是使用 Android 3.0 以下的版本,则需要引入 v4 的包,然后 Activity 继承 FragmentActivity,并且要通过 getSupportFragmentManager 的形式来获得 FragmentManager。这是版本向下兼容。
Fragment 常用 API
getFragmentManager() :获取 FragmentManager ,但在 v4 中,需要用 getSupportFragmentManager fm.beginTransaction() :开启一个事务,可以通过事务做很多操作 transaction.add() :在 Activity 中添加一个 Fragment transaction.remove() :移除一个 Fragment transaction.replace() :使用一个 Fragment 替换当前正在显示的 Fragment,可以理解为 remove 和 add 的结合 transaction.hide() :隐藏当前的 Fragment,不会销毁,就像控件设置 visibile 为 invisibile 一样,Fragment 只是不可见 transaction.show() :显示隐藏的 Fragment transaction.commit() :提交事务,也就是你之前调用了那些,现在要提交以生效。 以上,是操作 Fragment 的基本方式,在一个事务开启到提交可以进行多个的添加、移除、替换等操作。如果你经常使用Fragment,一定要清楚这些方法,哪个会销毁视图,哪个会销毁实例,哪个仅仅只是隐藏,这样才能更好的使用它们。
Android 人事+技术总贴
Android 基础篇总贴
Android 进阶篇总贴
Android 讨论区
以上言论,如有错误或者表达不准确或者有纰漏的地方还请指正,同时欢迎大家在评论区留言给予一定的建议,我会根据大家的意见进行相应的改正,谢谢各位!
|