Android ViewPager 实现 TabHost 的效果

经过了前三个范例,我几乎对使用 Android 实现 今日头条 滑动效果失去了耐心了,决定自己定制一个了


不过, ViewPager 本身的功能是非常棒的,我们要定制的也就是 PagerTabStrip,姑且,我们称之为 MsPagerTabStrip 吧

MsPagerStrip

我们先来看看 MsPagerStrip 长的啥样

布局

我们可以把布局分为两大块

  1. 标题栏,有多少个滑动页面就有多少个 TextView,且标题栏不会动
  2. 下划线指示器,有一个背景色,然后是一个 View 会随着滑动而滑动

对于这种布局,我们最喜欢使用的就是 LinearLayout

  1. 顶部一个 LinearLayout ,包着三个 TextView,weight 属性都为 1
  2. 下面跟着一个导轨 View 和一个滑块的 View
  3. 最底下是 ViewPager,我们会使用到它的两个属性

    1. android:flipInterval 指定 View 动画间的时间间隔的
    2. persistentDrawingCache 设置控件的绘制缓存策略

    可选值有四个,可以同时用多个,多个之间用 | 分割

    值 说明
    none 不在内存中保存绘图缓存
    animation 只保存动画绘图缓存
    scrolling 只保存滚动效果绘图缓存
    all 所有的绘图缓存都应该保存在内存中

动画

布局讲完了,我们就来看看动画

滑动的时候,滑块会从指定位置滑到下一个位置

  1. 首先我们需要将整个滑动区域分成 N 段,每一段的长度等于 屏幕总宽度 / n

    因为我们只有三个页面,所以有 n=3

  2. 确定滑块的宽度,刚好也等于 屏幕总宽度 / n

  3. 确定每次滑动移动的距离,其实算起来,也等于自身的宽度,只是有正有负 length

  4. 因为我们使用的是 TranslateAnimation 动画,它很简单,只要我们传递起始坐标和终点坐标即可

  5. 我们的滑动都是水平滑动,所以 y 轴的坐标可以忽略

  6. 动画的坐标系都是以 View 的左上角为起始点的

  7. 所以要确定当前的 x 坐标就只需要 (index * length) 即可 ( index 从 0 开始)

  8. 终点的 x 坐标也很简单还是 (index * length) ,这个你可以通过代码来看更容易

  9. 确定每次移动的时间,其实等于 ViewPager 切换页面的时间

实现

经过上面的分析,我们就可以开始实现了

