修改ViewPage的r预加载,左右滑动,切换经过中间页问题,ViewPager一屏显示多张图片

2017-04-16 19:40:01
1.屏蔽切换的时候需要经过中间页
2.屏蔽ViewPager的滑动
3.预加载问题

复制代码

import android.content.Context;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.view.MotionEvent;/**
 * 1.屏蔽切换的时候需要经过中间页
 * 2.屏蔽ViewPager的滑动
 * 3.预加载问题 */public class MyViewPager extends ViewPager {    /**
     * 是否可以滑动     */
    private boolean isCanScroll = false;    public MyViewPager(Context context) {        super(context);
    }    public MyViewPager(Context context, AttributeSet attrs) {        super(context, attrs);
    }    /**
     * 解决切换需要经过中间页     */
    @Override    public void setCurrentItem(int item) {        //super.setCurrentItem(item);源码
        super.setCurrentItem(item,false);//false表示切换的时候,不经过两个页面的中间页    }    /**
     * 让ViewPager不能左右滑动     */
    @Override    public boolean onTouchEvent(MotionEvent ev) {        if(isCanScroll){            return super.onTouchEvent(ev);
        }else{            return false;
        }
    }    /**
     * 暴露出去的方法,屏蔽ViewPager的滑动,默认不可滑动
     * @param isCanScroll 为true可以左右滑动,为false不可滑动     */
    public void setIsCanScroll(boolean isCanScroll){        this.isCanScroll = isCanScroll;
    }

    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        if(isCanScroll){            return super.onInterceptTouchEvent(ev);
        }else{            return false;
        }
    }    /* 设置预加载页数的源码,默认为1,当设置的数大于1是有效的,小于1就无效了
       1)如果想预加载多页(默认预加载一页),可以使用setOffscreenPageLimit(int limit),意思为幕后页的限制,默认为1
       2)当你不想要预加载的时候,那是不是只需要将这个值设为0呢?答案是不行的,
      解决办法:复制ViewPager源码将DEFAULT_OFFSCREEN_PAGES这个值改为0就可以了
    public void setOffscreenPageLimit(int limit) {
        if (limit < DEFAULT_OFFSCREEN_PAGES) {
            limit = DEFAULT_OFFSCREEN_PAGES;//可见当设置的值小于1时无效
        }
        if (limit != mOffscreenPageLimit) {
            mOffscreenPageLimit = limit;
            populate();
        }
    }     */}

复制代码

但是切记,复制ViewPager源码别复制高版本的,防止出问题,因为现在Android都7.0了,版本都老高了,其实android虽然每个版本都有v4包,但是这些v4包是有差异的。这就造成高版本v4包里的ViewPager,即使你Copy它,将其DEFAULT_OFFSCREEN_PAGES的值改为0,还是不起作用的,其中的逻辑变了。具体哪里变了导致无效我也没有继续研究了,下面给出一份低版本修改好的(只修改了预加载)

 View Code

2.利用ViewPager实现一屏显示多张图片的问题

MainActivity代码:

复制代码

public class MainActivity extends AppCompatActivity {    private List<ImageView> list;    private int[] imgsId={R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d};

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
        initData();
        viewPager.setAdapter(new MyPagerAdapter(list));
    }    
    //初始化显示的图片
    private void initData() {
        list = new ArrayList<>();        for (int i : imgsId) {
            ImageView imageView = new ImageView(MainActivity.this);
            imageView.setImageResource(i);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            list.add(imageView);
        }
    }
}

复制代码

适配器:

复制代码

public class MyPagerAdapter extends PagerAdapter {    private List<ImageView> list;    public MyPagerAdapter(List<ImageView> list) {        this.list = list;
    }

    @Override    public int getCount() {        return list.size();
    }

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

    @Override    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(list.get(position));        return list.get(position);
    }

    @Override    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
        object = null;
    }    /**
     * 设置该页内容所占屏幕的宽度     */
    @Override    public float getPageWidth(int position) {        //return 1.f; 默认返回1,代表该position占据了ViewPager的一整页,范围(0,1]
        return 0.8f;
    }
}

复制代码

布局文件:

 View Code

效果如下: 如果没重写getPageWidth()方法(左图)              重写后为(右图)

下面看下一屏显示多张图片的具体实现:

由于上面适配器中的getPageWidth方法只能控制一边的距离,不能实现左右两边显示,所以改功能需要删除上面适配器中的getPageWidth()方法

java代码:

复制代码

import android.os.Bundle;import android.support.v4.view.ViewPager;import android.support.v7.app.AppCompatActivity;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import java.util.ArrayList;import java.util.List;/**
 * ViewPager显示多张图片 */public class MainActivity extends AppCompatActivity {    private List<ImageView> list;    private int[] imgsId={R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d};

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();//初始化数据        //ViewPager的父布局
        final LinearLayout viewPagerContainer  = (LinearLayout) findViewById(R.id.viewPager_layout);        final ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
        viewPager.setOffscreenPageLimit(3); // viewPager的缓存页数
        viewPager.setPageMargin(30); // 设置各页面的间距        // 将父节点Layout事件分发给viewpager,否则只能滑动中间的一个view对象
        viewPagerContainer.setOnTouchListener(new View.OnTouchListener() {
            @Override            public boolean onTouch(View v, MotionEvent event) {                return viewPager.dispatchTouchEvent(event);
            }
        });        //设置ViewPager的滑动监听,必须在滑动的时候刷新界面才能看到效果
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {                //必须刷新页面,才能看到效果
                if (viewPagerContainer != null) {
                    viewPagerContainer.invalidate();
                }
            }

            @Override            public void onPageSelected(int position) {

            }

            @Override            public void onPageScrollStateChanged(int state) {

            }
        });        //设置适配器
        viewPager.setAdapter(new MyPagerAdapter(list));
    }    //初始化显示的图片
    private void initData() {
        list = new ArrayList<>();        for (int i : imgsId) {
            ImageView imageView = new ImageView(MainActivity.this);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            imageView.setImageResource(i);
            list.add(imageView);
        }
    }
}

