当前位置: 移动技术网 > 移动技术>移动开发>Android > Android实现顶部底部双导航界面功能

Android实现顶部底部双导航界面功能

2019年07月24日  | 移动技术网移动技术  | 我要评论

最近想弄一个双导航功能,查看了许多资料,总算是实现了功能,这边就算是给自己几个笔记吧! 

先来看看效果 

那么就开始实现了! 

底部导航栏我选择用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>

其中我是直接拉的view所以是形成的fragmenttabhost

也可以直接在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>

 总结:

算是一个笔记记录吧!一段时间没更新了,由于刚毕业断了一个时间,走走停停留下一些自己的记录,就怕自己以后要写忘了。 

下载地址:

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网