Several methods of implementing the menu bar at the bottom of WeChat -- Android Learning Road

sky-mxc summary and reprint: http://blog.csdn.net/mxiaochao?viewmode=contents

Recently, we have summarized several ways to implement the bottom menu similar to WeChat. Here is a summary.

Method to realize

There are many ways to implement it. Here are some of the most common ways to summarize, and add others later.

  • viewPager + RadioGroup
  • viewPager + FragmentTabHost
  • viewpager +TabLayout

viewPager+RadioGroup

I feel that this is the easiest one, so I won't post
the
The corresponding RadioButton can be selected in the monitoring.
When the RadioGroup is selected and changed, the monitoring will also be triggered. After the selected change, set the corresponding pager to be displayed.

FragmentTabHost +viewpager

This method is almost the same as the above method, which is achieved by monitoring.
If only FragmentTabHost is used, it can only achieve the effect of clicking on the tab to switch pages, but not sliding left and right. Combined with viewPager, this effect is just achieved.
Let's take a look at the method often used by FragmentTabHost
- setup( ) Before using addTab, call to set the necessary data such as FragmentManager, Fragment's container id
- addTab() to add a tab
- newTabSpec() to create a new tab
- setCurrentTab() to set the currently displayed tab
- setOnChangeTabListtener to set the tab selection change monitor
- tabHost.getTabWidget( ).setDividerDrawable(null); //Remove the interval line
- common method of Tab:
- setIndicator() can set view and string


main layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_tab_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.skymxc.demo.fragment.TabPagerActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"></android.support.v4.view.ViewPager>

    <android.support.v4.app.FragmentTabHost
        android:id="@+id/tab_host"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></android.support.v4.app.FragmentTabHost>

</LinearLayout>

Framgent does not write layout files for simplicity. Other Fragments are similar to this

public class DiscoverFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        TextView textView = new TextView(getActivity());
        textView.setText("发现");
        textView.setGravity(Gravity.CENTER);
        return textView;
    }
}

The layout image of the tab is relatively simple on the top and the text on the bottom

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_gravity="center"/>
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/selector_font"
        android:text="发现"
        android:layout_gravity="center"/>

</LinearLayout>

selector is basically similar to paste one here

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_selected="true" android:drawable="@mipmap/cb_icon_discover_selected"/>
    <item android:drawable="@mipmap/cb_icon_discover_normal"/>

</selector>

java code
initialize TabHost

    private void initTabHost() {
        tabHost.setup(this,getSupportFragmentManager(), R.id.pager);
        tabHost.getTabWidget().setDividerDrawable(null);
        tabHost.addTab(tabHost.newTabSpec("discover").setIndicator(createView(R.drawable.selector_bg,"发现")), DiscoverFragment.class,null);
        tabHost.addTab(tabHost.newTabSpec("attach").setIndicator(createView(R.drawable.selector_bg_attach,"关注")), AttachFragment.class,null);
        tabHost.addTab(tabHost.newTabSpec("message").setIndicator(createView(R.drawable.selector_bg_message,"消息")), MsgFragment.class,null);
        tabHost.addTab(tabHost.newTabSpec("info").setIndicator(createView(R.drawable.selector_bg_info,"我的")), ContactFragment.class,null);
    }

Initialize the pager and bind the adapter

    /**
     * 初始化 pager 绑定适配器
     */
    private void initPager() {
        fragments = new ArrayList<>();
        fragments.add(new DiscoverFragment());
        fragments.add(new AttachFragment());
        fragments.add(new MsgFragment());
        fragments.add(new ContactFragment());
        FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager(),fragments);
        pager.setAdapter(adapter);
    }

