画廊效果的ViewPager实现(附带无限自动轮播)[通俗易懂]

画廊效果的ViewPager实现(附带无限自动轮播)[通俗易懂]废话不多说,先上效果图根据效果所示,第一步实现适配器,完成无限循环首先做数据上的处理publicstaticclassLoopViewPagerAdapterextendsPagerAdapter{ …..LoopViewPagerAdapter(Contextcontext,ArrayList<Integer>imgIds){…

大家好,又见面了,我是你们的朋友全栈君。

废话不多说,先上效果图

画廊效果的ViewPager

根据效果所示,第一步实现适配器,完成无限循环

首先做数据上的处理

  public static class LoopViewPagerAdapter extends PagerAdapter{
  	.....
    LoopViewPagerAdapter(Context context, ArrayList<Integer> imgIds){
      this.context = context;

      this.ids.add(imgIds.get(imgIds.size()-1)); 将原本的最后一页复制一份放到第一页
      this.ids.addAll(imgIds);
      this.ids.add(imgIds.get(0)); 将原本的第一页复制一份放到最后一页

      views = new View[ids.size()];
    }
    .....
 }

配合OnPageChangeListener 即可实现无限循环

 private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {

    @Override
    public void onPageSelected(int position) {
      LogUtils.d("LoopViewPager onPageSelected --> " + loopViewPagerAdapter.getCount() + " : " + position);
      if (position == 0){
      	// 滑动到第一页的时候直接跳到倒数第二页,因为两页内容完全一致,跳的过程不会被人眼捕捉到
        setCurrentItem(loopViewPagerAdapter.getCount() - 2, false);
      }
      if (position == loopViewPagerAdapter.getCount() - 1){
      	// 同理滑动到倒数第一页的时候直接跳到第二页
        setCurrentItem(1, false);
      }
    }
    ...
}

第二步 实现放大效果

借助OnPageChangeListener 的 onPageScrolled 滑动进度给指定的Item放大和缩小

private static final float BASE_SCALE = 0.9f; // 为方便调整放大幅度,设立的最小倍数
private static final float BASE_INCREMENT = 0.2f; // 最大放大倍数与最小放大倍数的差值
private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
	...
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
      float zoom = BASE_SCALE + (BASE_INCREMENT - Math.abs(positionOffset * BASE_INCREMENT));
      loopViewPagerAdapter.getViews(position).setScaleX(zoom);
      loopViewPagerAdapter.getViews(position).setScaleY(zoom);

      if (positionOffset > 0) {
        // 左滑,右侧放大
        View leftView = loopViewPagerAdapter.getViews(position + 1);
        if (leftView != null){
          float zoomNext = BASE_SCALE + Math.abs(positionOffset * BASE_INCREMENT);
          leftView.setScaleX(zoomNext);
          leftView.setScaleY(zoomNext);
        }
      }
      if (positionOffset < 0) {
        // 右滑,左侧放大
        View rightView = loopViewPagerAdapter.getViews(position - 1);
        if (rightView != null){
          float zoomNext = BASE_SCALE + Math.abs(positionOffset * BASE_INCREMENT);
          rightView.setScaleX(zoomNext);
          rightView.setScaleY(zoomNext);
        }
    }

	@Override
    public void onPageScrollStateChanged(int state) {
      LogUtils.d("LoopViewPager onPageScrollStateChanged --> " + state);
      if (state == 0) {
        int position = getCurrentItem();
        for (int i = 0; i < loopViewPagerAdapter.getViews().length; i++) {
          View itemView = loopViewPagerAdapter.getViews(i);
          if (itemView != null){
            if (i == position){
              loopViewPagerAdapter.getViews(i).setScaleX(BASE_SCALE + BASE_INCREMENT);
              loopViewPagerAdapter.getViews(i).setScaleY(BASE_SCALE + BASE_INCREMENT);
            }else {
              loopViewPagerAdapter.getViews(i).setScaleX(BASE_SCALE);
              loopViewPagerAdapter.getViews(i).setScaleY(BASE_SCALE);
            }
          }
        }
      }
    }
 }

第三步 增加自动轮播功能

  @SuppressLint("HandlerLeak")
  private class MyHandler extends Handler {

    WeakReference<Context> mWeakReference;

    MyHandler(Context context) {
      mWeakReference = new WeakReference<>(context);
    }

    @Override
    public void handleMessage(Message msg) {
      Context context = mWeakReference.get();
      if (context == null) {
        return;
      }
      if (msg.what == HANDLE_LOOP_MSG) {
        int curItem = getCurrentItem() + 1;
        setCurrentItem(curItem);
      }
      if (isAutoLoop.get()){
        mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);
      }
    }
  }

 // 开始自动轮播
 MyHandler mHandler = new MyHandler(getContext());
 mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);

大功告成,附上完整代码

