Fragment基础知识
Fragment 介绍
答:Fragment是Android3.0后引入的一个新的API,他出现的初衷是为了适应大屏幕的平板电脑, 当然现在他仍然是平板APP UI设计的宠儿,而且我们普通手机开发也会加入这个Fragment, 我们可以把他看成一个小型的Activity,又称Activity片段!想想,如果一个很大的界面,我们 就一个布局,写起界面来会有多麻烦,而且如果组件多的话是管理起来也很麻烦!而使用Fragment 我们可以把屏幕划分成几块,然后进行分组,进行一个模块化的管理!从而可以更加方便的在 运行过程中动态地更新Activity的用户界面!另外Fragment并不能单独使用,他需要嵌套在Activity 中使用,尽管他拥有自己的生命周期,但是还是会受到宿主Activity的生命周期的影响,比如Activity 被destory销毁了,他也会跟着销毁!。
Fragment为什么被称为第五大组件?
Fragment的使用次数是不输于其他四大组件的,而且Fragment有自己的生命周期,比Activity更加节省内存。
Fragment的优势有以下几点:
模块化(Modularity):我们不必把所有代码全部写在Activity中,而是把代码写在各自的Fragment中。
可重用(Reusability):多个Activity可以重用一个Fragment。
可适配(Adaptability):根据硬件的屏幕尺寸、屏幕方向,能够方便地实现不同的布局,这样用户体验更好。
Fragment 应用
下图是文档中给出的一个Fragment分别对应手机与平板间不同情况的处理图:
在这里插入图片描述
实际中,app中的应用
在这里插入图片描述
如何创建Fragment
创建Fragment对象:(右击新建Fragment一步搞定)
内部执行的顺序是:
(1).定义一个类, 继承Fragment
(2).重写父类的方法onCreateView()
(3).在onCreateView()方法中, 为Fragment 创建UI界面
加载Fragment的两种方式
静态加载
在这里插入图片描述
自动生成的java文档
public class MyFragment extends Fragment {
public MyFragment() {
// Required empty public constructor
}
/**
* 参数详解
* fragment第一次创建用户界面时回调的方法
* @param inflater 实体加载器,用于加载一个fragment的视图
* @param container 表示当前fragment插入到activity中的对象
* @param savedInstanceState 表示储存一个fragment的信息
* @return
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_my, container, false);
}
}
自动生成的xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.MyFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
在需要加载fragment的activity中,想使用TextView一样,直接创建一个fragment即可.
已下是MainActivity中的xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--一定要注意的是:name属性是fragment的全限定名-->
<fragment
android:id="@+id/my_fragment_id"
android:name="com.example.day004.fragment.MyFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</fragment>
</LinearLayout>
以上是静态加载内容.
动态加载
动态加载也就是在java代码中创建fragment.
FragmentManager 介绍
1.简介
中文名称:碎片管理器
出生日期:Android 3.0/API level 11
助 理:FragmentTransaction
获取方式:
①Android 3.0前的版本使用getSupportFragmentManager()方法获取
②Android 3.0之后的版本用getFragmentManager()获取.
为了兼容的效果,我们选择getSupportFragmentManager()方法.
getFragmentManager()方法已经废弃.
一定要注意,如果用getSupportFragmentManager()这个方法,就整个项目全部用,
不要在项目里交叉使用getFragmentManager()方法.
否则你得请神仙来找错了.
2.实现流程
1:获得FragmentManager对象
FragmentManager fragmentManager=getSupportFragmentManager();
2:开启事务
FragmentTransaction transaction = fragmentManager.beginTransaction();
3:通过FragmentTransaction 调用add()、replace()方法管理fragment
4:transaction .commit();
在这里插入图片描述
package com.example.day004;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.day004.fragment.OneFragment;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1,创建fragment的管理对象
FragmentManager supportFragmentManager = getSupportFragmentManager();
//2,获取fragment的事物对象,并开启事务
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
//3,调用事务中相应的方法,来操作fragment
//add方法参数,第一个要放入的容器(布局的Id),第二个是fragment对象
fragmentTransaction.add(R.id.main_layout_id,new MyFragment());
//4,提交事务
fragmentTransaction.commit();
}
}
add,remove,replace,hide 方法
package com.example.day004;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.day004.fragment.MyFragment;
import com.example.day004.fragment.OneFragment;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1,创建fragment的管理对象
FragmentManager supportFragmentManager = getSupportFragmentManager();
//2,获取fragment的事物对象,并开启事务
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
//3,调用事务中相应的方法,来操作fragment
//add方法参数,第一个要放入的容器(布局的Id),第二个是fragment对象
MyFragment myFragment = new MyFragment();
fragmentTransaction.add(R.id.main_layout_id,myFragment);
//移除一个Fragment
fragmentTransaction.remove(myFragment);
OneFragment oneFragment = new OneFragment(); //实例化一个Fragment对象
//replace(替换一个布局)执行过程是先 remove 然后在 add.
fragmentTransaction.replace(R.id.main_layout_id,oneFragment);
//隐藏一个Fragment
fragmentTransaction.hide(oneFragment);
//4,提交事务
fragmentTransaction.commit();
}
}
Fragment的生命周期
文字描述版本的生命周期.
1.onAttach() :Fragment与Activity有联系。
2.onCreate():创建Fragment
3.onCreateView():创建Fragment视图,尽量不要做耗时操作
4.onActivityCreated():当Activity中的onCreate方法执行完后调用。
5.onStart():启动。
6.onResume():可见
7.onPause():不可见
8.onStop():停止。
9. onDestroyView() :销毁Fragment视图
10.onDestroy():销毁fragment对象
11.onDetach():Fragment和Activity解除关联的时候调用
Fragment高级进阶
Fragment 回退栈
radioGroupId.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.person_id:
manager = getSupportFragmentManager();
fragmentTransaction = manager.beginTransaction();
// fragmentTransaction.replace(R.id.frame_layout_id,new FristFragment());
fragmentTransaction.add(R.id.frame_layout_id,new FristFragment());
//入栈
fragmentTransaction.addToBackStack("11");
fragmentTransaction.commit();
break;
case R.id.message_id:
manager = getSupportFragmentManager();
//出栈
manager.popBackStack();
SelectActivity.this.fragmentTransaction = manager.beginTransaction();
SelectActivity.this.fragmentTransaction.replace(R.id.frame_layout_id,new SecondFragment());
// fragmentTransaction.addToBackStack(null);
SelectActivity.this.fragmentTransaction.commit();
break;
default:
break;
}
}
});
case R.id.message_id:
manager = getSupportFragmentManager();
// manager.popBackStack();
fragmentTransaction = manager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout_id,new SecondFragment());
//添加了返回栈,点击back的时候,不会退出activity,而会返回到之前的fragment界面.
// fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
Fragment 传值介绍
activity 给 fragment传值
主要涉及到一个方法是getArguments()和setArguments().
一个设置属性值,一个去取属性值.
步骤:
要传的值,放到bundle对象里;
在Activity中创建该Fragment的对象fragment,通过调用
fragment.setArguments()传递到fragment中;
然后更新fragment.
在该Fragment中通过调用getArguments()得到bundle对象,就能得到里面的值。
代码来了 这是刚创建完成的activity
package com.example.day004;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
/**
* activity 向 fragment 传值
*/
public class A2FActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a_2_f);
}
//点击事件的方法
public void click(View view) {
}
}
这是修完以后的他的xml的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".A2FActivity">
<EditText
android:id="@+id/et_id"
android:hint="来啊,传点啥吧!"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!--在activity中定义了点击事件-->
<Button
android:id="@+id/button_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点我试试"
android:onClick="click"
/>
<!--用来显示内容的,是个容器,里面可以放fragment-->
<LinearLayout
android:orientation="horizontal"
android:id="@+id/linear_layout_id"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
</LinearLayout>
创建fragment(右键一键完事,带布局)
package com.example.day004.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.day004.R;
/**
*用来接受传值的
*/
public class ShowContextFragment extends Fragment {
public ShowContextFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_show_context, container, false);
}
}
修改后的fragment的xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.ShowContextFragment">
<!--只加了一个Id,其他可有可无-->
<TextView
android:id="@+id/context_tv_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@color/colorAccent"
android:textSize="30sp"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
完整版的fragment
package com.example.day004.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.example.day004.R;
/**
*用来接受传值的
*/
public class ShowContextFragment extends Fragment {
private TextView textView;
public ShowContextFragment() {
// Required empty public constructor
}
//现在text里面的值是"hello_blank_fragment",思路就是拿到控件,重新赋值即可.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_show_context, container, false);
//1 拿控件
textView = inflate.findViewById(R.id.context_tv_id);
//2 给控件赋值
Bundle arguments = getArguments();
if(arguments != null){ //第一次启动一定为null,所以要判断一下
String key = arguments.getString("key");
textView.setText(key);
}
return inflate;
}
}
完整版的a2fActivity
package com.example.day004;
import android.icu.util.BuddhistCalendar;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import com.example.day004.fragment.ShowContextFragment;
import java.io.BufferedReader;
/**
* activity 向 fragment 传值
*/
public class A2FActivity extends AppCompatActivity {
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a_2_f);
//0,取到edit的控件和值
editText = findViewById(R.id.et_id);
//1,在这里动态添加一个fragment
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
//注意这个布局文件,是R.layout.activity_a_2_f xml文件里的线性布局
fragmentTransaction.add(R.id.linear_layout_id,new ShowContextFragment());
fragmentTransaction.commit();
}
public void click(View view) {
//取到输入的值
String string = editText.getText().toString();
//创建fragment对象
ShowContextFragment showContextFragment = new ShowContextFragment();
//创建bundle
Bundle bundle = new Bundle();
bundle.putString("key",string);
//给fragment对象赋值
showContextFragment.setArguments(bundle);
//动态修改fragment
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.linear_layout_id,showContextFragment);
fragmentTransaction.commit();
}
}
fragment 给 activity传值
第一种:
在Activity中调用getFragmentManager()得到fragmentManager,,调用findFragmentByTag(tag)或者通过findFragmentById(id)
FragmentManager fragmentManager = getFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(tag);
第二种:
通过回调的方式,定义一个接口(可以在Fragment类中定义),接口中有一个空的方法,在fragment中需要的时候调用接口的方法,值可以作为参数放在这个方法中,然后让Activity实现这个接口,必然会重写这个方法,这样值就传到了Activity中.
大白话,就是java的父类引用指向了子类对象
Activity中的代码
package com.example.day004;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.example.day004.fragment.ShowTitleFragment;
public class F2AActivity extends AppCompatActivity implements ShowTitleFragment.MyListener {
private TextView textView;
@Override
public void sendMessage(String string) {
textView.setText(string);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_f_2_a);
textView = findViewById(R.id.f2a_tv_id);
}
}
Activity中的xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".F2AActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/f2a_tv_id"
android:textSize="30sp"
android:hint="提示而已"
/>
<fragment
android:name="com.example.day004.fragment.ShowTitleFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/f2a_fm_id">
</fragment>
</LinearLayout>
fragment中的代码
package com.example.day004.fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import com.example.day004.R;
/**
* A simple {@link Fragment} subclass.
*/
public class ShowTitleFragment extends Fragment {
private EditText editText;
private Button button;
private MyListener listener;
public ShowTitleFragment() {
// Required empty public constructor
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
//拿到与当前fragment关联的Activity.
listener = (MyListener) getActivity();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_show_title, container, false);
//取到所有控件
editText = inflate.findViewById(R.id.fm_title_et_id);
button = inflate.findViewById(R.id.fm_title_button_id);
//点击事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String string = editText.getText().toString();
if(string != null){
//注意了.这里是父类引用指向了子类对象,其实是activity中的sendmessage方法在执行.
listener.sendMessage(string);
}
}
});
//返回fragment中的布局视图
return inflate;
}
//自定义的接口
public interface MyListener{
void sendMessage(String string);
}
}
fragment的xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".fragment.ShowTitleFragment">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/fm_title_et_id"
android:hint="整的啥吧"
/>
<Button
android:id="@+id/fm_title_button_id"
android:text="发送了啊"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
fragment 给 fragment 传值
第一种:
动态创建的fragment通过findFragmentByTag得到另一个的Fragment的对象,这样就可以调用另一个的方法了。
静态创建的fragment通过findFragmentById得到另一个的Fragment的对象,这样就可以调用另一个的方法了。
package com.example.day005.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.example.day005.R;
/**
* A simple {@link Fragment} subclass.
*/
public class LeftFragment extends Fragment {
private EditText editText;
private Button send_button;
public LeftFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_left, container, false);
editText = inflate.findViewById(R.id.left_textView_id);
send_button = inflate.findViewById(R.id.left_button_id);
send_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String string = editText.getText().toString();
**了解一种即可,不重点**
//1 fragment传值方式1
// 通过id找的指定fragment,调用他的方法,给他的组件赋值.
FragmentManager fragmentManager = getFragmentManager(); //注意,这个manager是v4包下的.
RightFragment rightFragment=(RightFragment) fragmentManager.findFragmentById(R.id.right_fragment_id);
rightFragment.setTextView(string);
//2 通过id找的指定fragment,得到他所有的view.在通过findViewById 找到组件.赋值
TextView textView = getFragmentManager().findFragmentById(R.id.right_fragment_id).getView().findViewById(R.id.right_textview_id);
textView.setText(string);
//3
//因为两个fragment在一个activity里面,所有可以通过拿到activity里面所有的指定组件.
TextView textView = (TextView) getActivity().findViewById(R.id.right_textview_id);
textView.setText(string);
}
});
return inflate;
}
}
第二种(重点)
通过接口回调的方式。
与上面的接口回调用法相同
第三种:
通过setArguments,getArguments的方式。
fragment 多层嵌套
与正常使用区别不大
FragmentManager childFragmentManager = getChildFragmentManager();
FragmentTransaction fragmentTransaction = childFragmentManager.beginTransaction();
fragmentTransaction.add(R.id.left_fragment_id,new RightFragment());
fragmentTransaction.commit();
案例(微信底部按钮与fragment实现界面切换)
activity中的代码
package com.example.day004.activities;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
import com.example.day004.R;
import com.example.day004.fragment.FristFragment;
import com.example.day004.fragment.SecondFragment;
/**
* 底部导航
*/
public class SelectActivity extends AppCompatActivity {
private FrameLayout frameLayoutId;
private RadioGroup radioGroupId;
private RadioButton personId;
private RadioButton messageId;
private static final String TAG = "SelectActivity";
private FragmentManager manager;
private FragmentTransaction fragmentTransaction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select);
frameLayoutId = findViewById(R.id.frame_layout_id);
radioGroupId = findViewById(R.id.radio_group_id);
radioGroupId.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.person_id:
manager = getSupportFragmentManager();
fragmentTransaction = manager.beginTransaction();
// fragmentTransaction.replace(R.id.frame_layout_id,new FristFragment());
fragmentTransaction.add(R.id.frame_layout_id,new FristFragment());
fragmentTransaction.addToBackStack("11");
Log.i(TAG, "onCheckedChanged: "+SelectActivity.class.getName());
fragmentTransaction.commit();
break;
case R.id.message_id:
manager = getSupportFragmentManager();
manager.popBackStack();
SelectActivity.this.fragmentTransaction = manager.beginTransaction();
SelectActivity.this.fragmentTransaction.replace(R.id.frame_layout_id,new SecondFragment());
// fragmentTransaction.addToBackStack(null);
SelectActivity.this.fragmentTransaction.commit();
break;
default:
break;
}
}
});
}
}
activity的xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activities.SelectActivity">
<FrameLayout
android:id="@+id/frame_layout_id"
android:layout_weight="9"
android:layout_width="match_parent"
android:layout_height="0dp">
</FrameLayout>
<RadioGroup
android:id="@+id/radio_group_id"
android:layout_weight="1"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0dp">
<RadioButton
android:layout_weight="1"
android:id="@+id/person_id"
android:button="@null"
android:text="联系人"
android:gravity="center"
android:checked="true"
android:drawableTop="@drawable/select_pserson"
android:textColor="@drawable/select_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
/>
<RadioButton
android:layout_weight="1"
android:id="@+id/message_id"
android:button="@null"
android:gravity="center"
android:drawableTop="@drawable/select_message"
android:textColor="@drawable/select_text"
android:text="信息"
android:layout_width="0dp"
android:layout_height="wrap_content"
/>
</RadioGroup>
</LinearLayout>
说明
android:drawableTop="@drawable/select_message"
android:textColor="@drawable/select_text"
这两个属性,参照下面链接创建
https://blog.youkuaiyun.com/qq_34178710/article/details/91411003
java代码中的fragment,右键创建即可.