Add listeners to TabHost and pager respectively to achieve linkage

 /**
  * 为TabHost和viewPager 添加监听 让其联动
  */
 private void bindTabAndPager() {
     tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
         /**
          *  tab改变后
          * @param tabId 当前tab的tag
          */
         @Override
         public void onTabChanged(String tabId) {
             log("vonTabChanged:"+tabId);
            int position = tabHost.getCurrentTab();
             pager.setCurrentItem(position,true);
         }
     });

     pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
         /**
          * 页面滑动 触发
          * @param position 当前显得第一个页面的索引,当滑动出现时屏幕就会显示两个pager, 向右滑 position为当前-1(左边的pager就显示出来了),向左滑position为当前(右面就显出来了),
          * @param positionOffset 0-1之间 position的偏移量 从原始位置的偏移量
          * @param positionOffsetPixels 从position偏移的像素值 从原始位置的便宜像素
          */
         @Override
         public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
         log("onPageScrolled=============position:"+position+"====positionOffset:"+positionOffset+"====positionOffsetPixels:"+positionOffsetPixels);
         }

         /**
          * 页面选中后
          * @param position 当前页面的index
          */
         @Override
         public void onPageSelected(int position) {
             tabHost.setCurrentTab(position);
             log("onPageSelected==========:position:"+position);
         }

         /**
          * 页面滑动状态改变时触发
          * @param state 当前滑动状态 共三个状态值
          */
         @Override
         public void onPageScrollStateChanged(int state) {

             String stateStr="";
             switch (state){
                 case ViewPager.SCROLL_STATE_DRAGGING:
                     stateStr="正在拖动";
                     break;
                 case ViewPager.SCROLL_STATE_SETTLING:
                     stateStr="正在去往最终位置 即将到达最终位置";
                     break;
                 case ViewPager.SCROLL_STATE_IDLE:
                     stateStr="滑动停止,当前页面充满屏幕";
                     break;
             }
             log("onPageScrollStateChanged========stateCode:"+state+"====state:"+stateStr);
         }

     });
 }

full code

 public class TabPagerActivity extends AppCompatActivity {

    private static final String TAG ="TabPagerActivity";

    private FragmentTabHost  tabHost;
    private ViewPager pager;
    private List<Fragment> fragments;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tab_pager);
        tabHost = (FragmentTabHost) findViewById(R.id.tab_host);
        pager = (ViewPager) findViewById(R.id.pager);
        //初始化TabHost
        initTabHost();

        //初始化pager
        initPager();

        //添加监听关联TabHost和viewPager
        bindTabAndPager();
    }

    /**
     * 为TabHost和viewPager 添加监听 让其联动
     */
    private void bindTabAndPager() {
        tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
            /**
             *  tab改变后
             * @param tabId 当前tab的tag
             */
            @Override
            public void onTabChanged(String tabId) {
                log("vonTabChanged:"+tabId);
               int position = tabHost.getCurrentTab();
                pager.setCurrentItem(position,true);
            }
        });

        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            /**
             * 页面滑动 触发
             * @param position 当前显得第一个页面的索引,当滑动出现时屏幕就会显示两个pager, 向右滑 position为当前-1(左边的pager就显示出来了),向左滑position为当前(右面就显出来了),
             * @param positionOffset 0-1之间 position的偏移量 从原始位置的偏移量
             * @param positionOffsetPixels 从position偏移的像素值 从原始位置的便宜像素
             */
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            log("onPageScrolled=============position:"+position+"====positionOffset:"+positionOffset+"====positionOffsetPixels:"+positionOffsetPixels);
            }

            /**
             * 页面选中后
             * @param position 当前页面的index
             */
            @Override
            public void onPageSelected(int position) {
                tabHost.setCurrentTab(position);
                log("onPageSelected==========:position:"+position);
            }

            /**
             * 页面滑动状态改变时触发
             * @param state 当前滑动状态 共三个状态值
             */
            @Override
            public void onPageScrollStateChanged(int state) {

                String stateStr="";
                switch (state){
                    case ViewPager.SCROLL_STATE_DRAGGING:
                        stateStr="正在拖动";
                        break;
                    case ViewPager.SCROLL_STATE_SETTLING:
                        stateStr="正在去往最终位置 即将到达最终位置";
                        break;
                    case ViewPager.SCROLL_STATE_IDLE:
                        stateStr="滑动停止,当前页面充满屏幕";
                        break;
                }
                log("onPageScrollStateChanged========stateCode:"+state+"====state:"+stateStr);
            }

        });
    }

    /**
     * 初始化 pager 绑定适配器
     */
    private void initPager() {
        fragments = new ArrayList<>();
        fragments.add(new DiscoverFragment());
        fragments.add(new AttachFragment());
        fragments.add(new MsgFragment());
        fragments.add(new ContactFragment());
        FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager(),fragments);
        pager.setAdapter(adapter);
    }

    /**
     * 初始化 TabHost
     */
    private void initTabHost() {
        tabHost.setup(this,getSupportFragmentManager(), R.id.pager);
        tabHost.getTabWidget().setDividerDrawable(null);
        tabHost.addTab(tabHost.newTabSpec("discover").setIndicator(createView(R.drawable.selector_bg,"发现")), DiscoverFragment.class,null);
        tabHost.addTab(tabHost.newTabSpec("attach").setIndicator(createView(R.drawable.selector_bg_attach,"关注")), AttachFragment.class,null);
        tabHost.addTab(tabHost.newTabSpec("message").setIndicator(createView(R.drawable.selector_bg_message,"消息")), MsgFragment.class,null);
        tabHost.addTab(tabHost.newTabSpec("info").setIndicator(createView(R.drawable.selector_bg_info,"我的")), ContactFragment.class,null);
    }

    /**
     * 返回view
     * @param icon
     * @param tab
     * @return
     */
    private View createView(int icon,String tab){
        View view = getLayoutInflater().inflate(R.layout.fragment_tab_discover,null);
        ImageView imageView = (ImageView) view.findViewById(R.id.icon);
        TextView  title = (TextView) view.findViewById(R.id.title);
        imageView.setImageResource(icon);
        title.setText(tab);
        return  view;
    }

    private void log(String log){
        Log.e(TAG,"="+log+"=");
    }

}

