Android ViewPager 实现 TabHost 的效果

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


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

MsPagerStrip

我们先来看看 MsPagerStrip 长的啥样

布局

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

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

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

  1. 顶部一个 LinearLayout ,包着三个 TextViewweight 属性都为 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.