美文网首页
ViewPager滚动功能

ViewPager滚动功能

作者: 其实我很菜啊 | 来源:发表于2017-10-14 16:57 被阅读0次

在我们日常生活使用的App中,有很多都带有图片的滚动功能,常见的有网易新闻、今日头条就会使用ViewPager来展示新闻图片。今天我们就来学习一下ViewPager是我们的App更强大美观。
首先看一下今天要实现的效果图

效果图一.png 效果图二.png

我只做四张图片进行测试,效果包括图片的展示滑动左下角的标题以及右下角的指示点。
现在我们来看一下实现此功能的代码。首先是布局文件activity_main.xml

<?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.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"  />

    <LinearLayout
        android:id="@+id/ll_dots"
        android:gravity="center_horizontal"
        android:layout_alignBottom="@+id/viewpager"
        android:layout_alignRight="@+id/viewpager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </LinearLayout>


</RelativeLayout>

主布局中包括了ViewPager以及LinearLayout两个布局,线性布局的作用是在右下角展示指示点。
展示新闻图片及标题的布局文件vp_item.xml

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

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_height="wrap_content" />

</RelativeLayout>

这里我们使用相对布局,layout_alignParentBottom="ture"作用是将TextView即新闻标题放在容器的最低端。
紧接着看一下存放新闻内容的Bean,包括标题及图片不做过多解释。

package com.example.lenovo.viewpager.Bean;

/**
 * Created by lenovo on 2017/10/12.
 */

public class News {
    private String title;
    private int    resId;

    public News(){
        super();
    }

    public News(String title, int resId) {
        this.title = title;
        this.resId = resId;
    }

    @Override
    public String toString() {
        return "News{" +
                "title='" + title + '\'' +
                ", resId=" + resId +
                '}';
    }


    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getResId() {
        return resId;
    }

    public void setResId(int resId) {
        this.resId = resId;
    }
}

接下来才是实现功能的代码,自定义一个适配器它继承PagerAdapter

package com.example.lenovo.viewpager.adapter;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.lenovo.viewpager.Bean.News;
import com.example.lenovo.viewpager.R;

import java.util.ArrayList;

/**
 * Created by lenovo on 2017/10/12.
 */

public class MyPagerAdapter extends PagerAdapter {

    private Context context;
    private ArrayList<News> NewsList;

    public MyPagerAdapter(Context context, ArrayList<News> NewsList) {
        this.context = context;
        this.NewsList = NewsList;
    }

    /**
     * 获取要展示图片的个数
     *
     */
    @Override
    public int getCount() {
        return NewsList.size();
    }
    
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view==object;
    }

    /**
    *初始页面
    */
    @Override
    public Object instantiateItem(ViewGroup container, int position) {

        View view=View.inflate(context, R.layout.vp_item,null);

        ImageView imageView=view.findViewById(R.id.imageview);
        TextView  textView=view.findViewById(R.id.tv_title);

        imageView.setImageResource(NewsList.get(position).getResId());
        textView.setText(NewsList.get(position).getTitle());

        container.addView(view);

        return view;
    }
    /**
     *当页面滑动时执行
     */
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }
}

当你实现一个PagerAdapter时,你至少需要重写下面的几个方法:

  • instantiateItem(ViewGroup, int)
  • destroyItem(ViewGroup, int, Object)
  • getCount()
  • isViewFromObject(View, Object)

PagerAdapter比很多AdapterView的适配器更加通用。ViewPager使用回调机制来显示一个更新步骤,而不是直接使用视图回收机制。如果需要时,PagerAdapter也可以实现视图回收方法,或者直接使用一种更加巧妙的方法来管理页面,比如直接使用能够管理自身事务的Fragment。
ViewPager并不直接管理页面,而是通过一个key将每个页面联系起来。这个key用来跟踪和唯一标识一个给定的页面,且该key独立于adapter之外。PagerAdapter中的startUpdate(ViewGroup)方法一旦被执行,就说明ViewPager的内容即将开始改变。紧接着,instantiateItem(ViewGroup, int)和/或destroyItem(ViewGroup, int, Object)方法将会被执行,然后finishUpdate(ViewGroup)的执行就意味着这一次刷新的完成。当finishUpdate(ViewGroup)方法执行完时,与instantiateItem(ViewGroup, int)方法返回的key相对应的视图将会被加入到父ViewGroup中,而与传递给destroyItem(ViewGroup, int, Object)方法的key相对应的视图将会被移除。isViewFromObject(View, Object)方法则判断一个视图是否与一个给定的key相对应。
一个简单的PagerAdapter会选择将视图本身作为key,在将视图创建并加入父ViewGroup之后通过instantiateItem(ViewGroup, int)返回。这种情况下,destroyItem(ViewGroup, int, Object) 的实现方法只需要将View从ViewGroup中移除即可,而isViewFromObject(View, Object)的实现方法可以直接写成return view == object;。
PagerAdapter支持数据集的改变。数据集的改变必须放在主线程中,并且在结束时调用notifyDataSetChanged()方法,这与通过BaseAdapter适配的AdapterView类似。一个数据集的改变包含了页面的添加、移除或者位移。ViewPager可以通过在适配器中实现getItemPosition(Object)方法来保持当前页面处于运行状态。
以上内容是官网的解释是不是一头雾水
其实简单来说就是:
instantiateItem(ViewGroup, int)负责初始化指定位置的页面,并且需要返回当前页面本身(其实不一定要View本身,只要是能唯一标识该页面的key都可以,不过初学者一般就先用View本身作为key就可以啦);
destroyItem(ViewGroup, int, Object)负责移除指定位置的页面;
isViewFromObject(View, Object)里直接写“return view == object;”即可(当然,如果你在instantiateItem(ViewGroup, int)里返回的不是View本身,那就不能这么写)。
最后看一下MainActivity

