热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android利用ViewPager实现可滑动放大缩小画廊效果

这篇文章主要介绍了Android利用ViewPager实现可滑动放大缩小画廊效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

画廊在很多的App设计中都有,如下图所示:

该例子是我没事的时候写的一个小项目,具体源码地址请访问https://github.com/AlexSmille/YingMi。

该画廊类似封面的效果,滑到中间的图片会慢慢变大,离开的View会慢慢的缩小,同时可设置滑动监听和点击监听。

网上有很多例子都是通过Gallery实现的,而上例的实现是通过ViewPager实现,解决了性能优化的问题,今天特此把它抽出来,封装一下,以便以后的方便使用。最终实现的效果如下:

使用方式

布局中添加该自定义控件



 
 


代码中设置

代码中设置分为以下几个步骤:
 •查找控件
 •初始化数据
 •将需要显示的数据设置到控件上
 •设置滑动监听 

public class MainActivity extends AppCompatActivity {

 private CoverFlowViewPager mCover;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 mCover = (CoverFlowViewPager) findViewById(R.id.cover);

 // 初始化数据
 List list = new ArrayList<>();
 for(int i = 0;i<10;i++){
 ImageView img = new ImageView(this);
 img.setBackgroundColor(Color.parseColor("#"+getRandColorCode()));
 list.add(img);
 }
 //设置显示的数据
 mCover.setViewList(list);
 // 设置滑动的监听,该监听为当前页面滑动到中央时的索引
 mCover.setOnPageSelectListener(new OnPageSelectListener() {
 @Override
 public void select(int position) {
 Toast.makeText(getApplicationContext(),position+"",Toast.LENGTH_SHORT).show();
 }
 });
 }


 /**
 * 获取随机颜色,便于区分
 * @return
 */
 public static String getRandColorCode(){
 String r,g,b;
 Random random = new Random();
 r = Integer.toHexString(random.nextInt(256)).toUpperCase();
 g = Integer.toHexString(random.nextInt(256)).toUpperCase();
 b = Integer.toHexString(random.nextInt(256)).toUpperCase();

 r = r.length()==1 &#63; "0" + r : r ;
 g = g.length()==1 &#63; "0" + g : g ;
 b = b.length()==1 &#63; "0" + b : b ;

 return r+g+b;
 }
}

实现原理

实现过程中有两个难点:
 &#8226;如何实现滑动过程中的放大与缩小
 &#8226;如何显示ViewPager中未被显示的页面 

如何实现滑动过程中的放大与缩小?

在设置每一个ViewPager 的页面时,对每一个页面都设置一个固定的padding值,这样每个页面都会显示缩小状态。同时ViewPager设置addOnPageChangeListener(),滑动监听,在该滑动监听中会回调ViewPager的滑动的状态,滑动的偏移量等,根据滑动的偏移量进行放大缩小。及根据padding值设置控件的显示大小

如何显示ViewPager中未被显示的页面

在xml中有一个不常用的属性android:clipChildren,是否限制子View的显示。设置为false,则子View的显示不受父控件的限制。

代码实现

编写控件的布局文件



 


 一个相对布局中嵌入一个ViewPager,相对布局用于确定显示的范围,ViewPager用以实现滑动,放大缩小等。

创建CoverFlowViewPager,加载布局

/**
 *
 * 实现封面浏览
 * Created by alex_mahao on 2016/8/25.
 */
public class CoverFlowViewPager extends RelativeLayout implements OnPageSelectListener {
 /**
 * 用于左右滚动
 */
 private ViewPager mViewPager;

 public CoverFlowViewPager(Context context, AttributeSet attrs) {
 super(context, attrs);
 inflate(context, R.layout.widget_cover_flow,this);
 mViewPager = (ViewPager) findViewById(R.id.vp_conver_flow);
 //init();
 }

查找控件,并加载布局。

编写适配器,实现滑动的监听

既然有了ViewPager,那么肯定要有适配器Adapter。因为我们要在滑动监听中,根据偏移量操作每一个子元素,放大或缩小,而对于子元素,当然适配器最容易获取,所以将Adapter实现了ViewPager的滑动监听接口。

/**
 * 滚动的适配器
 * Created by alex_mahao on 2016/8/25.
 */
public class CoverFlowAdapter extends PagerAdapter implements ViewPager.OnPageChangeListener {

 /**
 * 默认缩小的padding值
 */
 public static int sWidthPadding;

 public static int sHeightPadding;

 /**
 * 子元素的集合
 */
 private List mViewList;

 /**
 * 滑动监听的回调接口
 */
 private OnPageSelectListener listener;

 /**
 * 上下文对象
 */
 private Context mContext;

 public CoverFlowAdapter(List mImageViewList, Context context) {
 this.mViewList = mImageViewList;
 mCOntext= context;
 // 设置padding值
 sWidthPadding = dp2px(24);
 sHeightPadding = dp2px(32);
 }