The effect is as follows:
write picture description here



viewpager +TabLayout

TabLayout input design extension package must be imported before use.
TabLayout can automatically associate viewPager. Just specify the associated viewPager for tabLayout.
This is a lot more convenient, but it also has disadvantages. Take the title of viewPager, it is impossible to use a custom view as a tab

Import the design extension package side by side on v7
write picture description here

The layout uses two TabLayouts to achieve automatic association and manual association respectively

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_tab_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.skymxc.demo.fragment.TabLayoutActivity">

    <!-- 使用自动关联-->
    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed"
        app:tabSelectedTextColor="#f0f"
        app:tabIndicatorColor="#f0f"></android.support.design.widget.TabLayout>


    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"></android.support.v4.view.ViewPager>

    <!--通过监听去关联-->
    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout_menu"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed"
        app:tabSelectedTextColor="#ff0"
        app:tabIndicatorColor="#ff0"></android.support.design.widget.TabLayout>
</LinearLayout>

Initialize the automatically associated tab and bind it to viewPager


    private void initTabLayoutAndPager() {
        //关联 viewPager 使用关联后 tab就会自动去获取pager的title,使用addTab就会无效
        tabLayout.setupWithViewPager(pager);

        fragments = new ArrayList<>();
        fragments.add(new DiscoverFragment());
        fragments.add(new AttachFragment());
        fragments.add(new MsgFragment());
        fragments.add(new ContactFragment());
        adapter = new FragmentAdapter(getSupportFragmentManager(),fragments);
        pager.setAdapter(adapter);
    }

The layout of the tabs is the same as above.



Adding view to TabLayout automatically associates it with no use

        tabLayoutMenu.addTab(tabLayoutMenu.newTab().setCustomView(createView(R.drawable.selector_bg,"发现")));
        tabLayoutMenu.addTab(tabLayoutMenu.newTab().setCustomView(createView(R.drawable.selector_bg_attach,"关注")));
        tabLayoutMenu.addTab(tabLayoutMenu.newTab().setCustomView(createView(R.drawable.selector_bg_message,"消息")));
        tabLayoutMenu.addTab(tabLayoutMenu.newTab().setCustomView(createView(R.drawable.selector_bg_info,"我的")));
        tabLayoutMenu.setSelectedTabIndicatorHeight(0);//去除指示器

