android viewpager 底部tabhost,TabHost+ViewPager实现底部导航效果

本文详细介绍了如何结合ViewPager和TabHost在Android中实现底部导航栏功能。首先,通过设置TabHost和ViewPager的布局实现基础结构,然后创建Fragment并传递参数,展示不同页面内容。接着,为每个Tab定制布局,包括文字和图标,并处理点击状态。最后,通过监听ViewPager和TabHost的交互,确保页面与Tab的一致性。完成以上步骤后,底部导航功能得以实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:摘要

这篇文章主要为大家介绍了使用ViewPager+TabHost实现底部导航效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。

下面我们先来看一下要实现的效果吧!

63684772812d

二:具体实现过程

1.新建一个project,把主布局改为TabHost,id为tab_host

2.主布局添加一个相对布局,相对布局里加一个id为view_pager的 ViewPager布局。

加一个id为@android:id/tabs的TabWidget(指明高度)并将其放在最底部。

由于TabWidget要求必须要有一个id为@android:id/tabcontent的FrameLayout,所以得再加一个FrameLayout。

为了看出界限,我们还要添加一条id为tab_divider线,具体可用View实现。

从上往下,对组件进行排布。

ViewPager和FrameLayout的layout_above="@+id/tab_divider",

View的layout_above="@android:id/tabs",

TabWidget的layout_alignParentBottom="true"。

最后,让FrameLayout的visibility="gone"。

3.创建一个TestFragment类继承Fragment并复写onCreate,onCreateView方法。

4.创建fragment_test.xml文件。里面添加一个id为text_view的TextView。

5.在TestFragment的onCreateView方法中,删除原有代码,通过布局反向生成view对象并加以返回。

部分代码:

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

//删除原有代码,通过布局反向生成view对象并加以返回。

View view=inflater.inflate(R.layout.fragment_test,null);

TextView textView=view.findViewById(R.id.text_view);

return view;

}

6.因为要给TestFragment传参数(标题),所以得写一个静态方法来实现newInstance。

部分代码:

public static TestFragment newInstance(String title){

TestFragment testFragment=new TestFragment();

//建立一个bundle

Bundle bundle=new Bundle();

bundle.putString(TITLE,title);

testFragment.setArguments(bundle);

return testFragment;

}

//该方法里设置一个bundle用来testFragment.setArguments(bundle);可以把title提取为常量TITLE。

7.在TestFragment的onCreate的方法里,我们要判断是否接受了数据,如果接受了数据,则把数据给提取出来。这时,我们可以把接受到的字符提取为一个叫mTitle的全局变量。

部分代码:

public void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

if (getArguments()!=null){

mTitle = getArguments().getString(TITLE);

}

}

8.因为有了传参,所以在TestFragment的onCreateView的方法里,我们要把对应布局的TextView找到,设置TextView的文本为传入的参数mTitle。

部分代码:

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

//删除原有代码,通过布局反向生成view对象并加以返回。

View view=inflater.inflate(R.layout.fragment_test,null);

TextView textView=view.findViewById(R.id.text_view);

textView.setText(mTitle);

return view;

}

9.在MainActivity把ViewPager引用出来,记为mViewPager。

10.我们要用三个fragment组成的viewpager。因此,先创建final Fragment [] fragments数组。注意分号

部分代码:

final Fragment[] fragments=new Fragment[]{

TestFragment.newInstance("home"),

TestFragment.newInstance("message"),

TestFragment.newInstance("me")

};//注意分号

11.给mViewPager设置适配器。

部分代码:

mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {……};

/*

要重写两个方法,getItem和getCount。

getItem中,return fragments[position];

getCount中,return fragments.length

*/

至此,上面部分已经完成。

我们来看看效果。

63684772812d

63684772812d

12.我们建立一个main_tab_layout.xml文件(相对布局),id为tab_bg。

里面加一个id为main_tab_icon的ImageView,id为main_tab_text的TextView。设置好控件的外边距。

如果以后有需要在右上角做一个小红点的话,可以把这两个放在一个id为main_contain的LinearLayout里,小红点在LinearLayout就行。

13.main_tab_layout.xml里的文本,点击和没点击会显示不同的颜色,所以我们可以用textColor="@color/color_main_tab_text"来实现。

新建color_main_tab_text布局,在其中的选择器selector里,添加item标签

(注意顺序,显示特殊情况下的选择,最后才是默认情况下的选择,否则会失效)

14.同理,我们可以在drawable里也建立3个选择器。可以直接把color_main_tab_text布局文件复制到drawable后改名改参数即可。

15.复制准备好的图片到drawable文件夹。对布局文件的参数进行修改。(注意顺序)