动画方面,因为我们还没学到,所以你可以直接忽略,或者后面再回来看看

  1. 复用 Android ViewPager 页面切换组件 3 中的 demo

  2. 修改 activity_main.xml 添加整体的布局

    <?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/LinearLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="44dp"
            android:background="#FFFFFF">
    
            <TextView
                android:id="@+id/title_one"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1.0"
                android:gravity="center"
                android:text="科技"
                android:textColor="#000000" />
    
            <TextView
                android:id="@+id/title_two"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1.0"
                android:gravity="center"
                android:text="电影"
                android:textColor="#000000" />
    
            <TextView
                android:id="@+id/title_three"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1.0"
                android:gravity="center"
                android:text="小说"
                android:textColor="#000000" />
        </LinearLayout>
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:background="#dddddd"
            android:layout_height="4dp" >
            <View
                android:id="@+id/slider"
                android:background="#333333"
                android:layout_width="32dp"
                android:layout_height="fill_parent" />
        </RelativeLayout>
    
        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_gravity="center"
            android:layout_weight="1.0"
            android:flipInterval="30"
            android:persistentDrawingCache="animation" />
    
    </LinearLayout>
    
  3. 修改 MsPagerAdapter.java

    package cn.twle.android.viewpager;
    
    import android.support.v4.view.PagerAdapter;
    
    import android.view.View;
    import android.view.ViewGroup;
    
    import java.util.ArrayList;
    
    public class MsPagerAdapter extends PagerAdapter {
    
        private ArrayList<View> mData;
    
        public MsPagerAdapter() {
        }
    
        public MsPagerAdapter(ArrayList<View> view_list) {
            super();
            this.mData = view_list;
        }
    
        @Override
        public int getCount() {
            return mData.size();
        }
    
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }
    
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            container.addView(mData.get(position));
            return mData.get(position);
        }
    
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView(mData.get(position));
        }
    }
    
  4. 修改 MainActivity.java

    package cn.twle.android.viewpager;
    
    import android.graphics.Matrix;
    import android.os.Bundle;
    import android.support.v4.view.ViewPager;
    import android.support.v7.app.AppCompatActivity;
    import android.util.DisplayMetrics;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.animation.Animation;
    import android.view.animation.TranslateAnimation;
    import android.widget.TextView;
    
    import java.util.ArrayList;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener,
            ViewPager.OnPageChangeListener {
    
        private ViewPager viewpager;
        private View slider;
        private TextView title_one;
        private TextView title_two;
        private TextView title_three;
    
        private ArrayList<View> listViews;
        private int offset = 0;//移动条图片的偏移量
        private int currIndex = 0;//当前页面的编号
        private int bmpWidth;// 移动条图片的长度
        private int one = 0; //移动条滑动一页的距离
        private int two = 0; //滑动条移动两页的距离
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            viewpager = (ViewPager) findViewById(R.id.viewpager);
            title_one = (TextView) findViewById(R.id.title_one);
            title_two = (TextView) findViewById(R.id.title_two);
            title_three = (TextView) findViewById(R.id.title_three);
            slider = (View) findViewById(R.id.slider);
    
            //下划线动画的相关设置 -- start
    
            // 屏幕相关
            DisplayMetrics dm = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(dm);
    
            int screenW = dm.widthPixels;// 获取分辨率宽度
    
            bmpWidth = screenW / 3;  // 获取滑块应该的宽度
    
            // 设置滑块宽度
            slider.getLayoutParams().width = bmpWidth;
    
            // 计算初始滑块偏移量
            offset = (screenW / 3 - bmpWidth) / 2;// 计算偏移量
    
            Matrix matrix = new Matrix();
            matrix.postTranslate(offset, 0);
    
            //移动的距离
            one = offset * 2 + bmpWidth;// 移动一页的偏移量,比如1->2,或者2->3
            two = one * 2;// 移动两页的偏移量,比如1直接跳3
    
            // 往 ViewPager 填充 View,同时设置点击事件与页面切换事件
            listViews = new ArrayList<View>();
            LayoutInflater mInflater = getLayoutInflater();
            listViews.add(mInflater.inflate(R.layout.view_one, null, false));
            listViews.add(mInflater.inflate(R.layout.view_two, null, false));
            listViews.add(mInflater.inflate(R.layout.view_three, null, false));
    
            viewpager.setAdapter(new MsPagerAdapter(listViews));
            viewpager.setCurrentItem(0);          //设置ViewPager当前页,从0开始算
    
            title_one.setOnClickListener(this);
            title_two.setOnClickListener(this);
            title_three.setOnClickListener(this);
    
            viewpager.addOnPageChangeListener(this);
        }
    
        @Override
        public void onClick(View v) {
    
            switch (v.getId()) {
                case R.id.title_one:
                    viewpager.setCurrentItem(0);
                    break;
                case R.id.title_two:
                    viewpager.setCurrentItem(1);
                    break;
                case R.id.title_three:
                    viewpager.setCurrentItem(2);
                    break;
            }
        }
    
        @Override
        public void onPageSelected(int index) {
    
            int fromX = currIndex * bmpWidth;
    
            int toX = index * bmpWidth;
    
            Animation animation =  new TranslateAnimation(fromX, toX, 0, 0);
    
            currIndex = index;
            animation.setFillAfter(true);// true表示图片停在动画结束位置
            animation.setDuration(300); //设置动画时间为300毫秒
            slider.startAnimation(animation);//开始动画
        }
    
        @Override
        public void onPageScrollStateChanged(int i) {
    
        }
    
        @Override
        public void onPageScrolled(int i, float v, int i1) {
    
        }
    }
    

参考文档

  1. Android ViewPager

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

♥   简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.