Android ViewPager实现滑动切换页面+底部tab点击切换页面(类微信首页)

时间:2021-02-22 23:49:28
目录:
1.实现功能概述
2.代码实现

1.实现功能概述
实现了滑动更换页面同时切换底部Tab的图标、文字的颜色,同时也支持点击底部Tab达到切换页面的效果,有点类似微信首页布局
外带实现toolbar overflow菜单显示图标。

2.代码实现

2.1 效果截图(资源来源于网络,做学习所用若有不妥指出,反正我也改不了)

Android ViewPager实现滑动切换页面+底部tab点击切换页面(类微信首页)Android ViewPager实现滑动切换页面+底部tab点击切换页面(类微信首页)Android ViewPager实现滑动切换页面+底部tab点击切换页面(类微信首页)Android ViewPager实现滑动切换页面+底部tab点击切换页面(类微信首页)

2.2 主布局actvity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:toolbar="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.viewpager.MainActivity">
<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    toolbar:popupTheme="@style/OverflowTheme"
    android:layout_width="match_parent"
    android:background="@color/customColorPrimary"
    android:layout_height="?actionBarSize">


</android.support.v7.widget.Toolbar>
<android.support.v4.view.ViewPager
    android:layout_weight="1"
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_above="@+id/bottom_tab_layout">


</android.support.v4.view.ViewPager>
<LinearLayout
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        android:background="#000"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="5dp"
    android:id="@+id/bottom_tab_layout">
    <!--消息tab-->
 <LinearLayout
     android:orientation="vertical"
     android:layout_weight="1"
     android:layout_width="0dp"
     android:id="@+id/msg_layout"
     android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/msg_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/msg_green"/>
     <TextView
         android:id="@+id/msg_tv"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="消息"
         android:layout_gravity="center"
         android:textSize="14sp"
         android:textColor="@color/tabTextColorGreen"/>


</LinearLayout>


    <!--应用tab-->
    <LinearLayout
        android:id="@+id/all_layout"
        android:orientation="vertical"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/all_icon"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/all_white"/>
        <TextView
            android:id="@+id/all_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="应用"
            android:layout_gravity="center"
            android:textSize="14sp"
            android:textColor="@color/tabTextColor"/>
    </LinearLayout>
    <!--折扣tab-->
    <LinearLayout
        android:orientation="vertical"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:id="@+id/sale_layout"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/sale_icon"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/sale"/>
        <TextView
            android:id="@+id/sale_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="折扣"
            android:layout_gravity="center"
            android:textSize="14sp"
            android:textColor="@color/tabTextColor"/>
    </LinearLayout>
    <!--时间线tab-->
    <LinearLayout
        android:id="@+id/timeline_layout"
        android:orientation="vertical"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/timeline_icon"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/timeline_white"/>
        <TextView
            android:id="@+id/timeline_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="时间线"
            android:layout_gravity="center"
            android:textSize="14sp"
            android:textColor="@color/tabTextColor"/>
    </LinearLayout>
</LinearLayout>


</LinearLayout>

2.3 菜单布局toolbar_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".MainActivity">
    <!--
    属性用法:
     android:title="":设置自定义action的标题文字,放入action flow中时只显示文字
     android:orderInCategory="":表示action在app bar上显示的顺序,值越小越靠前
     android:icon="":设置显示的图标
     app:showAsAction="ifRoom":设置显示的位置,ifRoom(有空间显示,没空间显示到overflow)
        never(一直显示到overflow),alaways(一直显示在app bar上),
        withText(设置图标和文字一起显示)
     actionViewClass:可以设置替换toolbar中Action Button的控件
    -->
    <!--查询按钮-->
    <item android:id="@+id/action_search"
        android:title="@string/action_search"
        android:orderInCategory="1"
        android:actionViewClass="android.widget.SearchView"
        android:icon="@drawable/search_24"
        app:showAsAction="ifRoom|collapseActionView"
        />
    <!--分享-->
    <item android:id="@+id/action_share"
        android:title="@string/action_share"
        android:orderInCategory="2"
        app:showAsAction="ifRoom|withText"
        android:icon="@drawable/share_24"
        />
    <!--设置-->
    <item android:id="@+id/action_setting"
        android:title="@string/action_setting"
        android:orderInCategory="3"
        app:showAsAction="never|withText"
        android:icon="@drawable/back"
        />
    <!--更多-->
    <item android:id="@+id/action_more"
        android:title="@string/action_more"
        android:orderInCategory="4"
        app:showAsAction="never|withText"
        android:icon="@drawable/share_24b"
        />
</menu>

2.4 主布局类MainActivity.java
package com.example.viewpager;