复制代码

布局文件:

复制代码

<?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/viewPager_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:layerType="software"
    android:clipChildren="false">

    <!--
        一屏显示多张图片的步骤:
        1.配置ViewPager和其父布局的 android:clipChildren属性为”false”.
            (android:clipChildren表示是否限制子View在其范围内,默认为true. 代码设置setClipChildren(false))
            因为如果clipChildren属性设置为true,就表明我们要将children给clip掉,
            就是说对于子元素来说,超出当前view的部分都会被切掉,那我们在这里把它设置成false,
            就表明超出view的部分,不要切掉,依然显示。

        2.设置ViewPager的父布局,android:layerType="software",这样才能显示左右两边的图片,否则不显示为空白

        3.设置幕后item的缓存数目。如果一屏展示的pager数目多的话就需要设置此项。
            viewPager.setOffscreenPageLimit(3); //具体缓存页数看需求

        4.设置页与页之间的间距
            viewPager.setPageMargin(int marginPixls);// setPageMargin表示设置page之间的间距

        5.将ViewPager的父布局触摸事件分发给viewpager,否则只能滑动ViewPager中间的那个view对象

        6.必须在ViewPager的滑动监听中刷新界面才能看到效果
        
        具体代码见MainActivity的onCreate方法两空行之间的代码     -->

    <!--android:layout_marginLeft="50dp"
        android:layout_marginRight="50dp"代表居中显示的pager距离屏幕左右两边的距离-->
    <android.support.v4.view.ViewPager        android:id="@+id/viewPager"
        android:clipChildren="false"
        android:layout_marginLeft="50dp"
        android:layout_marginRight="50dp"
        android:layout_width="match_parent"
        android:layout_height="300dp">
    </android.support.v4.view.ViewPager></LinearLayout>

复制代码

效果如下:

 如果需要切换效果可以看鸿洋大神的:   巧用ViewPager 打造不一样的广告轮播切换效果

https://github.com/hongyangAndroid/MagicViewPager


  • 2019-08-15 13:32:18

    Node.js是如何解决服务器高性能瓶颈问题的

    在Java、PHP或者.net等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存。也就是说,理论上,一个8GB内存的服务器可以同时连接的最大用户数为4000个左右。要让Web应用程序支持更多的用户,就需要增加服务器的数量,而Web应用程序的硬件成本当然就上升了。

  • 2019-08-15 13:33:53

    nodejs的10个性能优化技巧

    在我接触JavaScript(无论浏览器还是NodeJS)的时间里,总是遇到有朋友有多线程的需求。而在NodeJS方面,有朋友甚至直接说到,NodeJS是单线程的,无法很好的利用多核CPU。那么我们在使用过程中,就要非常注意性能优化了

  • 2019-08-16 13:18:48

    使用ffmpeg进行ts切片并AES-128加密

    由于解密的key文件都是公开的,所以并不能算上完全加密,用户只要把你的key+m3u8里的ts切片文件全部下载,用ffmpeg还是能解,这时就要考虑url的key防止用户直接下载和盗链。 ​

  • 2019-08-18 22:22:54

    Error:error: unable to remove file: Permission denied

    JNI里写的C++增加了函数或修改了,如果此时是Debug模式下,而且还没退出程序,就出现这个Permission denied的提示。解决也很简单:就是退出App即可。如果退出无响应,直接拔usb,重新插上也可以

  • 2019-08-19 10:24:29

    浅析Express中的路由与应用模式

    Express是一个基于Node.js的轻量级web开发框架,具有体积小,使用灵活等特点。查看Express的源码,如果不计供使用的中间件,主体框架只有一千余行代码,非常简练。

  • 2019-08-19 15:50:17

    记录PHP的进程和线程理解

    线程是进程的一个执行流,线程不能分配系统资源,它是进程的一部分,比进程更小的独立运行的单位。 解释一下:进程有两个特性:一是资源的所有权,一个是调度执行(指令集),线程是调度执行中的一部分,是指进程执行过程的路径,也叫程序执行流。线程有时候也叫轻量级进程。

  • 2019-08-20 08:51:52

    一台Linux服务器可以负载多少个连接?

    我们在压测一台目标服务器,想看下负载的连接数,当我们压到一定数量的时候,控制台突然报"too many open files",这是因为linux系统创建一个TCP连接的时候,都会创建一个socket句柄,每个socket句柄就是一个文件句柄。

  • 2019-08-20 08:56:42

    Linux下Http高并发参数优化之TCP参数

    Linux 内核参数考虑的是最通用场景,并不符合用于支持高并发访问的Web服务器的定义,所以需要修改Linux内核参数。其次,对 Nginx 的一些参数,也需要根据服务情况进行调整。

  • 2019-08-20 11:05:30

    php,nginx,线程和进程分析

    大多数的 Linux 程序都倾向于使用进程而不是线程,因为 Linux 下相对来说创建进程的开销比较小,而 Linux 的线程功能又不是很强大。