画廊效果的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)


相关推荐

  • 编译器警告RegisterStartupScript已经过时

    编译器警告RegisterStartupScript已经过时protectedvoidAlertMsg(stringmsg){this.Page.RegisterStartupScript(“alert”,”<scriptlanguage=\”javascript\”>alert(‘”+msg+”‘);</script>”);}使用上面的代码建立的客户端脚本块编译器会警告Reg…

  • 一分钟教会你固态硬盘数据恢复方法

    不少人都知道,固态硬盘上丢失了数据是很难恢复的,但是也有一些数据丢失的情况,是可以尝试恢复数据的,比如说误删除分区、分区变为RAW状态。针对这些情况,今天呢,小编给大家分享一下固态硬盘数据恢复方法,我们需要借助一款好用的数据恢复软件——易我数据恢复,该软件可深度扫描磁盘数据,根据删除标记、文件目录信息和文件内容等三种方式分别检索文件,搜寻更全面。(详情访问:https://www.easeus.com.cn/data-recovery-software/data-recovery-wizard.html

  • Robotium 常用方法

    Robotium 常用方法①点击:clickOnButton(int)//ClicksonaButtonwithagivenindex.clickOnButton(String)//ClicksonaButtonwithagiventext.clickOnCheckBox(int)//ClicksonaCheckBoxwithagivenindex.clickOnVie

  • vue生命周期函数_vue生命周期函数有哪些

    vue生命周期函数_vue生命周期函数有哪些生命周期函数生命周期函数代表的是Vue实例,或者是Vue组件,在网页中各个生命阶段所执行的函数。生命周期函数可以分为创建阶段和运行期间以及销毁期间。其中创建期间的函数有beforeCreate、c

  • html5 sexteen,Sexy TV shows blamed for teen pregnancies

    html5 sexteen,Sexy TV shows blamed for teen pregnanciesExposuretosomeformsofentertainmentisacorruptinginfluenceonchildren,leadingteenswhowatchsexyprogramsintoearlypregnanciesandchildrenwhoplayviolentvideogamestoadoptaggressiv…

  • python二维列表操作求一个向量与二维矩阵的乘积_python三维列表

    python二维列表操作求一个向量与二维矩阵的乘积_python三维列表Python二维列表操作创建二维列表对象获取二维列表行元素的个数获取二维列表总元素个数今天介绍一下Python中二维列表的一些操作。创建二维列表对象lst_2D=[]lst_1D_a=[“1″,”2″,”3”]lst_1D_b=[“4″,”5″,”6”]lst_1D_c=[“7″,”8″,”9”]lst_2D.append(lst_1D_a)lst_2D.append(lst_1D_b)lst_2D.append(lst_1D_c)print(lst_2

    2022年10月30日

发表回复

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

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