16.初始化总布局。把TabHost找出来并提取为全局变量mTabHost。调用mTabHost.setup();

17.三个Tab做处理。三个Tab做处理,用数组来准备。

int [] titlesIDs={R.string.home,R.string.message,R.string.me};//利用alt+enter为其设值。

int [] drawableIDs={

R.drawable.color_main_tab_icon_home,

R.drawable.color_main_tab_icon_message,

R.drawable.color_main_tab_icon_me

};

18.利用for循环把数据填充到布局里。

先把视图提取出来,给mIcon设置图片,给title设置文本,给tab设置背景颜色。

调用mTabHost.addTab方法。因为该方法的setContent()要设置视图内容,我们可以通过让该类实现一个TabContentFactory接口来解决。

部分代码:

//数据填到视图里

for (int index = 0; index < titlesIDs.length; index++) {

//先把视图提取出来

View view=getLayoutInflater().inflate(R.layout.main_tab_layout,null,false);

ImageView mIcon=view.findViewById(R.id.main_tab_icon);

TextView mTitle=view.findViewById(R.id.main_tab_text);

View tab=view.findViewById(R.id.tab_bg);

mIcon.setImageResource(drawableIDs[index]);

mTitle.setText(titlesIDs[index]);

//tab背景颜色,可以创建一个value

tab.setBackgroundColor(getResources().getColor(R.color.myColor));

mTabHost.addTab(

mTabHost.newTabSpec(getString(titlesIDs[index]))

.setIndicator(view)//设置分割

//因为实现了TabContentFactory接口,所以我们就可以用this

.setContent(this) );

}

19.MainActivity实现TabContentFactory接口,重写方法createTabContent。

在createTabContent中,直接创建一个view并返回就行。

因为下面的要对应上上面的内容,而我们的内容是用ViewPager做的,虽然我们不要这个内容,但要求我们必须设置,所以直接返回一个view。我们可以把它隐藏掉。

部分代码:

public View createTabContent(String tag) {

/*因为下面的要对应上上面的内容,而我们的内容是用ViewPager做的,

虽然我们不要这个内容,但要求我们必须设置,所以直接返回一个view。我们可以把它隐藏掉。

*/

View view=new View(this);

view.setMinimumWidth(0);

view.setMinimumHeight(0);

return view;

}

至此,界面基本完成。

63684772812d

20.我们看到底下有分割线,

在activity_main的TabWidget里,可以通过调用

android:showDividers="none"去掉分割线

21.最后,添加互动。

给mViewPager添加监听器。

部分代码:

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {……}

//在方法onPageSelected中先判断mTabHost是否为空,

//不为空则调用mTabHost.setCurrentTab(position);方法。具体如下:

public void onPageSelected(int position) {

if(mTabHost!=null){

mTabHost.setCurrentTab(position);

}

}

22.给mTabHost添加监听器。

部分代码:

/*

mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {……}

onTabChanged方法中,先判断mTabHost && mViewPager是否为空。

如果两个都不为空的话,则调用mViewPager.setCurrentItem(mTabHost.getCurrentTab());具体如下:

*/

mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {

@Override

public void onTabChanged(String tabId) {

if(mViewPager!=null&&mTabHost!=null){

//写法1

//mViewPager.setCurrentItem(mTabHost.getCurrentTab());

//写法2

int position = mTabHost.getCurrentTab();

mViewPager.setCurrentItem(position);

}

}

});

至此,全部功能已经完成。

下面提供全部代码,欢迎小伙伴们交流学习。

MainActivity:

package com.wxdgut.navigation;

import androidx.annotation.NonNull;

import androidx.appcompat.app.AppCompatActivity;

import androidx.fragment.app.Fragment;

import androidx.fragment.app.FragmentPagerAdapter;

import androidx.viewpager.widget.ViewPager;

import android.os.Bundle;

import android.view.View;

import android.widget.ImageView;

import android.widget.TabHost;