import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity implements View.OnClickListener,ViewPager.OnPageChangeListener {
    private Toolbar toolbar;
    private ViewPager viewPager;
    private ImageView allImage,msgImage,timelineImage,saleImage;
    private TextView allText,msgText,timelineText,saleText;
    private LinearLayout allLayout,msgLayout,timelineLayout,saleLayout;
    private List<View> pages;
    private CustomViewPagerAdapter customViewPagerAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化控件
        initView();
        //初始化viewpager页面
        initPages();
        //设置总是显示Overflow
        setAlwaysShowOverflow();
        //设置toolbar
        toolbar.setTitle("ViewPager");
        setSupportActionBar(toolbar);
        //toolbar menu设置监听
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                Toast.makeText(MainActivity.this,item.getTitle().toString(),Toast.LENGTH_SHORT).show();
                return false;
            }
        });
        //初始化自定义适配器
        customViewPagerAdapter = new CustomViewPagerAdapter(pages);
        //设置adapter
        viewPager.setAdapter(customViewPagerAdapter);
        //设置监听
        allLayout.setOnClickListener(this);
        msgLayout.setOnClickListener(this);
        timelineLayout.setOnClickListener(this);
        saleLayout.setOnClickListener(this);
        viewPager.setOnPageChangeListener(this);
    }
    /*
    * 初始化viewpager页面
    * */
    private void initPages() {
        pages = new ArrayList<View>();
        View page01 = View.inflate(MainActivity.this,R.layout.viewpager01,null);
        View page02 = View.inflate(MainActivity.this,R.layout.viewpager02,null);
        View page03 = View.inflate(MainActivity.this,R.layout.viewpager03,null);
        View page04 = View.inflate(MainActivity.this,R.layout.viewpager04,null);
        pages.add(page01);
        pages.add(page02);
        pages.add(page03);
        pages.add(page04);


    }


    /*
    *创建选项菜单
    * */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        Log.d("run","onCreateOptionsMenu");
        //通过menu布局加载器将定义的menu xml适配到overflow显示
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.toolbar_menu,menu);
        //判断menu是否为空,如果不为空则通过反射获取setOptionalIconsVisible()方法
        //并实现overflow菜单显示icon,类似于下面public boolean onMenuOpened(
        // int featureId, Menu menu) {}方法中实现,不过区别在于,他们的执行时间不同。
        if (menu != null)
        {
            //获取MenuBuilder类
            if (menu.getClass().getSimpleName().equals("MenuBuilder"))
            {
                //打印全类名和简单类名,可以看看他们长啥样
                Log.d("debug",menu.getClass().getSimpleName());
                Log.d("debug",menu.getClass().getName());
                try
                {
                    //获取类中的返回值为boolean类型的setOptionalIconsVisible方法
                    Method m = menu.getClass().getDeclaredMethod(
                            "setOptionalIconsVisible", Boolean.TYPE);
                    //设置该方法是可接近的,可操作的
                    m.setAccessible(true);
                    //设置Icon显示
                    m.invoke(menu, true);
                } catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
/*        //获取到添加Action View的菜单项,并设置监听操作,在这里可能和菜单监听事件有冲突,没有进行测试
        MenuItem searchItem = menu.findItem(R.id.action_search);
        //添加action行为
        MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
            @Override
            public boolean onMenuItemActionExpand(MenuItem item) {
                Toast.makeText(MainActivity.this,"你可以搜索啦",Toast.LENGTH_SHORT).show();
                return false;
            }


            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {
                Toast.makeText(MainActivity.this,"你离开了我,宝宝不开心",Toast.LENGTH_SHORT).show();
                return false;
            }
        });*/


        return true;
    }


        /*
        * 继承该方法通过反射实现点击物理Menu键后弹出的菜单显示icon
        * */
        @Override
        public boolean onMenuOpened(int featureId, Menu menu) {
            Log.d("run","onMenuOpened");
            Log.d("param",featureId+"");
            if (menu != null)
            {
                if (menu.getClass().getSimpleName().equals("MenuBuilder"))
                {
                    Log.d("debug",menu.getClass().getSimpleName());
                    Log.d("debug",menu.getClass().getName());
                    try
                    {
                        Method m = menu.getClass().getDeclaredMethod(
                                "setOptionalIconsVisible", Boolean.TYPE);
                        m.setAccessible(true);
                        m.invoke(menu, true);
                    } catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            }
            return super.onMenuOpened(featureId, menu);
        }
    /*
    * 设置一直显示Overflow为了避免有硬件Menu键的时候菜单会从底部弹出
    * */
    public void setAlwaysShowOverflow() {
        try {
            ViewConfiguration config = ViewConfiguration.get(this);
            if (config.hasPermanentMenuKey()) {
                Field menuKeyField = ViewConfiguration.class
                        .getDeclaredField("sHasPermanentMenuKey");
                if (menuKeyField != null) {
                    menuKeyField.setAccessible(true);
                    menuKeyField.setBoolean(config, false);
                    Log.d("setAlwaysShowOverflow", menuKeyField.toString());
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
    /*
        * 初始化控件方法
        * */
    private void initView() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        allImage = (ImageView) findViewById(R.id.all_icon);
        allText = (TextView) findViewById(R.id.all_tv);
        msgImage = (ImageView) findViewById(R.id.msg_icon);
        msgText = (TextView) findViewById(R.id.msg_tv);
        timelineImage = (ImageView) findViewById(R.id.timeline_icon);
        timelineText = (TextView) findViewById(R.id.timeline_tv);
        saleImage = (ImageView) findViewById(R.id.sale_icon);
        saleText = (TextView) findViewById(R.id.sale_tv);
        allLayout = (LinearLayout) findViewById(R.id.all_layout);
        timelineLayout = (LinearLayout) findViewById(R.id.timeline_layout);
        saleLayout = (LinearLayout) findViewById(R.id.sale_layout);
        msgLayout = (LinearLayout) findViewById(R.id.msg_layout);
    }
    /*
    * 实现tab点击监听
    * */
    @Override
    public void onClick(View v) {
        resumeTab();
        switch (v.getId()){
            case R.id.all_layout:
                allImage.setImageResource(R.drawable.all_green);
                allText.setTextColor(getResources().getColor(R.color.tabTextColorGreen));
                viewPager.setCurrentItem(1);
                break;
            case R.id.sale_layout:
                saleImage.setImageResource(R.drawable.sale_green);
                saleText.setTextColor(getResources().getColor(R.color.tabTextColorGreen));
                viewPager.setCurrentItem(2);
                break;
            case R.id.timeline_layout:
                timelineImage.setImageResource(R.drawable.time_green);
                timelineText.setTextColor(getResources().getColor(R.color.tabTextColorGreen));
                viewPager.setCurrentItem(3);
                break;
            case R.id.msg_layout:
                msgImage.setImageResource(R.drawable.msg_green);
                msgText.setTextColor(getResources().getColor(R.color.tabTextColorGreen));
                viewPager.setCurrentItem(0);
                break;
            default:
                break;
        }
    }
    /*
    * 将底部的tab颜色恢复全灰
    * */
    private void resumeTab() {
        allImage.setImageResource(R.drawable.all_white);
        msgImage.setImageResource(R.drawable.msg_white);
        timelineImage.setImageResource(R.drawable.time_white);
        saleImage.setImageResource(R.drawable.sale);
        allText.setTextColor(getResources().getColor(R.color.tabTextColor));
        msgText.setTextColor(getResources().getColor(R.color.tabTextColor));
        timelineText.setTextColor(getResources().getColor(R.color.tabTextColor));
        saleText.setTextColor(getResources().getColor(R.color.tabTextColor));
    }


    /*
    * 继承自ViewPager.OnPageChangeListener接口
    * 实现页面滑动的事件监听
    * */
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {


    }
    /*
    * 继承自ViewPager.OnPageChangeListener接口
    * 实现页面选中后的事件监听
    * */
    @Override
    public void onPageSelected(int position) {
        resumeTab();
        switch (position){
            case 0:
                msgImage.setImageResource(R.drawable.msg_green);
                msgText.setTextColor(getResources().getColor(R.color.tabTextColorGreen));
                break;
            case 1:
                allImage.setImageResource(R.drawable.all_green);
                allText.setTextColor(getResources().getColor(R.color.tabTextColorGreen));
                break;
            case 2:
                saleImage.setImageResource(R.drawable.sale_green);
                saleText.setTextColor(getResources().getColor(R.color.tabTextColorGreen));
                break;
            case 3:
                timelineImage.setImageResource(R.drawable.time_green);
                timelineText.setTextColor(getResources().getColor(R.color.tabTextColorGreen));
                break;
            default:
                break;
        }
    }
    /*
    * 继承自ViewPager.OnPageChangeListener接口
    * 实现页面滑动状态改变的事件监听
    * */
    @Override
    public void onPageScrollStateChanged(int state) {


    }
}

2.5 自定义的adapter类CustomViewPagerAdapter.java
package com.example.viewpager;


import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;


import java.util.List;


/**
 * Created by elimy on 2016-09-11.
 */
public class CustomViewPagerAdapter extends PagerAdapter {
    List<View> pages;
    public CustomViewPagerAdapter(List<View> pages){
        this.pages = pages;
    };
    /*
    * 获取页面数量
    * */
    @Override
    public int getCount() {
        return pages.size();
    }


    /*
    *判断类型是否匹配
    * */
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return object==view;
    }
    /*
    * 加载page
    * */
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = pages.get(position);
        container.addView(view);
        return view;
    }
    /*
    * 移除page
    * */
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(pages.get(position));
    }
}

2.6 viewPager布局viewpager01.java(其他viewpager页面布局类似,就不一一给出了)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/page01_back">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="18sp"
        android:textColor="@color/contentTextColor"
        android:text="你有新消息请注意查收"/>
</RelativeLayout>