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
- <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>
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
This is the xml file for the layout settings of each bottom button
- <?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="home page"
- android:textColor="@color/tab_color" />
- </LinearLayout>
Display effect.
And then the MainActivity code.
The TabDb class is used to set up the resources for data and image switching in the navigation bar.
- 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);
- //Initialize FragmentTabHost
- initHost();
- //Initialize the bottom navigation bar
- initTab();
- //Default selection
- mTabHost.onTabChanged(TabDb.getTabsTxt()[0]);
- }
- private void initTab() {
- String[] tabs = TabDb.getTabsTxt();
- for (int i = 0; i < tabs.length; i++) {
- //New TabSpec
- TabSpec tabSpec = mTabHost.newTabSpec(TabDb.getTabsTxt()[i]);
- //Setting 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);
- //Add TabSpec
- mTabHost.addTab(tabSpec,TabDb.getFramgent()[i],null);
- }
- }
- /***
- * Initialize Host
- */
- private void initHost() {
- mTabHost = (FragmentTabHost) findViewById(R.id.main_tab);
- //Call the setup method to set view
- mTabHost.setup(this, getSupportFragmentManager(),R.id.main_view);
- //Removal of partition lines
- mTabHost.getTabWidget().setDividerDrawable(null);
- //Monitoring events
- mTabHost.setOnTabChangedListener(this);
- }
- @Override
- public void onTabChanged(String arg0) {
- //How many switching interfaces can be obtained from the splitting line
- 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);
- //Modify the current interface button color picture
- 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]);
- }
- }
- }
- }
The following is the TabDb class
So far, the bottom navigation bar is fully implemented.
- package com.gjn.mynavigation;
- public class TabDb {
- /***
- * Get all the bottom items
- */
- public static String[] getTabsTxt() {
- String[] tabs = {"home page","transaction","place","My"};
- return tabs;
- }
- /***
- * Get all the debris
- */
- public static Class[] getFramgent(){
- Class[] cls = {OneFm.class,TwoFm.class,ThreeFm.class,FourFm.class};
- return cls ;
- }
- /***
- * Get all the pictures before clicking
- */
- public static int[] getTabsImg(){
- int[] img = {R.drawable.home1,R.drawable.glod1,R.drawable.xc1,R.drawable.user1};
- return img ;
- }
- /***
- * Get all the clicked pictures
- */
- public static int[] getTabsImgLight(){
- int[] img = {R.drawable.home2,R.drawable.glod2,R.drawable.xc2,R.drawable.user2};
- return img ;
- }
- }
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
Setting the top navigation bar and displaying view
- <?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>
After that, the layout of each item in the navigation bar
tab_rb.xml
It sets the selector file to control the click and non-click status.
- <?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="today" >
- </RadioButton>
tab_rb_selector.xml
Set the display status when clicking and default
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android" >
- <!-- click -->
- <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>
- <!-- default -->
- <item >
- <shape >
- <solid android:color="#fafafa"/>
- </shape>
- </item>
- </selector>
Finally, implement the OneFm class
There are two data classes and one fragment class.
- 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) {
- //Initialize 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);
- //Setting up RadioGroup Click Events
- rg_.setOnCheckedChangeListener(new OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(RadioGroup group, int id) {
- vp_.setCurrentItem(id);
- }
- });
- //Initialize the top navigation bar
- initTab(inflater);
- //Initialize viewpager
- initView();
- }
- /*
- * When the bottom navigation bar is switched, the top settings are not destroyed, resulting in no view reset
- * Bugs that cause data to be cut back to the top page after bottom switching disappear
- * The following settings can be recreated each time view is created
- */
- ViewGroup parent = (ViewGroup) view.getParent();
- if (parent != null) {
- parent.removeView(view);
- }
- return view;
- }
- /***
- * Initialize 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);
- }
- //Setting up the viewpager adapter
- adapter = new OneFmAdapter(getActivity().getSupportFragmentManager(),newsList);
- vp_.setAdapter(adapter);
- //Switching between two viewpager s does not reload
- vp_.setOffscreenPageLimit(2);
- //set default
- vp_.setCurrentItem(0);
- //Setting up viewpager to listen for events
- vp_.setOnPageChangeListener(this);
- }
- /***
- * Initialize Header Navigation Bar
- * @param inflater
- */
- private void initTab(LayoutInflater inflater) {
- List<HTab> hTabs = HTabDb.getSelected();
- for (int i = 0; i < hTabs.size(); i++) {
- //Setting header layout initialization data
- 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);
- //Join RadioGroup
- rg_.addView(rbButton,params);
- }
- //Default Click
- 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);
- }
- /***
- * Page Jump Switch Header Offset Settings
- * @param id
- */
- private void setTab(int id) {
- RadioButton rbButton = (RadioButton) rg_.getChildAt(id);
- //Set the title to be clicked
- rbButton.setChecked(true);
- //Offset setting
- int left = rbButton.getLeft();
- int width = rbButton.getMeasuredWidth();
- DisplayMetrics metrics = new DisplayMetrics();
- getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
- int screenWidth = metrics.widthPixels;
- //Moving distance = left position + half button width - half screen width
- int len = left + width / 2 - screenWidth / 2;
- //move
- hv_.smoothScrollTo(len, 0);
- }
- }
Data class
HTab.Java
HTabDb.java
- package com.gjn.mynavigation;
- /***
- * Header Tab attribute
- *
- */
- 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;
- }
- }
Debris
- 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("today"));
- Selected.add(new HTab("Headlines"));
- Selected.add(new HTab("entertainment"));
- Selected.add(new HTab("Finance"));
- Selected.add(new HTab("Military"));
- Selected.add(new HTab("science and technology"));
- Selected.add(new HTab("fashion"));
- Selected.add(new HTab("Sports"));
- }
- /***
- * Get all items of the header tab
- */
- public static List<HTab> getSelected() {
- return Selected;
- }
- }
OneFm1.java
In this way, the top navigation bar is added to the first fragment and the switching function is implemented.
- 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;
- }
- }
Finally, paste fragment.xml, which is the default display page for each fragment.
- <?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>