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

来源:互联网 发布:linux口袋书 pdf 编辑:程序博客网 时间:2024/05/16 07:35

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

先来看看效果


那么就开始实现了!

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

首先是开始的activity_main.xml

[java] view plain copy
 print?
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     tools:context="${relativePackage}.${activityClass}" >  
  6.   
  7.     <FrameLayout  
  8.         android:id="@+id/main_view"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="match_parent"  
  11.         android:layout_above="@+id/main_tab"  
  12.         android:layout_alignParentLeft="true"  
  13.         android:layout_alignParentTop="true" >  
  14.   
  15.     </FrameLayout>  
  16.   
  17.         <view  
  18.         android:id="@+id/main_tab"  
  19.         android:layout_width="match_parent"  
  20.         android:layout_height="50dp"  
  21.         android:layout_alignParentBottom="true"  
  22.         android:layout_alignParentLeft="true"   
  23.         class="android.support.v4.app.FragmentTabHost" />  
  24.   
  25. </RelativeLayout>  

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

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

<Android.support.v4.view.FragmentTabHost >

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

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

再来是tab_foot.xml

[java] view plain copy
 print?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="#F6F6F6"  
  6.     android:gravity="center"  
  7.     android:orientation="vertical" >  
  8.   
  9.     <ImageView  
  10.         android:id="@+id/foot_iv"  
  11.         android:layout_width="wrap_content"  
  12.         android:layout_height="wrap_content"  
  13.         android:src="@drawable/home1" />  
  14.   
  15.     <TextView  
  16.         android:id="@+id/foot_tv"  
  17.         android:layout_width="wrap_content"  
  18.         android:layout_height="wrap_content"  
  19.         android:layout_marginTop="3dp"  
  20.         android:text="首页"  
  21.         android:textColor="@color/tab_color" />  
  22.   
  23. </LinearLayout>  
这是每个底部按钮的布局设置的xml文件

显示效果。

再来是MainActivity的代码


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

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


--------------------------------------------------------------------------------------------------------------------------

现在来实现顶部导航栏,看了许多最后使用了RadioGroup+ViewPager来实现

首先是为第一个碎片设计一个xml布局

fm_one.xml

[java] view plain copy
 print?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <HorizontalScrollView  
  8.         android:id="@+id/one_hv"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:scrollbars="none" >  
  12.   
  13.         <RadioGroup  
  14.             android:id="@+id/one_rg"  
  15.             android:layout_width="match_parent"  
  16.             android:layout_height="match_parent"  
  17.             android:orientation="horizontal" >  
  18.         </RadioGroup>  
  19.     </HorizontalScrollView>  
  20.   
  21.     <view  
  22.         android:id="@+id/one_view"  
  23.         android:layout_width="match_parent"  
  24.         android:layout_height="0dp"  
  25.         android:layout_weight="1"  
  26.         class="android.support.v4.view.ViewPager" />  
  27.   
  28. </LinearLayout>  
设置顶部导航栏和显示view
之后吧导航栏的每个项的布局

tab_rb.xml

[java] view plain copy
 print?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RadioButton xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="wrap_content"  
  5.     android:background="@drawable/tab_rb_selector"  
  6.     android:button="@null"  
  7.     android:paddingBottom="10dp"  
  8.     android:paddingLeft="15dp"  
  9.     android:paddingRight="15dp"  
  10.     android:paddingTop="10dp"  
  11.     android:text="今日" >  
  12. </RadioButton>  
其中设置selector文件来控制点击和未点击的状态

tab_rb_selector.xml

[java] view plain copy
 print?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android" >  
  3.     <!-- 点击 -->  
  4.     <item android:state_checked="true">  
  5.         <layer-list >  
  6.             <item >  
  7.                 <shape android:shape="rectangle">  
  8.                     <stroke android:width="5dp" android:color="@color/tab_light_color"/>  
  9.                 </shape>  
  10.             </item>  
  11.             <item android:bottom="5dp">  
  12.                 <shape android:shape="rectangle">  
  13.                     <solid android:color="#fff"/>  
  14.                 </shape>  
  15.             </item>  
  16.         </layer-list>  
  17.     </item>  
  18.     <!-- 默认 -->  
  19.     <item >  
  20.         <shape >  
  21.             <solid android:color="#fafafa"/>  
  22.         </shape>  
  23.     </item>  
  24. </selector>  
设置了点击和默认的时候的显示状态
最后来实现OneFm类

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

数据类

HTab.Java

[java] view plain copy
 print?
  1. package com.gjn.mynavigation;  
  2.   
  3. /*** 
  4.  * 头部Tab属性 
  5.  * 
  6.  */  
  7. public class HTab {  
  8.     private String name;  
  9.   
  10.     public HTab(String name) {  
  11.         super();  
  12.         this.setName(name);  
  13.     }  
  14.   
  15.     public String getName() {  
  16.         return name;  
  17.     }  
  18.   
  19.     public void setName(String name) {  
  20.         this.name = name;  
  21.     }  
  22.       
  23. }  
HTabDb.java
[java] view plain copy
 print?
  1. package com.gjn.mynavigation;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. public class HTabDb {  
  7.     private static final List<HTab> Selected = new ArrayList<HTab>();  
  8.     static{  
  9.         Selected.add(new HTab("今日"));  
  10.         Selected.add(new HTab("头条"));  
  11.         Selected.add(new HTab("娱乐"));  
  12.         Selected.add(new HTab("财经"));  
  13.         Selected.add(new HTab("军事"));  
  14.         Selected.add(new HTab("科技"));  
  15.         Selected.add(new HTab("时尚"));  
  16.         Selected.add(new HTab("体育"));  
  17.     }  
  18.     /*** 
  19.      * 获得头部tab的所有项 
  20.      */  
  21.     public static List<HTab> getSelected() {  
  22.         return Selected;  
  23.     }  
  24.   
  25. }  
碎片类
OneFm1.java
[java] view plain copy
 print?
  1. package com.gjn.mynavigation;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.annotation.Nullable;  
  5. import android.support.v4.app.Fragment;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.view.ViewGroup;  
  9. import android.widget.TextView;  
  10.   
  11. public class OneFm1 extends Fragment {  
  12.   
  13.     private String name;  
  14.   
  15.     @Override  
  16.     public void setArguments(Bundle args) {  
  17.         name = args.getString("name");  
  18.     }  
  19.   
  20.     @Override  
  21.     public View onCreateView(LayoutInflater inflater,  
  22.             @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
  23.         View view = inflater.inflate(R.layout.fragment, container,false);  
  24.         ((TextView) view.findViewById(R.id.fm_text)).setText(name);  
  25.         return view;  
  26.     }  
  27.   
  28. }  
这样就把顶部的导航栏加入到了第一个fragment里面并且实现了切换功能

最后把fragment.xml贴下,就是每个碎片最默认的显示页面罢了

[java] view plain copy
 print?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:gravity="center"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <TextView  
  9.         android:id="@+id/fm_text"  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content"  
  12.         android:text="Large Text"  
  13.         android:textAppearance="?android:attr/textAppearanceLarge" />  
  14.   
  15. </LinearLayout>  

总结:

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

0 0
原创粉丝点击