package com.zhlm.babyhearread.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.zhlm.babyhearread.base.utils.LogUtils;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 自动轮播ViewPager,画廊效果(当前展示的放大,两侧待展示的缩小),两侧可看到部分
 * 目前仅支持使用图片,需要其他的话请自行将PagerAdapter改造成FragmentPagerAdapter
 *
 * 使用方法
 * <xxx.xxx.LoopViewPager
 *     android:id="@+id/loopViewPager"
 *     android:layout_width="match_parent"
 *     android:layout_height="wrap_content"
 *     android:paddingStart="40dp"
 *     android:paddingEnd="40dp"
 *     android:clipToPadding="false"
 *     />
 *
 * ArrayList<Integer> ids = new ArrayList<>();
 * ids.add(R.drawable.img1);
 * ids.add(R.drawable.img2);
 * ids.add(R.drawable.img3);
 * ids.add(R.drawable.img4);
 * LoopViewPager loopViewPager = findViewById(R.id.loopViewPager);
 * loopViewPager.setDates(ids); // 设置数据
 * loopViewPager.autoLoop(true); // 自动轮播
 *
 * author liming  2019/12/9 16:40
 * e-mail : limit_round@163.com
 *
 */
public class LoopViewPager extends ViewPager {

  private MyHandler mHandler;
  private LoopViewPagerAdapter loopViewPagerAdapter;
  private final static int HANDLE_LOOP_MSG = 101;
  private AtomicBoolean isAutoLoop = new AtomicBoolean();

  private static final float BASE_SCALE = 0.9f;
  private static final float BASE_INCREMENT = 0.2f;

  public LoopViewPager(Context context) {
    this(context, null);
  }

