Android - Implementing Top + Bottom Dual Navigation Interface Function

Keywords: Android xml Fragment Java

Recently, I want to get a dual navigation function. After checking a lot of information, I finally realized the function. Here I can even take a few notes for myself.

Let's see the effect first.


So it's starting to come true!

The bottom navigation bar I chose to use FragmentTabHost+Fragment to achieve, which I think is very useful, and the amount of code is not much.

First, start with activity_main.xml

  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>  

Among them, I was directly pulling the view so it was formed by FragmentTab Host.

It can also be written directly in an xml file

<Android.support.v4.view.FragmentTabHost >

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

This xml file adds a tab view to a view to display the fragments, and tab to place the number of bottom buttons

Then tab_foot.xml

  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="home page"  
  21.         android:textColor="@color/tab_color" />  
  22.   
  23. </LinearLayout>  
This is the xml file for the layout settings of each bottom button

Display effect.

And then the MainActivity code.


  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.         //Initialize FragmentTabHost  
  25.         initHost();  
  26.         //Initialize the bottom navigation bar  
  27.         initTab();  
  28.         //Default selection  
  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.             //New TabSpec  
  36.             TabSpec tabSpec = mTabHost.newTabSpec(TabDb.getTabsTxt()[i]);  
  37.             //Setting 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.             //Add TabSpec  
  43.             mTabHost.addTab(tabSpec,TabDb.getFramgent()[i],null);  
  44.         }  
  45.     }  
  46.     /*** 
  47.      * Initialize Host 
  48.      */  
  49.     private void initHost() {  
  50.         mTabHost = (FragmentTabHost) findViewById(R.id.main_tab);  
  51.         //Call the setup method to set view  
  52.         mTabHost.setup(this, getSupportFragmentManager(),R.id.main_view);  
  53.         //Removal of partition lines  
  54.         mTabHost.getTabWidget().setDividerDrawable(null);  
  55.         //Monitoring events  
  56.         mTabHost.setOnTabChangedListener(this);  
  57.     }  
  58.   
  59.     @Override  
  60.     public void onTabChanged(String arg0) {  
  61.         //How many switching interfaces can be obtained from the splitting line  
  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.             //Modify the current interface button color picture  
  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. }  
The TabDb class is used to set up the resources for data and image switching in the navigation bar.
The following is the TabDb class

  1. package com.gjn.mynavigation;  
  2.   
  3. public class TabDb {  
  4.     /*** 
  5.      * Get all the bottom items 
  6.      */  
  7.     public static String[] getTabsTxt() {  
  8.         String[] tabs = {"home page","transaction","place","My"};  
  9.         return tabs;  
  10.     }  
  11.     /*** 
  12.      * Get all the debris 
  13.      */  
  14.     public static Class[] getFramgent(){  
  15.         Class[] cls = {OneFm.class,TwoFm.class,ThreeFm.class,FourFm.class};  
  16.         return cls ;  
  17.     }  
  18.     /*** 
  19.      * Get all the pictures before clicking 
  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.      * Get all the clicked pictures 
  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. }  
So far, the bottom navigation bar is fully implemented.


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

Now to implement the top navigation bar, I've seen a lot of things that are finally implemented using RadioGroup+ViewPager

First, design an xml layout for the first fragment

fm_one.xml

  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>  
Setting the top navigation bar and displaying view
After that, the layout of each item in the navigation bar

tab_rb.xml

  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="today" >  
  12. </RadioButton>  
It sets the selector file to control the click and non-click status.

tab_rb_selector.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android" >  
  3.     <!-- click -->  
  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.     <!-- default -->  
  19.     <item >  
  20.         <shape >  
  21.             <solid android:color="#fafafa"/>  
  22.         </shape>  
  23.     </item>  
  24. </selector>  
Set the display status when clicking and default
Finally, implement the OneFm class

  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.             //Initialize 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.             //Setting up RadioGroup Click Events  
  40.             rg_.setOnCheckedChangeListener(new OnCheckedChangeListener() {  
  41.                   
  42.                 @Override  
  43.                 public void onCheckedChanged(RadioGroup group, int id) {  
  44.                     vp_.setCurrentItem(id);  
  45.                 }  
  46.             });  
  47.             //Initialize the top navigation bar  
  48.             initTab(inflater);  
  49.             //Initialize viewpager  
  50.             initView();  
  51.         }  
  52.         /* 
  53.          * When the bottom navigation bar is switched, the top settings are not destroyed, resulting in no view reset 
  54.          * Bugs that cause data to be cut back to the top page after bottom switching disappear 
  55.          * The following settings can be recreated each time view is created 
  56.         */  
  57.         ViewGroup parent = (ViewGroup) view.getParent();  
  58.         if (parent != null) {  
  59.             parent.removeView(view);  
  60.         }  
  61.         return view;  
  62.     }  
  63.     /*** 
  64.      * Initialize 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.         //Setting up the viewpager adapter  
  76.         adapter = new OneFmAdapter(getActivity().getSupportFragmentManager(),newsList);  
  77.         vp_.setAdapter(adapter);  
  78.         //Switching between two viewpager s does not reload  
  79.         vp_.setOffscreenPageLimit(2);  
  80.         //set default  
  81.         vp_.setCurrentItem(0);  
  82.         //Setting up viewpager to listen for events  
  83.         vp_.setOnPageChangeListener(this);  
  84.     }  
  85.     /*** 
  86.      * Initialize Header Navigation Bar 
  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.             //Setting header layout initialization data  
  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.             //Join RadioGroup  
  99.             rg_.addView(rbButton,params);  
  100.         }  
  101.         //Default Click  
  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.      * Page Jump Switch Header Offset Settings 
  118.      * @param id 
  119.      */  
  120.     private void setTab(int id) {  
  121.         RadioButton rbButton = (RadioButton) rg_.getChildAt(id);  
  122.         //Set the title to be clicked  
  123.         rbButton.setChecked(true);  
  124.         //Offset setting  
  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.         //Moving distance = left position + half button width - half screen width  
  131.         int len = left + width / 2 - screenWidth / 2;  
  132.         //move  
  133.         hv_.smoothScrollTo(len, 0);  
  134.     }  
  135. }  
There are two data classes and one fragment class.

Data class

HTab.Java

  1. package com.gjn.mynavigation;  
  2.   
  3. /*** 
  4.  * Header Tab attribute 
  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
  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("today"));  
  10.         Selected.add(new HTab("Headlines"));  
  11.         Selected.add(new HTab("entertainment"));  
  12.         Selected.add(new HTab("Finance"));  
  13.         Selected.add(new HTab("Military"));  
  14.         Selected.add(new HTab("science and technology"));  
  15.         Selected.add(new HTab("fashion"));  
  16.         Selected.add(new HTab("Sports"));  
  17.     }  
  18.     /*** 
  19.      * Get all items of the header tab 
  20.      */  
  21.     public static List<HTab> getSelected() {  
  22.         return Selected;  
  23.     }  
  24.   
  25. }  
Debris
OneFm1.java
  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. }  
In this way, the top navigation bar is added to the first fragment and the switching function is implemented.

Finally, paste fragment.xml, which is the default display page for each fragment.

  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>  

Posted by mhodge87 on Fri, 07 Jun 2019 18:21:40 -0700