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

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

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

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

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

使用方式

布局中添加该自定义控件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <!-- 布局中添加自定义控件-->
 <com.mahao.alex.customviewdemo.viewpager.CoverFlowViewPager
 android:id="@+id/cover"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" />

</RelativeLayout>

代码中设置

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

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<View> 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 ? "0" + r : r ;
 g = g.length()==1 ? "0" + g : g ;
 b = b.length()==1 ? "0" + b : b ;

 return r+g+b;
 }
}

实现原理

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

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

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

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

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

代码实现

编写控件的布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:clipChildren="false">

 <android.support.v4.view.ViewPager
 android:id="@+id/vp_conver_flow"
 android:layout_width="180dp"
 android:layout_height="260dp"
 android:layout_centerHorizontal="true"
 android:clipChildren="false" />

</RelativeLayout>

 一个相对布局中嵌入一个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<View> mViewList;

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

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

 public CoverFlowAdapter(List<View> 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 ? 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 < mViewList.size()) {
  //当前手指触摸滑动的页面,从0页滑动到1页 offset越来越大,padding越来越大
  Log.i("info", "重新设置padding");
  int outHeightPadding = (int) (positionOffset * sHeightPadding);
  int outWidthPadding = (int) (positionOffset * sWidthPadding);
  // 从0滑动到一时,此时position = 0,其应该是缩小的,符合
  mViewList.get(position).setPadding(outWidthPadding, outHeightPadding, outWidthPadding, outHeightPadding);

  // position+1 为即将显示的页面,越来越大
  if (position < mViewList.size() - 1) {
  int inWidthPadding = (int) ((1 - positionOffset) * sWidthPadding);
  int inHeightPadding = (int) ((1 - positionOffset) * sHeightPadding);
  mViewList.get(position + 1).setPadding(inWidthPadding, inHeightPadding, inWidthPadding, inHeightPadding);
  }
 }

 }

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

 @Override
 public void onPageScrollStateChanged(int state) {

 }

 /**
 * 当将某一个作为最中央时的回调
 *
 * @param listener
 */
 public void setOnPageSelectListener(OnPageSelectListener listener) {
 this.listener = listener;
 }

 /**
 * dp 转 px
 *
 * @param dp
 * @return
 */
 public int dp2px(int dp) {
 int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources().getDisplayMetrics());

 return px;
 }

}

改代码分为两部分,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<View> 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);
 }
 }

点击事件的设置

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

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, viewpager
画廊
viewpager放大缩小、滑动鼠标页面放大缩小、android 滑动放大缩小、ios滑动放大缩小动画、viewpager画廊效果,以便于您获取更多的相关知识。

时间: 2024-11-08 17:19:42

Android利用ViewPager实现可滑动放大缩小画廊效果_Android的相关文章

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

画廊在很多的App设计中都有,如下图所示: 该例子是我没事的时候写的一个小项目,具体源码地址请访问https://github.com/AlexSmille/YingMi. 该画廊类似封面的效果,滑到中间的图片会慢慢变大,离开的View会慢慢的缩小,同时可设置滑动监听和点击监听. 网上有很多例子都是通过Gallery实现的,而上例的实现是通过ViewPager实现,解决了性能优化的问题,今天特此把它抽出来,封装一下,以便以后的方便使用.最终实现的效果如下: 使用方式 布局中添加该自定义控件 <R

Android实现手势滑动多点触摸放大缩小图片效果_Android

网上文章虽多,但是这种效果少之又少,我真诚的献上以供大家参考 实现原理:自定义ImageView对此控件进行相应的layout(动态布局). 这里你要明白几个方法执行的流程: 首先ImageView是继承自View的子类.onLayout方法:是一个回调方法.该方法会在在View中的layout方法中执行,在执行layout方法前面会首先执行setFrame方法.setFrame方法:判断我们的View是否发生变化,如果发生变化,那么将最新的l,t,r,b传递给View,然后刷新进行动态更新UI

