前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >android实现底部导航栏

android实现底部导航栏

作者头像
砸漏
发布2020-11-05 11:33:08
3.3K0
发布2020-11-05 11:33:08
举报
文章被收录于专栏:恩蓝脚本恩蓝脚本

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

首先是开始的activity_main.xml

代码语言:javascript
复制
<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文件里面写

代码语言:javascript
复制
<android.support.v4.view.FragmentTabHost   
</android.support.v4.view.FragmentTabHost  

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

再来是tab_foot.xml

代码语言:javascript
复制
<?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的代码

代码语言:javascript
复制
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类

代码语言:javascript
复制
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

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?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类

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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贴下,就是每个碎片最默认的显示页面

代码语言:javascript
复制
<?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  

以上就是本文的全部内容,希望对大家的学习有所帮助。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档