 @Override
 public void destroyItem(ViewGroup container, int position, Object object) {
 container.removeView(mViewList.get(position));
 }

 @Override
 public Object instantiateItem(ViewGroup container, int position) {
 View view = mViewList.get(position);
 container.addView(view);

 return view;
 }

 @Override
 public int getCount() {
 return mViewList == null &#63; 0 : mViewList.size();
 }

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

 @Override
 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 // 该方法回调ViewPager 的滑动偏移量
 if (mViewList.size() > 0 && position 

改代码分为两部分,PagerAdapter实现,滑动监听的实现。PagerAdapter的实现不在多说,最基础的东西。重点在滑动监听的实现。

滑动监听有三个回调方法:其中onPageScrolled(int position, float positionOffset, int positionOffsetPixels)回调的便是ViewPager的滑动得偏移量,我们再次动态的设置相应元素的padding值,实现放大缩小。

onPageSelected()为选中的回调,通过自定义接口的方式回调给其调用者。后面会提。

初始化ViewPager

既然有了适配器,那么自然就开始编写适配器的部分:

 /**
 * 初始化方法
 */
 private void init() {
 // 构造适配器,传入数据源
 mAdapter = new CoverFlowAdapter(mViewList,getContext());
 // 设置选中的回调
 mAdapter.setOnPageSelectListener(this);
 // 设置适配器
 mViewPager.setAdapter(mAdapter);
 // 设置滑动的监听,因为adpter实现了滑动回调的接口,所以这里直接设置adpter
 mViewPager.addOnPageChangeListener(mAdapter);
 // 自己百度
 mViewPager.setOffscreenPageLimit(5);

 // 设置触摸事件的分发
 setOnTouchListener(new OnTouchListener() {
 @Override
 public boolean onTouch(View v, MotionEvent event) {
 // 传递给ViewPager 进行滑动处理
 return mViewPager.dispatchTouchEvent(event);
 }
 });
 }

注释很详细,唯一需要解释的便是事件的分发。

我们的ViewPager的大小是固定的,只有中间的显示区域,那么对于手指在两个侧边滑动时,ViewPager自然接受不到触摸事件,通过设置外层相对布局的触摸事件监听,将触摸的事件传递到ViewPager,实现滑动ViewPager之外区域时,ViewPager仍能够实现对应的滑动。

数据源的包装

适配器有了,ViewPager也有了,那么只剩下数据源了。

因为我们是根据设置padding值实现的,那么对于需要显示的控件,他的背景将无法实现放大缩小,所以对控件在包装一层外部控件,这样设置外部控件的padding值,自然需要显示的控件会放大缩小。

 /**
 * 设置显示的数据,进行一层封装
 * @param lists
 */
 public void setViewList(List lists){
 if(lists==null){
 return;
 }
 mViewList.clear();
 for(View view:lists){

 FrameLayout layout = new FrameLayout(getContext());
 // 设置padding 值,默认缩小
 layout.setPadding(CoverFlowAdapter.sWidthPadding,CoverFlowAdapter.sHeightPadding,CoverFlowAdapter.sWidthPadding,CoverFlowAdapter.sHeightPadding);
 layout.addView(view);
 mViewList.add(layout);
 }
 // 刷新数据
 mAdapter.notifyDataSetChanged();
 }

选中监听的回调

当我们滑动时,可能会根据不同的滑动,显示不同的数据。

通过设置滑动监听之后,对onPageSelected实现层层的接口回调。

接口的定义OnPageSelectListener

public interface OnPageSelectListener {

 void select(int position);
}

CoverFlowAdapter中添加回调

 @Override
 public void onPageSelected(int position) {
 // 回调选择的接口
 if (listener != null) {
 listener.select(position);
 }
 }

CoverFlowViewPager中添加回调

 // 显示的回调
 @Override
 public void select(int position) {
 if(listener!=null){
 listener.select(position);
 }
 }

点击事件的设置

直接对数据源循环设置监听即可

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文介绍如何使用 Sortable.js 库实现元素的拖拽和位置交换功能。Sortable.js 是一个轻量级、无依赖的 JavaScript 库,支持拖拽排序、动画效果和多种插件扩展。通过简单的配置和事件处理,可以轻松实现复杂的功能。 ... [详细]
  • 探讨一个显示数字的故障计算器,它支持两种操作:将当前数字乘以2或减去1。本文将详细介绍如何用最少的操作次数将初始值X转换为目标值Y。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文详细介绍了如何在 Spring Boot 应用中通过 @PropertySource 注解读取非默认配置文件,包括配置文件的创建、映射类的设计以及确保 Spring 容器能够正确加载这些配置的方法。 ... [详细]
  • This document outlines the recommended naming conventions for HTML attributes in Fast Components, focusing on readability and consistency with existing standards. ... [详细]
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
author-avatar
mobiledu2502906047
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有