服务器之家

服务器之家 > 正文

android实现底部导航栏

时间:2022-03-03 14:46     来源/作者:son_king

底部导航栏我选择用FragmentTabHost+Fragment来实现,这个方法比较好用,代码量也不多

首先是开始的activity_main.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<RelativeLayout 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="${relativePackage}.${activityClass}" >
 
 <FrameLayout
 android:id="@+id/main_view"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_above="@+id/main_tab"
 android:layout_alignParentLeft="true"
 android:layout_alignParentTop="true" >
 </FrameLayout>
 
 <view
 android:id="@+id/main_tab"
 android:layout_width="match_parent"
 android:layout_height="50dp"
 android:layout_alignParentBottom="true"
 android:layout_alignParentLeft="true"
 class="android.support.v4.app.FragmentTabHost" />
 
</RelativeLayout>

也可以直接在xml文件里面写

?
1
2
<android.support.v4.view.FragmentTabHost >
</android.support.v4.view.FragmentTabHost>

这xml文件就一个view加一个tab  view用来显示碎片,tab用来放置底部按钮的数量

再来是tab_foot.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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="#F6F6F6"
 android:gravity="center"
 android:orientation="vertical" >
 
 <ImageView
 android:id="@+id/foot_iv"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:src="@drawable/home1" />
 
 <TextView
 android:id="@+id/foot_tv"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginTop="3dp"
 android:text="首页"
 android:textColor="@color/tab_color" />
 
</LinearLayout>

这是每个底部按钮的布局设置的xml文件

再来是MainActivity的代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.gjn.mynavigation;
 
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TabWidget;
import android.widget.TextView;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabHost.TabSpec;
 
public class MainActivity extends FragmentActivity implements OnTabChangeListener {
 
 private FragmentTabHost mTabHost;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 requestWindowFeature(Window.FEATURE_NO_TITLE);
 setContentView(R.layout.activity_main);
 
 //初始化FragmentTabHost
 initHost();
 //初始化底部导航栏
 initTab();
 //默认选中
 mTabHost.onTabChanged(TabDb.getTabsTxt()[0]);
 }
 
 private void initTab() {
 String[] tabs = TabDb.getTabsTxt();
 for (int i = 0; i < tabs.length; i++) {
  //新建TabSpec
  TabSpec tabSpec = mTabHost.newTabSpec(TabDb.getTabsTxt()[i]);
  //设置view
  View view = LayoutInflater.from(this).inflate(R.layout.tabs_foot, null);
  ((TextView) view.findViewById(R.id.foot_tv)).setText(TabDb.getTabsTxt()[i]);
  ((ImageView) view.findViewById(R.id.foot_iv)).setImageResource(TabDb.getTabsImg()[i]);
  tabSpec.setIndicator(view);
  //加入TabSpec
  mTabHost.addTab(tabSpec,TabDb.getFramgent()[i],null);
 }
 }
 /***
 * 初始化Host
 */
 private void initHost() {
 mTabHost = (FragmentTabHost) findViewById(R.id.main_tab);
 //调用setup方法 设置view
 mTabHost.setup(this, getSupportFragmentManager(),R.id.main_view);
 //去除分割线
 mTabHost.getTabWidget().setDividerDrawable(null);
 //监听事件
 mTabHost.setOnTabChangedListener(this);
 }
 
 @Override
 public void onTabChanged(String arg0) {
 //从分割线中获得多少个切换界面
 TabWidget tabw = mTabHost.getTabWidget();
 for (int i = 0; i < tabw.getChildCount(); i++) {
  View v = tabw.getChildAt(i);
  TextView tv = (TextView) v.findViewById(R.id.foot_tv);
  ImageView iv = (ImageView) v.findViewById(R.id.foot_iv);
  //修改当前的界面按钮颜色图片
  if (i == mTabHost.getCurrentTab()) {
  tv.setTextColor(getResources().getColor(R.color.tab_light_color));
  iv.setImageResource(TabDb.getTabsImgLight()[i]);
  }else{
  tv.setTextColor(getResources().getColor(R.color.tab_color));
  iv.setImageResource(TabDb.getTabsImg()[i]);
  }
 }
 }
}

其中TabDb类是用来设置导航栏的数据和图片切换时候的资源
 以下是TabDb类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.gjn.mynavigation;
 