import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements TabHost.TabContentFactory {

private TabHost mTabHost;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTabHost = findViewById(R.id.tab_host);

mTabHost.setup();

//三个Tab做处理,用数组来准备

int [] titlesIDs= new int[]{R.string.home, R.string.message, R.string.me};

int [] drawableIDs={

R.drawable.main_tab_icon_home,

R.drawable.main_tab_icon_message,

R.drawable.main_tab_icon_me

};

//数据塞到视图里

for (int index = 0; index < titlesIDs.length; index++) {

//先把视图提取出来

View view=

getLayoutInflater().inflate(R.layout.main_tab_layout,null,false);

ImageView mIcon=view.findViewById(R.id.main_tab_icon);

TextView mTitle=view.findViewById(R.id.main_tab_text);

View tab=view.findViewById(R.id.tab_bg);

mIcon.setImageResource(drawableIDs[index]);

mTitle.setText(titlesIDs[index]);

//tab背景颜色,可以创建一个value

tab.setBackgroundColor(getResources().getColor(R.color.myColor));

mTabHost.addTab(

mTabHost.newTabSpec(getString(titlesIDs[index]))

.setIndicator(view)//设置分割

//因为实现了该接口,所以我们就可以用this

.setContent(this)

);

}

final Fragment[] fragments=new Fragment[]{

TestFragment.newInstance("home"),

TestFragment.newInstance("message"),

TestFragment.newInstance("me")

};//注意分号

final ViewPager mViewPager= findViewById(R.id.view_pager);

mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {

@NonNull

@Override

public Fragment getItem(int position) {

return fragments[position];

}

@Override

public int getCount() {

return fragments.length;

}

});

//做互动,将tab与viewpager关联

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

@Override

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override

public void onPageSelected(int position) {

if(mTabHost!=null){

mTabHost.setCurrentTab(position);

}

}

@Override

public void onPageScrollStateChanged(int state) {

}

});

mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {

@Override

public void onTabChanged(String tabId) {

if(mViewPager!=null&&mTabHost!=null){

//写法1

//mViewPager.setCurrentItem(mTabHost.getCurrentTab());

//写法2

int position = mTabHost.getCurrentTab();

mViewPager.setCurrentItem(position);

}

}

});

}

@Override

public View createTabContent(String tag) {

/*因为下面的要对应上上面的内容,而我们的内容是用ViewPager做的,

虽然我们不要这个内容,但要求我们必须设置,所以直接返回一个view。我们可以把它隐藏掉。

*/

View view=new View(this);

view.setMinimumWidth(0);

view.setMinimumHeight(0);

return view;

}

}

TestFragment:

package com.wxdgut.navigation;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.TextView;

import androidx.annotation.NonNull;

import androidx.annotation.Nullable;

import androidx.fragment.app.Fragment;

public class TestFragment extends Fragment {

public static final String TITLE = "title";

private String mTitle;

public static TestFragment newInstance(String title){

TestFragment testFragment=new TestFragment();

//建立一个bundle

Bundle bundle=new Bundle();

bundle.putString(TITLE,title);

testFragment.setArguments(bundle);

return testFragment;

}

@Override

public void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

if (getArguments()!=null){

mTitle = getArguments().getString(TITLE);

}

}

@Nullable

@Override

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

//删除原有代码,通过布局反向生成view对象并加以返回。非activity中就用inflater

View view=inflater.inflate(R.layout.fragment_test,null);

TextView textView=view.findViewById(R.id.text_view);

textView.setText(mTitle);

return view;

}

}

activity_main.xml:

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/tab_host"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/view_pager"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_above="@+id/tab_divider">

android:id="@android:id/tabcontent"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_above="@+id/tab_divider"

android:visibility="gone"/>

android:id="@+id/tab_divider"

android:layout_width="match_parent"

android:layout_height="5dp"

android:background="#dfdfdf"

android:layout_above="@android:id/tabs"/>

android:id="@android:id/tabs"

android:layout_width="match_parent"

android:layout_height="80dp"

android:showDividers="none"

android:layout_alignParentBottom="true"/>

fragment_test.xml:

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:gravity="center">

android:id="@+id/text_view"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="wxdgut.com"

android:textSize="25sp" />

main_tab_layout.xml:

android:orientation="vertical"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:id="@+id/tab_bg">

android:id="@+id/main_content"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="vertical"

android:gravity="center"

android:layout_centerInParent="true">

android:id="@+id/main_tab_icon"

android:layout_width="30dp"

android:layout_height="30dp"

android:src="@mipmap/ic_launcher"

android:layout_marginTop="4dp"/>

android:id="@+id/main_tab_text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/app_name"

android:textColor="@color/color_main_tab_text"

android:layout_marginTop="5dp"/>

//以后可以做个小红点

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:visibility="gone"/>

color_main_tab_text.xml:

//注意顺序,显示特殊情况下的选择,最后才是默认情况下的选择,否则会失效

main_tab_icon_home.xml:

//注意顺序,显示特殊情况下的选择,最后才是默认情况下的选择,否则会失效

main_tab_icon_me.xml和main_tab_icon_message.xml:同上面的类似。

接下来是图片素材,需要的话就保存一下吧。

1

63684772812d

tabbar_home_pressed

2

63684772812d

tabbar_home

3

63684772812d

tabbar_msg_pressed

4

63684772812d

tabbar_msg

5

63684772812d

tabbar_my_pressed

6

63684772812d

tabbar_my

欢迎小伙伴们批评指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值