package com.example.lenovo.viewpager;

import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.example.lenovo.viewpager.Bean.News;
import com.example.lenovo.viewpager.adapter.MyPagerAdapter;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ArrayList<News> NewsList=new ArrayList<News>();
    private ViewPager viewPager;
    private LinearLayout dots;
    private int currentPosition;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        dots =(LinearLayout) findViewById(R.id.ll_dots);
        //初始图片布局
        initData();
        //初始指示点
        initDots();
        viewPager.setAdapter(new MyPagerAdapter(MainActivity.this
                ,NewsList));

        viewPager.setCurrentItem(1);//定位第一个新闻

        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {



            /**
             *设置偏移量
             */
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            /**
             *监听选中的页面
             */
            @Override
            public void onPageSelected(int position) {

                if (position==NewsList.size()-1){
                    currentPosition=1;

                }else if (position==0){
                    currentPosition=NewsList.size()-2;

                }else {
                    currentPosition=position;

                }


                changeDots();//随图片变化的指示点


            }


            /**
             *设置滑动状态
             */
            @Override
            public void onPageScrollStateChanged(int state) {

                //SCROLL_STATE_IDLE表示是当前页静止,此状态下将当前页进行替换
                if (state== viewPager.SCROLL_STATE_IDLE)
                //设置当前页平稳滑动,false闪动,ture慢慢缓缓滑动
                viewPager.setCurrentItem(currentPosition,false);

            }
        });

    }

    /**
     * 将指示点与图片进行配对
     */
    public void changeDots(){

        int dotPosition=currentPosition-1;

        for (int i=0;i<dots.getChildCount();i++) {

            ImageView imageView = (ImageView) dots.getChildAt(i);

            if (i == dotPosition) {
                imageView.setImageResource(R.drawable.button1);
            } else {
                imageView.setImageResource(R.drawable.button2);
            }
        }
    }


    /**
     * 初始指示点
     */
    private void initDots() {
        for (int i=0;i<NewsList.size()-2;i++){
            //实际上只有四张图片所以要-2
            ImageView imageView=new ImageView(this);

            if (i==0){
                imageView.setImageResource(R.drawable.button1);
            }else{
                imageView.setImageResource(R.drawable.button2);
            }
            dots.addView(imageView);
        }

    }

    /**
     * 初始化新闻数据
     */
    private void initData() {

        //实现无限轮播,从1-4,1左滑动到4,4右滑动到1

        NewsList.add(new News("新闻测试四",R.drawable.item4));//索引0

        NewsList.add(new News("新闻测试一",R.drawable.itme1));//1
        NewsList.add(new News("新闻测试二",R.drawable.item2));//2
        NewsList.add(new News("新闻测试三",R.drawable.item3));//3
        NewsList.add(new News("新闻测试四",R.drawable.item4));//4

        NewsList.add(new News("新闻测试一",R.drawable.itme1));//5
    }
}

在代码中实现了无限轮播的功能,在滑动中当处于第一张图片时向左滑动要展示第四张图片,处于第四张图片时向右滑动要展示第一张图片。所以在初始化新闻数据时要添加两个重复的list,实现方法是

            @Override
            public void onPageSelected(int position) {
                    //当索引值是5时,跳转为索引值为1的照片
                if (position==NewsList.size()-1){
                    currentPosition=1;
                  //当索引值为0时使用索引值为4的照片
                }else if (position==0){
                    currentPosition=NewsList.size()-2;

                }else {
                    currentPosition=position;
                }

指示点只要与currentPosition配对即可,逻辑基本一致但要注意指示点只有4个而PcurrentPosition有5个所以要-1

    /**
     * 将指示点与图片进行配对
     */
    public void changeDots(){

        int dotPosition=currentPosition-1;

        for (int i=0;i<dots.getChildCount();i++) {

            ImageView imageView = (ImageView) dots.getChildAt(i);

            if (i == dotPosition) {
                imageView.setImageResource(R.drawable.button1);
            } else {
                imageView.setImageResource(R.drawable.button2);
            }
        }
    }

这就是实现功能的全部代码,有一些地方可能解释得不太清楚下次争取更大的进步

相关文章

网友评论

      本文标题:ViewPager滚动功能

      本文链接:https://www.haomeiwen.com/subject/vlrtuxtx.html