android实现底部导航栏

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

首先是开始的activity_main.xml

<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文件里面写

<android.support.v4.view.FragmentTabHost >
</android.support.v4.view.FragmentTabHost>

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

再来是tab_foot.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="#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的代码

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类

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

<?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

<?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

<?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类

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

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

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

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贴下,就是每个碎片最默认的显示页面

<?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> 

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

(0)

相关推荐

  • Android design包自定义tablayout的底部导航栏的实现方法

    以前做项目大多用的radiobutton,今天用tablayout来做一个tab切换页面的的效果. 实现的效果就是类似QQ.微信的页面间(也就是Fragment间)的切换.如图: 布局只要一个tablayout <android.support.design.widget.TabLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:id=&

  • Android中TabLayout+ViewPager 简单实现app底部Tab导航栏

    前言 在谷歌发布Android Design Support Library之前,app底部tab布局的实现方法就有很多种,其中有RadioGroup+FrameLayout.TabHost+Fragment.FragmentPagerAdapter+ViewPager等方法,虽然这些方法虽然能达到同样的效果,但我个人总觉得有些繁琐.然而,Google在2015的IO大会上,给开发者们带来了全新的Android Design Support Library,里面包含了许多新控件,这些新控件有许多

  • 使用RadioButton+Fragment实现底部导航栏效果

    底部导航栏,在我们App项目中是非常常用!而且实现它的方式很多,今天我们就来使用RadioButton+Fragment实现底部导航栏! 下面就让我们动手吧,首先我们打开RadioButtonDemo这个项目,首先修改activity_main.xml文件如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.androi

  • 微信小程序实战之仿android fragment可滑动底部导航栏(4)

    底部3-5个选项的底部导航栏,目前在移动端上是主流布局之一,因此腾讯官方特地做了,可以通过设置,就可以做出了一个底部的导航栏. 相关教程:微信小程序教程系列之设置标题栏和导航栏(7) 但是通过设置的这个底部的导航栏,功能上比较固定,它必须要设置与它对应的一个页面,而且并不能滑动. 在业务上,有时候会比较限制,并不能完全满足所需. 又例如早前有人拿着UI稿问我,这种广告轮播图的样式,在小程序能不能实现呢? 我当时没有想了下,还不是很确定,因为小程序的轮播图的那几个小点点实在比较普通,样式单一. 因

  • Android实现底部导航栏功能

    本文实例为大家分享了Android实现底部导航栏功能的具体代码,供大家参考,具体内容如下 实验效果: (1)在drawable文件夹下新建tab_menu_bg.xml文件,具体代码如下: <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item

  • Android实现简单底部导航栏 Android仿微信滑动切换效果

    Android仿微信滑动切换最终实现效果: 大体思路: 1. 主要使用两个自定义View配合实现; 底部图标加文字为一个自定义view,底部导航栏为一个载体,根据需要来添加底部图标; 2. 底部导航栏的设置方法类似于TabLayout的关联,View需要创建关联方法,用来关联VIewPager; 3. 通过关联方法获取ViewPager实例后,根据ViewPager页面数创建底部导航栏的图标按钮; 代码实现: 1. 新建第一个自定义View, 图标 + 文字 的底部按钮; /** * 自定义控件

  • android中Fragment+RadioButton实现底部导航栏

    在App中经常看到这样的tab底部导航栏 那么这种效果是如何实现,实现的方式有很多种,最常见的就是使用Fragment+RadioButton去实现.下面我们来写一个例子 首先我们先在activity_mian.xml定义布局,整个布局的外面是线性布局,上面是帧布局切换不同的Fragment,底下是RadioGroup嵌套的是RadioButton.代码如下所示: <?xml version="1.0" encoding="utf-8"?> <Li

  • Android程序开发之Fragment实现底部导航栏实例代码

    流行的应用的导航一般分为两种,一种是底部导航,一种是侧边栏. 说明 IDE:AS,Android studio; 模拟器:genymotion; 实现的效果,见下图. 具体实现 为了讲明白这个实现过程,我们贴出来的代码多一写,这样更方便理解 [最后还会放出完整的代码实现] .看上图的界面做的比较粗糙,但实现过程的骨架都具有了,想要更完美的设计,之后自行完善吧 ^0^. 布局 通过观察上述效果图,发现任意一个选项页面都有三部分组成: 顶部去除ActionBar后的标题栏: 中间一个Fragment

  • Android实现底部导航栏功能(选项卡)

    现在很多android的应用都采用底部导航栏的功能,这样可以使得用户在使用过程中随意切换不同的页面,现在我采用TabHost组件来自定义一个底部的导航栏的功能. 我们先看下该demo实例的框架图: 其中各个类的作用以及资源文件就不详细解释了,还有资源图片(在该Demo中借用了其它应用程序的资源图片)也不提供了,大家可以自行更换自己需要的资源图片.直接上各个布局文件或各个类的代码: 1. res/layout目录下的 maintabs.xml 源码: <?xml version="1.0&q

  • Android用Scroller实现一个可向上滑动的底部导航栏

    静静等了5分钟竟不知道如何写我这第一篇文章.每次都想好好的学习学习,有时间多敲敲代码,写几篇自己的文章.今天终于开始实行了,还是有点小激动的.哈哈! 好了废话就不多收了.我今天想实现的一个功能就是一个可以上滑底部菜单栏.为什么我会想搞这么个东西呢, 还是源于一年前,我们app 有这么个需求,当时百度也好谷歌也好,都没有找到想要的效果,其实很简单的一个效果.但是当时我也是真的太菜了,所有有关自定义的控件真的是不会,看别人的代码还好,真要是自己写,一点头绪都没有.因为我试着写了,真的不行啊.当时觉得

随机推荐