Set the monitoring of viewPager and the monitoring of TabLayout to achieve linkage

        tabLayoutMenu.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {

            /**
             * 选中tab后触发
             * @param tab 选中的tab
             */
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                //与pager 关联
                pager.setCurrentItem(tab.getPosition(),true);
            }

            /**
             * 退出选中状态时触发
             * @param tab 退出选中的tab
             */
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            /**
             * 重复选择时触发
             * @param tab 被 选择的tab
             */
            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                //关联 TabLayout
                tabLayoutMenu.getTabAt(position).select();
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

full code

package com.skymxc.demo.fragment;

import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.skymxc.demo.fragment.adapter.FragmentAdapter;
import com.skymxc.demo.fragment.fragment.AttachFragment;
import com.skymxc.demo.fragment.fragment.ContactFragment;
import com.skymxc.demo.fragment.fragment.DiscoverFragment;
import com.skymxc.demo.fragment.fragment.MsgFragment;

import java.util.ArrayList;
import java.util.List;

public class TabLayoutActivity extends AppCompatActivity {

    private TabLayout tabLayout;
    private ViewPager pager;
    private TabLayout tabLayoutMenu;

    private FragmentAdapter adapter ;
    private List<Fragment> fragments;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tab_layout);
        tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        pager = (ViewPager) findViewById(R.id.container);
        tabLayoutMenu = (TabLayout) findViewById(R.id.tab_layout_menu);
        initTabLayoutAndPager();


        //想使用自己的布局就得 通过 监听进行关联
        bindPagerAndTab();
    }

    private void bindPagerAndTab() {
        tabLayoutMenu.addTab(tabLayoutMenu.newTab().setCustomView(createView(R.drawable.selector_bg,"发现")));
        tabLayoutMenu.addTab(tabLayoutMenu.newTab().setCustomView(createView(R.drawable.selector_bg_attach,"关注")));
        tabLayoutMenu.addTab(tabLayoutMenu.newTab().setCustomView(createView(R.drawable.selector_bg_message,"消息")));
        tabLayoutMenu.addTab(tabLayoutMenu.newTab().setCustomView(createView(R.drawable.selector_bg_info,"我的")));
        tabLayoutMenu.setSelectedTabIndicatorHeight(0);//去除指示器

        tabLayoutMenu.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {

            /**
             * 选中tab后触发
             * @param tab 选中的tab
             */
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                //与pager 关联
                pager.setCurrentItem(tab.getPosition(),true);
            }

            /**
             * 退出选中状态时触发
             * @param tab 退出选中的tab
             */
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            /**
             * 重复选择时触发
             * @param tab 被 选择的tab
             */
            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                //关联 TabLayout
                tabLayoutMenu.getTabAt(position).select();
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    private void initTabLayoutAndPager() {
        //关联 viewPager 使用关联后 tab就会自动去获取pager的title,使用addTab就会无效
        tabLayout.setupWithViewPager(pager);

        fragments = new ArrayList<>();
        fragments.add(new DiscoverFragment());
        fragments.add(new AttachFragment());
        fragments.add(new MsgFragment());
        fragments.add(new ContactFragment());
        adapter = new FragmentAdapter(getSupportFragmentManager(),fragments);
        pager.setAdapter(adapter);
    }


    private View createView(int icon, String tab){
        View view = getLayoutInflater().inflate(R.layout.fragment_tab_discover,null);
        ImageView imageView = (ImageView) view.findViewById(R.id.icon);
        TextView title = (TextView) view.findViewById(R.id.title);
        imageView.setImageResource(icon);
        title.setText(tab);
        return  view;
    }
}

renderings
write picture description here



Paste the viewPager adapter here

public class FragmentAdapter extends FragmentPagerAdapter {
    List<Fragment> fragments ;
    private String[] titles = new String[]{"发现","关注","消息","我的"};
    public FragmentAdapter(FragmentManager fm,List<Fragment> fragments) {
        super(fm);
        this.fragments =fragments;
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments ==null ?0:fragments.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles[position];
    }
}

At present, I have summarized these methods and thought of other methods and then summarized the github
about this Demo: https://github.com/sky-mxc/AndroidDemo/tree/master/fragment

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325384191&siteId=291194637