public class TabDb {
 /***
 * 获得底部所有项
 */
 public static String[] getTabsTxt() {
 String[] tabs = {"首页","交易","地点","我的"};
 return tabs;
 }
 /***
 * 获得所有碎片
 */
 public static Class[] getFramgent(){
 Class[] cls = {OneFm.class,TwoFm.class,ThreeFm.class,FourFm.class};
 return cls ;
 }
 /***
 * 获得所有点击前的图片
 */
 public static int[] getTabsImg(){
 int[] img = {R.drawable.home1,R.drawable.glod1,R.drawable.xc1,R.drawable.user1};
 return img ;
 }
 /***
 * 获得所有点击后的图片
 */
 public static int[] getTabsImgLight(){
 int[] img = {R.drawable.home2,R.drawable.glod2,R.drawable.xc2,R.drawable.user2};
 return img ;
 }
}

到此,底部导航栏就算是完全实现了。

现在来实现顶部导航栏,看了许多最后使用了RadioGroup+ViewPager来实现 
首先是为第一个碎片设计一个xml布局:fm_one.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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" >
 
 <HorizontalScrollView
 android:id="@+id/one_hv"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:scrollbars="none" >
 
 <RadioGroup
  android:id="@+id/one_rg"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="horizontal" >
 </RadioGroup>
 </HorizontalScrollView>
 
 <view
 android:id="@+id/one_view"
 android:layout_width="match_parent"
 android:layout_height="0dp"
 android:layout_weight="1"
 class="android.support.v4.view.ViewPager" />
 
</LinearLayout>

 设置顶部导航栏和显示view
之后是导航栏的每个项的布局

 tab_rb.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="@drawable/tab_rb_selector"
 android:button="@null"
 android:paddingBottom="10dp"
 android:paddingLeft="15dp"
 android:paddingRight="15dp"
 android:paddingTop="10dp"
 android:text="今日" >
</RadioButton>

其中设置selector文件来控制点击和未点击的状态

tab_rb_selector.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
 <!-- 点击 -->
 <item android:state_checked="true">
 <layer-list >
  <item >
  <shape android:shape="rectangle">
   <stroke android:width="5dp" android:color="@color/tab_light_color"/>
  </shape>
  </item>
  <item android:bottom="5dp">
  <shape android:shape="rectangle">
   <solid android:color="#fff"/>
  </shape>
  </item>
 </layer-list>
 </item>
 <!-- 默认 -->
 <item >
 <shape >
  <solid android:color="#fafafa"/>
 </shape>
 </item>
</selector>

 设置了点击和默认的时候的显示状态
最后来实现OneFm类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package com.gjn.mynavigation;
 
import java.util.ArrayList;
import java.util.List;
 
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.LayoutParams;
import android.widget.RadioGroup.OnCheckedChangeListener;
 
public class OneFm extends Fragment implements OnPageChangeListener {
 
 private View view;
 private RadioGroup rg_;
 private ViewPager vp_;
 private HorizontalScrollView hv_;
 private List<Fragment> newsList = new ArrayList<Fragment>();
 private OneFmAdapter adapter;
 
