第4章 探究碎片fragment
本系列学习笔记第4章
前言
打算把android基本知识点写一个系列,旨在把android基础书,例如《Android 第一行代码 第2版》、《爱上android》、《疯狂android讲义》等书的一些知识点记录一下,会持续更新内容,为了方便自己复习,也希望可以帮助到大家!
1、碎片是什么
碎片(Fragment)是一种可以嵌入在活动当中的UI片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用得非常广泛。
2、碎片的使用方式
2.1 静态添加碎片(布局文件中添加碎片)
left_fragment.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/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Button"
/>
</LinearLayout>
right_fragment.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#00ff00"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="This is right fragment"
/>
</LinearLayout>
LeftFragment.java文件
public class LeftFragment extends Fragment {
public static final String TAG = LeftFragment.class.getSimpleName();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_fragment, container, false);
return view;
}
}
RightFragment.java文件
public class RightFragment extends Fragment {
public static final String TAG = RightFragment.class.getSimpleName();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right_fragment, container, false);
return view;
}
}
activity_main.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"
tools:context="com.example.fragmenttest.MainActivity">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
/>
<fragment
android:id="@+id/right_fragment"
android:name="com.example.fragmenttest.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
/>
</LinearLayout>
效果图如下:
image.png
2.2 动态态添加碎片
2.2.1 案例一
在上一节的代码基础上修改,新建another_right_fragment.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#ffff00"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
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"
/>
</LinearLayout>
AnotherRightFragment.java文件
public class AnotherRightFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.another_right_fragment, container, false);
return view;
}
}
activity_main.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"
tools:context="com.example.fragmenttest.MainActivity">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
/>
<FrameLayout
android:id="@+id/right_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
/>
</LinearLayout>
MainActivity.java文件
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
replaceFragment(new RightFragment());
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.button:
replaceFragment(new AnotherRightFragment());
break;
default:
break;
}
}
private void replaceFragment(Fragment fragment){
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout,fragment);
transaction.commit();
}
}
效果图如下:
image.png image.png
2.2.1 案例二
layout_left_fragment.xml文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
>
</android.support.constraint.ConstraintLayout>
layout_right_fragment.xml文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
>
</android.support.constraint.ConstraintLayout>
activity_main.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"
tools:context="com.example.fragmenttest2.MainActivity">
<FrameLayout
android:id="@+id/container_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
LeftFragment.java文件
public class LeftFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_left_fragment, null);
return view;
}
}
RightFragment.java 文件
public class RightFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_right_fragment, null);
return view;
}
}
MainActivity.java文件
public class MainActivity extends AppCompatActivity {
private LeftFragment leftFragment;
private RightFragment rightFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WindowManager windowManager = getWindowManager();
DisplayMetrics displayMetrics = new DisplayMetrics();
//测量屏幕的尺寸
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
//测量屏幕宽高
int widthPixels = displayMetrics.widthPixels;
int heightPixels = displayMetrics.heightPixels;
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
if (widthPixels > heightPixels){
transaction.replace(R.id.container_content,getLeftFragment());
}else if (widthPixels < heightPixels){
transaction.replace(R.id.container_content, getRightFragment());
}
transaction.addToBackStack(null);
transaction.commit();
}
// 获取左边的Fragment
private LeftFragment getLeftFragment(){
if (leftFragment == null){
leftFragment = new LeftFragment();
}
return leftFragment;
}
// 获取左边的Fragment
private RightFragment getRightFragment(){
if (rightFragment == null){
rightFragment = new RightFragment();
}
return rightFragment;
}
}
image.png
image.png
2.3 在碎片中模拟返回栈
修改MainActivity.java文件
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
replaceFragment(new RightFragment());
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.button:
replaceFragment(new AnotherRightFragment());
break;
default:
break;
}
}
private void replaceFragment(Fragment fragment){
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout,fragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
效果图如下:
image.png
image.png image.png
image.png
image.png
image.png
image.png
2.4 碎片和活动之间进行通信
1)活动中使用碎片的方法(获得碎片的实例,就可以获取碎片的方法)
LeftFragment leftFragment = (LeftFragment) getSupportFragmentManager().findFragmentById(R.id.left_fragment);
2)碎片中使用活动的方法
MainActivity activity = (MainActivity) getActivity();
3)碎片与碎片之间的通信
基本思路如下:
在一个碎片中可以获取得到与它相关联的活动,然后再通过这个活动去获取另外一个碎片的实例,这样也就实现了不同碎片之间的通信功能。
2.5 片段管理的一些说明
1)从Activity通过getSupportFragmentManager()方法(建议用这个兼容版本)或者getFragmentManager()方法获取FragmentManager
2)通过fragmentManager.findFragmentById()方法(对于在Activity布局中提供UI片段)获取Activity中存在的Fragment
3)通过fragmentManager.findFragmentByTag()方法(对于提供或不提供UI片段)获取Activity中存在的Fragment
4) 通过fragmentManager.popBackStack()(模拟用户按Back返回键)将片段从返回栈中弹出
5)通过fragmentManager.beginTransaction()开启一个事务
6) 通过fragmentManager.addOnBackStackChangedListener()注册一个监听返回栈的监听器
7)transaction.addToBackStack(null)添加返回栈
3、碎片的生命周期
3.1 碎片的状态和回调
1)运行状态
当一个碎片是可见的,并且它所关联的活动正处于运行状态时,该碎片也处于运行状态。
2)暂停状态
当一个活动进入暂停状态时(由于另外一个未占满屏幕的活动被添加到了栈顶),与它相关联的可见碎片就会进入暂停状态
3)停止状态
当一个活动进入停止状态时,与它相关联的碎片就会进入到停止状态,或者通过FragmentTransaction的remove()、replace()方法将碎片从活动中移除,但是如果在事务提交之前调用addToBackStack()方法,这时的碎片也会进入到停止状态。总的来说,进入停止状态的碎片对用户来说是完全不可见的,也可能会被系统回收。
4)销毁状态
碎片总是依附于活动而存在的,因此当活动被销毁时,与它相关联的碎片就会进入到销毁状态。或者通过调用FragmentTransaction的remove()、replace()方法将碎片从活动中移除,但是在事务提交之前并没有调用addToBackStack()方法,这时的碎片也会进入到销毁状态。
3.2 体验碎片的生命周期
修改RightFragment,java文件
public class RightFragment extends Fragment {
public static final String TAG = RightFragment.class.getSimpleName();
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d(TAG, "onAttach");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.right_fragment, container, false);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "onActivityCreated");
}
@Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart");
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause");
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop");
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "onDestroyView");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
@Override
public void onDetach() {
super.onDetach();
Log.d(TAG, "onDetach");
}
}
运行上面的项目,观察发现RightFragment 的生命周期如下:
image.png
点击按钮切换Fragment
image.png image.png
如果在替换的时候没有调用addToBackStack()方法,生命周期如下:
image.png
点击返回按钮,RightFragment 的生命周期如下:
image.png image.png
4、动态加载布局的技巧
4.1 使用限定符
layout/activity_main.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"
tools:context="com.example.fragmenttest.MainActivity">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
layout-large目录下的activity_main.xml文件
<?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/left_fragment"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="@+id/right_fragment"
android:name="com.example.fragmenttest.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
image.png
image.png
4.2 使用最小宽度限定符
最小宽度限定符允许我们对屏幕的宽度指定一个最小值(以dp为单位),然后以这个最小值为临界点,屏幕宽度大于这个值的设备就加载一个布局,屏幕宽度小于这个值的设备就加载另一个布局
例如,res目录下新建layout-sw6600dp的文件夹,就是以屏幕宽度600dp为临界点
5、碎片的最佳实现---------一个简易版的新闻应用
创建实体类News,java
···
public class News {
private String title;
private String content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
···
列表item布局news_item.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/news_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="end"
android:textSize="18sp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
/>
news_content_frag.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/visibility_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible" >
<TextView
android:id="@+id/news_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:textSize="20sp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000" />
<TextView
android:id="@+id/news_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="15dp"
android:textSize="18sp" />
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:background="#000" />
</RelativeLayout>
NewsContentFragment文件
public class NewsContentFragment extends Fragment {
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.news_content_frag, container, false);
return view;
}
public void refresh(String newsTitle, String newsContent) {
View visibilityLayout = view.findViewById(R.id.visibility_layout);
visibilityLayout.setVisibility(View.VISIBLE);
TextView newsTitleText = (TextView) view.findViewById (R.id.news_title);
TextView newsContentText = (TextView) view.findViewById(R.id.news_content);
newsTitleText.setText(newsTitle); // 刷新新闻的标题
newsContentText.setText(newsContent); // 刷新新闻的内容
}
}
NewsContentActivity.java文件
public class NewsContentActivity extends AppCompatActivity {
public static void actionStart(Context context, String newsTitle, String newsContent) {
Intent intent = new Intent(context, NewsContentActivity.class);
intent.putExtra("news_title", newsTitle);
intent.putExtra("news_content", newsContent);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_content);
String newsTitle = getIntent().getStringExtra("news_title"); // 获取传入的新闻标题
String newsContent = getIntent().getStringExtra("news_content"); // 获取传入的新闻内容
NewsContentFragment newsContentFragment = (NewsContentFragment) getSupportFragmentManager().findFragmentById(R.id.news_content_fragment);
newsContentFragment.refresh(newsTitle, newsContent); // 刷新NewsContentFragment界面
}
}
news_title_frag.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.support.v7.widget.RecyclerView
android:id="@+id/news_title_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
NewsTitleFragment.java文件
public class NewsTitleFragment extends Fragment {
private boolean isTwoPane;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.news_title_frag, container, false);
RecyclerView newsTitleRecyclerView = (RecyclerView) view.findViewById(R.id.news_title_recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
newsTitleRecyclerView.setLayoutManager(layoutManager);
NewsAdapter adapter = new NewsAdapter(getNews());
newsTitleRecyclerView.setAdapter(adapter);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getActivity().findViewById(R.id.news_content_layout) != null) {
isTwoPane = true; // 可以找到news_content_layout布局时,为双页模式
News news = newsList.get(0);
NewsContentFragment newsContentFragment = (NewsContentFragment)
getFragmentManager().findFragmentById(R.id.news_content_fragment);
newsContentFragment.refresh(news.getTitle(), news.getContent());
} else {
isTwoPane = false; // 找不到news_content_layout布局时,为单页模式
}
}
private List<News> getNews() {
List<News> newsList = new ArrayList<>();
for (int i = 1; i <= 50; i++) {
News news = new News();
news.setTitle("This is news title " + i);
news.setContent(getRandomLengthContent("This is news content " + i + ". "));
newsList.add(news);
}
return newsList;
}
private String getRandomLengthContent(String content) {
Random random = new Random();
int length = random.nextInt(20) + 1;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < length; i++) {
builder.append(content);
}
return builder.toString();
}
class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
private List<News> mNewsList;
class ViewHolder extends RecyclerView.ViewHolder {
TextView newsTitleText;
public ViewHolder(View view) {
super(view);
newsTitleText = (TextView) view.findViewById(R.id.news_title);
}
}
public NewsAdapter(List<News> newsList) {
mNewsList = newsList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
News news = mNewsList.get(holder.getAdapterPosition());
if (isTwoPane) {
NewsContentFragment newsContentFragment = (NewsContentFragment)
getFragmentManager().findFragmentById(R.id.news_content_fragment);
newsContentFragment.refresh(news.getTitle(), news.getContent());
} else {
NewsContentActivity.actionStart(getActivity(), news.getTitle(), news.getContent());
}
}
});
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
News news = mNewsList.get(position);
holder.newsTitleText.setText(news.getTitle());
}
@Override
public int getItemCount() {
return mNewsList.size();
}
}
}
layout目录下的activity_main.xml文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/news_title_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/news_title_fragment"
android:name="com.example.fragmenttest.NewsTitleFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
layout-sw600dp目录下的activity_main.xml文件
<?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/news_title_fragment"
android:name="com.example.fragmenttest.NewsTitleFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="@+id/news_content_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" >
<fragment
android:id="@+id/news_content_fragment"
android:name="com.example.fragmenttest.NewsContentFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
image.png
image.png
image.png
6、FragmentTabHost实现底部标签
准备好图片资源,制作selector样式
image.png
tab1.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/tab1_normal" android:state_selected="false"/>
<item android:drawable="@drawable/tab1_selected" android:state_selected="true"/>
</selector>
tab2.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/tab2_normal" android:state_selected="false"/>
<item android:drawable="@drawable/tab2_selected" android:state_selected="true"/>
</selector>
image.png
layout_left_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:background="@color/colorAccent"
>
</LinearLayout>
layout_right_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:background="@color/colorPrimaryDark"
>
</LinearLayout>
LeftFragment.java文件
public class LeftFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_left_fragment, null);
return view;
}
}
RightFragment.java文件
public class RightFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_right_fragment, null);
return view;
}
}
layout_indicator_view.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:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_gravity="center"
android:id="@+id/iv_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
tools:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/tv_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标签"/>
</LinearLayout>
activity_fragment_tab_host.xml文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.app.FragmentTabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--用来加载Fragment -->
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<!--分割线 用来分割Fragment和底部标签-->
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#d9d9d9"
android:orientation="vertical"/>
<!--标签组件-->
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom" />
</LinearLayout>
</android.support.v4.app.FragmentTabHost>
FragmentTabHostActivity.java文件
public class FragmentTabHostActivity extends AppCompatActivity {
private FragmentTabHost fragmentTabHost;
//标签的图片
private int imageIds[] = {R.drawable.tab1, R.drawable.tab2,
};
//加载的Fragment
private Class<?> mFragmentClasses[] = {LeftFragment.class, RightFragment.class};
//标签文字
private String[] text=new String[]{"首页","娱乐"};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_tab_host);
fragmentTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
//初始化
fragmentTabHost.setup(this,getSupportFragmentManager(),android.R.id.tabcontent);
//去掉分割线
fragmentTabHost.getTabWidget().setDividerDrawable(null);
//添加标签
for (int i = 0; i < imageIds.length; i++) {
//Tab按钮添加文字和图片
TabHost.TabSpec tabSpec = fragmentTabHost.newTabSpec(i + "").setIndicator(getIndicatorView(this, i));
//添加到fragment
fragmentTabHost.addTab(tabSpec,mFragmentClasses[i],null);
}
//切换标签时调用
fragmentTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
@Override
public void onTabChanged(String s) {
}
});
}
//获取标签的View
private View getIndicatorView(Context context,int i){
View view = View.inflate(context,R.layout.layout_indicator_view, null);
ImageView imageView = (ImageView) view.findViewById(R.id.iv_tab);
TextView textView = (TextView) view.findViewById(R.id.tv_tab);
imageView.setImageResource(imageIds[i]);
textView.setText(text[i]);
return view;
}
}
image.png