App界面Tab选项卡之ViewPager

时间:2021-12-12 18:37:57

说到现在app的Tab选项卡,随处可见,微信、QQ音乐数不胜数,因此了解并掌握实现原理显得尤为重要。原理并不是特别的复杂,初学android一定要多动手,多敲代码。今天就说说App界面Tab选项卡之ViewPager。


先说说ViewPager,附加于android-support-v4.jar中,用于实现view之间的相互切换,一般新建时便会自动生成,在xml中应用须输入完整路径,例如:

<android.support.v4.view.ViewPager
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

ViewPager可以设置专门的PagerAdapter,用于填充用于滑动的view集合,还可以配合OnPageChangeListener一起使用,监听切换视图的状态。更具体详细信息自行google,好了,开始今天的任务。

我们的目标是实现类似微信主界面那样的Tab选项卡,效果图如下图:
App界面Tab选项卡之ViewPager

有了目标,那么就开始做准备工作了,很明显,我们需要一个title_bar:

<?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="45dp" android:background="@drawable/bar_bg" android:orientation="vertical">

    <TextView  android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="微信" android:textColor="#fff" android:textSize="20sp" />

</LinearLayout>

还有一个bottom_bar,用于ViewPager的Indicator:

<?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="55dp" android:background="@drawable/bar_bg" android:orientation="horizontal">

    <LinearLayout  android:id="@+id/tab_0" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical">

        <ImageView  android:id="@+id/img_0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/tab_weixin_pressed" />

        <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="微信" android:textColor="#fff" />

    </LinearLayout>

    <LinearLayout  android:id="@+id/tab_1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical">

        <ImageView  android:id="@+id/img_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/tab_find_frd_normal" />

        <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="朋友" android:textColor="#fff" />

    </LinearLayout>

    <LinearLayout  android:id="@+id/tab_2" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical">

        <ImageView  android:id="@+id/img_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/tab_address_normal" />

        <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="通讯录" android:textColor="#fff" />

    </LinearLayout>

    <LinearLayout  android:id="@+id/tab_3" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical">

        <ImageView  android:id="@+id/img_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/tab_settings_normal" />

        <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="设置" android:textColor="#fff" />

    </LinearLayout>

</LinearLayout>

还有四个内容页,我就不贴了,最后是主界面:

<?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">

    <include layout="@layout/title_bar" />

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

    <include layout="@layout/bottom_bar" />
</LinearLayout>

唯一的技巧可能就是用了include,开始编写MainActivity代码段:

package com.cjt_pc.viewpager;

import android.app.Activity;
import android.media.Image;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;

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

/** * Created by cjt-pc on 2015/8/20. * Email:879309896@qq.com */
public class MainActivity extends Activity implements View.OnClickListener {

    private ViewPager viewPager;
    // 填充ViewPager的页面集合
    private List<View> views = new ArrayList<>();
    // ViewPager指示器布局
    private LinearLayout llIndicator0, llIndicator1, llIndicator2, llIndicator3;
    private ImageView ivImg0, ivImg1, ivImg2, ivImg3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initWidget();
        initViewPager();
    }

    private void initViewPager() {
        initViews();
        viewPager.setAdapter(new PagerAdapter() {
            @Override
            public int getCount() {
                return views.size();
            }

            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view == object;
            }

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                View view = views.get(position);
                container.addView(view);
                return view;
            }

            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView(views.get(position));
            }
        });
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            // 只有当前select项发生改变才会调用该方法,初始化ViewPager时默认选中第一项,但不会触发该方法
            @Override
            public void onPageSelected(int position) {
                resetIndicator();
                switch (position) {
                    case 0:
                        ivImg0.setImageResource(R.mipmap.tab_weixin_pressed);
                        break;
                    case 1:
                        ivImg1.setImageResource(R.mipmap.tab_find_frd_pressed);
                        break;
                    case 2:
                        ivImg2.setImageResource(R.mipmap.tab_address_pressed);
                        break;
                    case 3:
                        ivImg3.setImageResource(R.mipmap.tab_settings_pressed);
                        break;
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    private void initWidget() {
        viewPager = (ViewPager) findViewById(R.id.view_pager);
        llIndicator0 = (LinearLayout) findViewById(R.id.tab_0);
        llIndicator0.setOnClickListener(this);
        llIndicator1 = (LinearLayout) findViewById(R.id.tab_1);
        llIndicator1.setOnClickListener(this);
        llIndicator2 = (LinearLayout) findViewById(R.id.tab_2);
        llIndicator2.setOnClickListener(this);
        llIndicator3 = (LinearLayout) findViewById(R.id.tab_3);
        llIndicator3.setOnClickListener(this);
        ivImg0 = (ImageView) findViewById(R.id.img_0);
        ivImg1 = (ImageView) findViewById(R.id.img_1);
        ivImg2 = (ImageView) findViewById(R.id.img_2);
        ivImg3 = (ImageView) findViewById(R.id.img_3);
    }

    private void initViews() {
        View view0 = getLayoutInflater().inflate(R.layout.content_0, null);
        View view1 = getLayoutInflater().inflate(R.layout.content_1, null);
        View view2 = getLayoutInflater().inflate(R.layout.content_2, null);
        View view3 = getLayoutInflater().inflate(R.layout.content_3, null);
        views.add(view0);
        views.add(view1);
        views.add(view2);
        views.add(view3);
    }

    @Override
    public void onClick(View view) {
        // 若点击的indicator项与viewpager的项相等,则不采取任何操作
        int position = viewPager.getCurrentItem();
        switch (view.getId()) {
            case R.id.tab_0:
                if (position != 0) {
                    resetIndicator();
                    viewPager.setCurrentItem(0);
                }
                break;
            case R.id.tab_1:
                if (position != 1) {
                    resetIndicator();
                    viewPager.setCurrentItem(1);
                }
                break;
            case R.id.tab_2:
                if (position != 2) {
                    resetIndicator();
                    viewPager.setCurrentItem(2);
                }
                break;
            case R.id.tab_3:
                if (position != 3) {
                    resetIndicator();
                    viewPager.setCurrentItem(3);
                }
                break;
        }
    }

    private void resetIndicator() {
        ivImg0.setImageResource(R.mipmap.tab_weixin_normal);
        ivImg1.setImageResource(R.mipmap.tab_find_frd_normal);
        ivImg2.setImageResource(R.mipmap.tab_address_normal);
        ivImg3.setImageResource(R.mipmap.tab_settings_normal);
    }
}

几个关键位置说一下,onPageChangeListener的三个抽象方法,各有千秋:

  1. onPageScrolled:视图滚动式触发
  2. onPageSelected:手指抬起viewPager.getCurrentItem()发生改变时触发,初始化时默认选中0项,但并不会触发该方法
  3. onPageScrollStateChanged:viewPager滑动状态改变时触发,有三个参数,SCROLL_STATE_DRAGGING;SCROLL_STATE_IDLE;SCROLL_STATE_SETTLING;分别是手指拖拽、视图停止滚动、手指抬起视图开始滑动到完全显示某一页面的过程。

所以会在bottom.xml为bottom首项img设置初始值为pressed,因为页面index不发生改变onPageSelected不会触发,所以在onClick中会加入判断。

大概就是这样了,项目源码地址:http://download.csdn.net/detail/qq_15002323/9033803