 @Override
 public View onCreateView(LayoutInflater inflater,
 @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 if (view == null) {
  //初始化view
  view = inflater.inflate(R.layout.fm_one, container,false);
  rg_ = (RadioGroup) view.findViewById(R.id.one_rg);
  vp_ = (ViewPager) view.findViewById(R.id.one_view);
  hv_ = (HorizontalScrollView) view.findViewById(R.id.one_hv);
  //设置RadioGroup点击事件
  rg_.setOnCheckedChangeListener(new OnCheckedChangeListener() {
 
  @Override
  public void onCheckedChanged(RadioGroup group, int id) {
   vp_.setCurrentItem(id);
  }
  }
  //初始化顶部导航栏
  initTab(inflater);
  //初始化viewpager
  initView();
 }
 /**
 * 底部导航栏切换后 由于没有销毁顶部设置导致如果没有重新设置view
 * 导致底部切换后切回顶部页面数据会消失等bug
 * 以下设置每次重新创建view即可
 */
 ViewGroup parent = (ViewGroup) view.getParent();
 if (parent != null) {
  parent.removeView(view);
 }
 return view;
 }
 /***
 * 初始化viewpager
 */
 private void initView() {
 List<HTab> hTabs = HTabDb.getSelected();
 for (int i = 0; i < hTabs.size(); i++) {
  OneFm1 fm1 = new OneFm1();
  Bundle bundle = new Bundle();
  bundle.putString("name", hTabs.get(i).getName());
  fm1.setArguments(bundle);
  newsList.add(fm1);
 }
 //设置viewpager适配器
 adapter = new OneFmAdapter(getActivity().getSupportFragmentManager(),newsList);
 vp_.setAdapter(adapter);
 //两个viewpager切换不重新加载
 vp_.setOffscreenPageLimit(2);
 //设置默认
 vp_.setCurrentItem(0);
 //设置viewpager监听事件
 vp_.setOnPageChangeListener(this);
 }
 /***
 * 初始化头部导航栏
 * @param inflater
 */
 private void initTab(LayoutInflater inflater) {
 List<HTab> hTabs = HTabDb.getSelected();
 for (int i = 0; i < hTabs.size(); i++) {
  //设置头部项布局初始化数据
  RadioButton rbButton = (RadioButton) inflater.inflate(R.layout.tab_rb, null);
  rbButton.setId(i);
  rbButton.setText(hTabs.get(i).getName());
  LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
  LayoutParams.WRAP_CONTENT);
  //加入RadioGroup
  rg_.addView(rbButton,params);
 }
 //默认点击
 rg_.check(0);
 }
 @Override
 public void onPageScrollStateChanged(int arg0) {
 
 }
 @Override
 public void onPageScrolled(int arg0, float arg1, int arg2) {
 
 }
 @Override
 public void onPageSelected(int id) {
 setTab(id);
 }
 /***
 * 页面跳转切换头部偏移设置
 * @param id
 */
 private void setTab(int id) {
 RadioButton rbButton = (RadioButton) rg_.getChildAt(id);
 //设置标题被点击
 rbButton.setChecked(true);
 //偏移设置
 int left = rbButton.getLeft();
 int width = rbButton.getMeasuredWidth();
 DisplayMetrics metrics = new DisplayMetrics();
 getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
 int screenWidth = metrics.widthPixels;
 //移动距离= 左边的位置 + button宽度的一半 - 屏幕宽度的一半
 int len = left + width / 2 - screenWidth / 2;
 //移动
 hv_.smoothScrollTo(len, 0);
 }
}

其中有两个数据类和一个碎片类

数据类

HTab.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.gjn.mynavigation;
 
/***
 * 头部Tab属性
 *
 */
public class HTab {
 private String name;
 
 public HTab(String name) {
 super();
 this.setName(name);
 }
 
 public String getName() {
 return name;
 }
 
 public void setName(String name) {
 this.name = name;
 }
}

 HTabDb.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.gjn.mynavigation;
 
import java.util.ArrayList;
import java.util.List;
 
public class HTabDb {
 private static final List<HTab> Selected = new ArrayList<HTab>();
 static{
 Selected.add(new HTab("今日"));
 Selected.add(new HTab("头条"));
 Selected.add(new HTab("娱乐"));
 Selected.add(new HTab("财经"));
 Selected.add(new HTab("军事"));
 Selected.add(new HTab("科技"));
 Selected.add(new HTab("时尚"));
 Selected.add(new HTab("体育"));
 }
 /***
 * 获得头部tab的所有项
 */
 public static List<HTab> getSelected() {
 return Selected;
 }
}

碎片类
OneFm1.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.gjn.mynavigation;
 
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
 
public class OneFm1 extends Fragment {
 
 private String name;
 
 @Override
 public void setArguments(Bundle args) {
 name = args.getString("name");
 }
 
 @Override
 public View onCreateView(LayoutInflater inflater,
 @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 View view = inflater.inflate(R.layout.fragment, container,false);
 ((TextView) view.findViewById(R.id.fm_text)).setText(name);
 return view;
 }
}

这样就把顶部的导航栏加入到了第一个fragment里面并且实现了切换功能
最后把fragment.xml贴下,就是每个碎片最默认的显示页面

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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:gravity="center"
 android:orientation="vertical" >
 
 <TextView
 android:id="@+id/fm_text"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Large Text"
 android:textAppearance="?android:attr/textAppearanceLarge" />
 
</LinearLayout>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/son_king/article/details/80783500

标签:

相关文章

热门资讯

2022年最旺的微信头像大全 微信头像2022年最新版图片
2022年最旺的微信头像大全 微信头像2022年最新版图片 2022-01-10
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
返回顶部