首页 > 系统 > Android > 正文

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

2019-12-12 05:21:43
字体:
来源:转载
供稿:网友

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

先来看看效果 

那么就开始实现了!

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

 总结:

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

下载地址:点击打开链接

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表