  public LoopViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public void autoLoop(boolean isAuto) {
    if (mHandler == null) {
      mHandler = new MyHandler(getContext());
    }
    if (isAuto) {
      mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);
    } else {
      mHandler.removeCallbacksAndMessages(null);
    }
    isAutoLoop.set(isAuto);
  }

  public void setDates(ArrayList<Integer> imgIds){
    setOffscreenPageLimit(5);
    loopViewPagerAdapter = new LoopViewPagerAdapter(getContext(), imgIds);
    loopViewPagerAdapter.initItem();
    setAdapter(loopViewPagerAdapter);
    setCurrentItem(1);

    setOnPageChangeListener(onPageChangeListener);
  }

  private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {

    @Override
    public void onPageSelected(int position) {
      LogUtils.d("LoopViewPager onPageSelected --> " + loopViewPagerAdapter.getCount() + " : " + position);
      if (position == 0){
        setCurrentItem(loopViewPagerAdapter.getCount() - 2, false);
      }
      if (position == loopViewPagerAdapter.getCount() - 1){
        setCurrentItem(1, false);
      }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
      float zoom = BASE_SCALE + (BASE_INCREMENT - Math.abs(positionOffset * BASE_INCREMENT));
      loopViewPagerAdapter.getViews(position).setScaleX(zoom);
      loopViewPagerAdapter.getViews(position).setScaleY(zoom);

      if (positionOffset > 0) {
        // 左滑,右侧放大
        View leftView = loopViewPagerAdapter.getViews(position + 1);
        if (leftView != null){
          float zoomNext = BASE_SCALE + Math.abs(positionOffset * BASE_INCREMENT);
          leftView.setScaleX(zoomNext);
          leftView.setScaleY(zoomNext);
        }
      }
      if (positionOffset < 0) {
        // 右滑,左侧放大
        View rightView = loopViewPagerAdapter.getViews(position - 1);
        if (rightView != null){
          float zoomNext = BASE_SCALE + Math.abs(positionOffset * BASE_INCREMENT);
          rightView.setScaleX(zoomNext);
          rightView.setScaleY(zoomNext);
        }
      }
    }

    @Override
    public void onPageScrollStateChanged(int state) {
      LogUtils.d("LoopViewPager onPageScrollStateChanged --> " + state);
      if (state == 0) {
        int position = getCurrentItem();
        for (int i = 0; i < loopViewPagerAdapter.getViews().length; i++) {
          View itemView = loopViewPagerAdapter.getViews(i);
          if (itemView != null){
            if (i == position){
              loopViewPagerAdapter.getViews(i).setScaleX(BASE_SCALE + BASE_INCREMENT);
              loopViewPagerAdapter.getViews(i).setScaleY(BASE_SCALE + BASE_INCREMENT);
            }else {
              loopViewPagerAdapter.getViews(i).setScaleX(BASE_SCALE);
              loopViewPagerAdapter.getViews(i).setScaleY(BASE_SCALE);
            }
          }
        }
      }
    }
  };

  @SuppressLint("HandlerLeak")
  private class MyHandler extends Handler {

    WeakReference<Context> mWeakReference;

    MyHandler(Context context) {
      mWeakReference = new WeakReference<>(context);
    }

    @Override
    public void handleMessage(Message msg) {
      Context context = mWeakReference.get();
      if (context == null) {
        return;
      }
      if (msg.what == HANDLE_LOOP_MSG) {
        int curItem = getCurrentItem() + 1;
        setCurrentItem(curItem);
      }
      if (isAutoLoop.get()){
        mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);
      }
    }
  }

  public int getWidth(Context context) {
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics outMetrics = new DisplayMetrics();
    if (wm != null) {
      wm.getDefaultDisplay().getMetrics(outMetrics);
    }
    return outMetrics.widthPixels;
  }

  public static class LoopViewPagerAdapter extends PagerAdapter{

    private Context context;
    private ArrayList<Integer> ids = new ArrayList<>();
    private View[] views;
    private int currItem = -1;

    LoopViewPagerAdapter(Context context, ArrayList<Integer> imgIds){
      this.context = context;

      this.ids.add(imgIds.get(imgIds.size()-1));
      this.ids.addAll(imgIds);
      this.ids.add(imgIds.get(0));

      views = new View[ids.size()];
    }

    View getViews(int position) {
      return views[position];
    }

    View[] getViews() {
      return views;
    }

    void initItem(){
      currItem = 1;
    }

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

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

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
      ImageView imageView = new ImageView(context);
      imageView.setImageResource(ids.get(position));

      if (position == currItem){
        imageView.setScaleX(BASE_SCALE + BASE_INCREMENT);
        imageView.setScaleY(BASE_SCALE + BASE_INCREMENT);
        currItem = -1;
      }else {
        imageView.setScaleX(BASE_SCALE);
        imageView.setScaleY(BASE_SCALE);
      }

      container.addView(imageView);
      views[position] = imageView;
      return imageView;
    }
  }
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/131247.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • C语言实现学生成绩管理系统设计

    C语言实现学生成绩管理系统设计本系统有**增加学生记录、修改学生记录、删除学生记录、按姓名查询学生记录、按C语言成绩对学生进行排序、退出系统**6大功能。能够对学生的姓名,学号,c语言成绩做相应的操作。在检测到输入成绩大于55时,会自动加上5。该管理系统设计功能模块图:下面是源代码:#include”stdio.h”#include”string”/*定义学生结构体*/structStudent

  • makefile文件编写「建议收藏」

    makefile文件编写「建议收藏」makefile文件用于管理和组织代码工程的编译和链接,其不是可执行文件,其被make工具解析并完成相关动作,下面笔者将介绍makefile中常用的一些语法说明:1、文件包含:语法:include文件名作用:将其它makefile文件包含进来,组成一个更大的makefile文件,这样有利于makefile模块化编程。通常我们将一些配置选项分开成一个独立的makefile文件,这…

  • 社区打造智慧小区_idc智能化解决方案

    社区打造智慧小区_idc智能化解决方案智慧社区建设方案丨智慧小区智能化解决方案随着物联网技术和我国新一代互联网技术的发展,未来社区网络将会实现全覆盖,通过社区网络和物联网络,将会实现社区机电设备和住宅的自动化,智能化,实现远程监控和网络数字化。智慧社区是社区综合服务管理的一种创新,利用前沿的智能化基础设施建设,增强社区治理和小区管理智能化,推动便民措施服务项目智能化,使社区居民的衣食住行更为舒服、高效率。智慧社区概念介绍:智慧社区是指充分利用物联网、云计算、移动互联网等新一代信息技术的集成应用,涉及到智能楼…

    2022年10月18日
  • 反三角函数求解matlab,关於反三角函数atan2的使用 使用Matlab计算反三角函数atan2…[通俗易懂]

    三角函数中atan2是如何计算的atan2(y,x)返回的是弧度值,两者如果相同则是0.785……,既45度我想问的atan2(y,x)是表示X-Y平面上所对应的(x,y)坐标的角度,它的值域范围是(-π,π)用数学表示就是:atan2(y,x)=arg(y/x)-π当y0时,其值为正.当两者相同时,即y=x,则其角度就是π/4,即45度。使用Matlab计算反三角函数atan2各位好…

  • SSL及其加密通信过程「建议收藏」

    SSL及其加密通信过程「建议收藏」SSL协议和加密过程一、什么是SSL二、HTTPS和SSL三、SSL加密方式3.1对称加密与非对称加密3.1.1对称加密3.1.2非对称加密3.2具体的加密过程一、什么是SSLSSL英文全称SecureSocketLayer,安全套接层,是一种为网络通信提供安全以及数据完整性的安全协议,它在传输层对网络进行加密。它主要是分为两层:SSL记录协议:为高层协议提供安全封装、压缩、加密等…

  • 较完整的 bean生命周期[通俗易懂]

    较完整的 bean生命周期[通俗易懂]首先需要说明的是,Bean的生命周期主要指的是singletonbean,标签的scope默认就是singleton。对prototypebean来说,当用户getBean获得prototypebean的实例后,IOC容器就不再对当前实例进行管理,而是把管理权交由用户,此后再getBean生成的是新的实例。普通JavaBean和SpringBean普通java对象就是new出来,然后不再使用的时候通过垃圾回收机制进行回收; 而springBean是由spring容器来控制的,并且..

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号