Android利用Camera实现中轴3D卡牌翻转效果_Android

在Android系统API中,有两个Camera类: android.graphics.Camera android.hardware.Camera 第二个应用于手机硬件中的相机相关的操作,本文讲述的是利用第一个Camera类实现中轴3D转换的卡牌翻转效果,开始之前,先看一下Android系统中的坐标系: 对应于三维坐标系中的三个方向,Camera提供了三种旋转方法: rotateX() rotateY() rotateX() 调用这三种方法,传入旋转角度参数,即可实现视图沿着坐标轴旋转的功能.

android配合viewpager实现可滑动的标签栏示例分享_Android

复制代码 代码如下: package com.example.playtabtest.view; import com.example.playtabtest.R; import android.app.Activity;import android.content.Context;import android.support.v4.view.ViewPager;import android.support.v4.view.ViewPager.OnPageChangeListener;impor

Android 利用ViewPager实现图片可以左右循环滑动效果附代码下载_Android

首先给大家展示靓照,对效果图感兴趣的朋友可以继续往下阅读哦. ViewPager这个小demo实现的是可以左右循环滑动图片,下面带索引,滑到最后一页在往右滑动就要第一页,第一页往左滑动就到最后一页,上面是效果图,用美女图片是我一贯的作风,呵呵  1.    首先看一些layout下的xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width=&qu

Android使用ViewPager实现无限滑动效果_Android

前言 其实仔细想一下原理还是挺简单的.无非是当我们滑动到最后一页,再向后滑动时定位到第一页;当我们滑动到第一页,再向前滑动时定位到最后一页. 但是,相信很多朋友都遇到过这个问题:视图的过度效果不自然. 小编也是通过百度和谷歌查找了很多解决方案,实验了很多方法,总结了一个相对不错的方法,接下来给各位分享下滑动效果.实现细节以及一些踩过的坑. 1.无限滑动效果(左右无限滑动) 事先准备好2张滑动图片(有想试验的小伙伴,自备图片啊,小编就不提供了...) 运行效果图(左右无限循环): 为了显示更加直观

Android利用ViewPager实现用户引导界面效果的方法_Android

本文实例讲述了Android利用ViewPager实现用户引导界面效果.分享给大家供大家参考,具体如下: 我相信有很多朋友在装完软件首次打开时,有很多软件都有一个软件功能介绍, 例如刚装完微信打开它,有很多介绍微信功能的图片,并且在屏幕下方有很多小圆点提示你当前图片的位置. 今天我就来实现这么个功能 所实现的功能: 1.可以左右滑动功能图片. 2.图片的索引 看出当前图片所在的位置. 3.可循环滑动. 4.图片的索引带有动画效果. 本次学习主要是利用ViewPager实现用户引导界面 在这里,我

Android利用ViewPager实现用户引导界面效果的方法

本文实例讲述了Android利用ViewPager实现用户引导界面效果.分享给大家供大家参考,具体如下: 我相信有很多朋友在装完软件首次打开时,有很多软件都有一个软件功能介绍, 例如刚装完微信打开它,有很多介绍微信功能的图片,并且在屏幕下方有很多小圆点提示你当前图片的位置. 今天我就来实现这么个功能 所实现的功能: 1.可以左右滑动功能图片. 2.图片的索引 看出当前图片所在的位置. 3.可循环滑动. 4.图片的索引带有动画效果. 本次学习主要是利用ViewPager实现用户引导界面 在这里,我

Android编程实现ViewPager多页面滑动切换及动画效果的方法_Android

本文实例讲述了Android编程实现ViewPager多页面滑动切换及动画效果的方法.分享给大家供大家参考,具体如下: 一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式, 白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了,接下来我们就来实现它. 二.在开始前,我们先要认识一个控件,ViewPager.它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换. 这个附加包是and