Android实现图片点击预览效果(zoom动画)

参考:https://developer.android.google.cn/training/animation/zoom.html

1.创建Views

下面的布局包括了你想要zoom的大版本和小版本的view。

1.ImageButton是小版本的,能点击的,点击后显示大版本的ImageView。

2.ImageView是大版本的,可以显示ImageButton点击后的样式。

3.ImageView一开始是不可见的(invisible),当ImageButton点击后,它会实现zoom动画,就像从ImageButton上扩大显示出来。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/container"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <LinearLayout android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical"
  android:padding="16dp">
  <ImageButton
   android:id="@+id/thumb_button_1"
   android:layout_width="100dp"
   android:layout_height="75dp"
   android:layout_marginRight="1dp"
   android:src="@drawable/thumb1"
   android:scaleType="centerCrop"
android:contentDescription="@string/description_image_1" />
 </LinearLayout>
 <!-- 这个不可见的ImageView持有上面的ImageButton zoom后的图片版本。
 动画没有发生之前,它占据了整个屏幕。动画开始,这个View从上面
 ImageButton的范围变化到他自己最终的范围。
   -->
 <ImageView
  android:id="@+id/expanded_image"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:visibility="invisible"
android:contentDescription="@string/description_zoom_touch_close" />

</FrameLayout>

2.设置zoom动画

在ImageButton上设置点击事件,执行zoom动画

public class ZoomActivity extends FragmentActivity {
 // 保存下当前动画类,以便可以随时结束动画
 private Animator mCurrentAnimator;
 //系统的短时长动画持续时间(单位ms)
 // 对于不易察觉的动画或者频繁发生的动画
 // 这个动画持续时间是最理想的
 private int mShortAnimationDuration;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_zoom);
  // 给ImageButton设置点击事件
  final View thumb1View = findViewById(R.id.thumb_button_1);
  thumb1View.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
  //执行zoom动画方法
    zoomImageFromThumb(thumb1View, R.drawable.image1);
   }
  });
  //取回系统默认的短时长动画持续时间
  mShortAnimationDuration = getResources().getInteger(
android.R.integer.config_shortAnimTime);
 }
 ...
}

3.实现zoom动画

你需要把从正常大小的view到扩大以后的view这个过程作成动画。

1.指定想要zoom的图片给ImageView。(理想情况下,这个bitmap的大小不应该比屏幕大)

2.计算这个ImageView的开始和结束位置

3.把四个点和缩放大小的属性同时作成动画,从开始的状态到结束的状态。这四个动画被添加到AnimatorSet中,方便他们同时执行。

4.当用户再次点击屏幕时,动画要执行回去。一样道理,给ImageView一个View.OnClickListener,然后隐藏ImageView。

private void zoomImageFromThumb(final View thumbView, int imageResId) {
 // 如果有动画在执行,立即取消,然后执行现在这个动画
 if (mCurrentAnimator != null) {
 mCurrentAnimator.cancel();
 }
 // 加载高分辨率的图片
 final ImageView expandedImageView = (ImageView) findViewById(
  R.id.expanded_image);
 expandedImageView.setImageResource(imageResId);
 // 计算开始和结束位置的图片范围
 final Rect startBounds = new Rect();
 final Rect finalBounds = new Rect();
 final Point globalOffset = new Point();
 // 开始的范围就是ImageButton的范围,
 // 结束的范围是容器(FrameLayout)的范围
 // getGlobalVisibleRect(Rect)得到的是view相对于整个硬件屏幕的Rect
 // 即绝对坐标,减去偏移,获得动画需要的坐标,即相对坐标
 // getGlobalVisibleRect(Rect,Point)中,Point获得的是view在它在
 // 父控件上的坐标与在屏幕上坐标的偏移
 thumbView.getGlobalVisibleRect(startBounds);
 findViewById(R.id.container)
  .getGlobalVisibleRect(finalBounds, globalOffset);
 startBounds.offset(-globalOffset.x, -globalOffset.y);
 finalBounds.offset(-globalOffset.x, -globalOffset.y);
 // Adjust the start bounds to be the same aspect ratio as the final
 // bounds using the "center crop" technique. This prevents undesirable
 // stretching during the animation. Also calculate the start scaling
 // factor (the end scaling factor is always 1.0).
 // 下面这段逻辑其实就是保持纵横比
 float startScale;
 // 如果结束图片的宽高比比开始图片的宽高比大
 // 就是结束时“视觉上”拉宽了(压扁了)图片
 if ((float) finalBounds.width() / finalBounds.height()
  > (float) startBounds.width() / startBounds.height()) {
 // Extend start bounds horizontally
 startScale = (float) startBounds.height() / finalBounds.height();
 float startWidth = startScale * finalBounds.width();
 float deltaWidth = (startWidth - startBounds.width()) / 2;
 startBounds.left -= deltaWidth;
 startBounds.right += deltaWidth;
 } else {
 // Extend start bounds vertically
 startScale = (float) startBounds.width() / finalBounds.width();
 float startHeight = startScale * finalBounds.height();
 float deltaHeight = (startHeight - startBounds.height()) / 2;
 startBounds.top -= deltaHeight;
 startBounds.bottom += deltaHeight;
 }
 // Hide the thumbnail and show the zoomed-in view. When the animation
 // begins, it will position the zoomed-in view in the place of the
 // thumbnail.
 // 隐藏小的图片,展示大的图片。当动画开始的时候,
 // 要把大的图片发在小的图片的位置上
 //小的设置透明
 thumbView.setAlpha(0f);
 //大的可见
 expandedImageView.setVisibility(View.VISIBLE);
 // Set the pivot point for SCALE_X and SCALE_Y transformations
 // to the top-left corner of the zoomed-in view (the default
 // is the center of the view).
 expandedImageView.setPivotX(0f);
 expandedImageView.setPivotY(0f);
 // Construct and run the parallel animation of the four translation and
 // scale properties (X, Y, SCALE_X, and SCALE_Y).
 AnimatorSet set = new AnimatorSet();
 set
  .play(ObjectAnimator.ofFloat(expandedImageView, View.X,
   startBounds.left, finalBounds.left))
  .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
   startBounds.top, finalBounds.top))
  .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
  startScale, 1f)).with(ObjectAnimator.ofFloat(expandedImageView,
   View.SCALE_Y, startScale, 1f));
 set.setDuration(mShortAnimationDuration);
 set.setInterpolator(new DecelerateInterpolator());
 set.addListener(new AnimatorListenerAdapter() {
 @Override
 public void onAnimationEnd(Animator animation) {
  mCurrentAnimator = null;
 }
 @Override
 public void onAnimationCancel(Animator animation) {
  mCurrentAnimator = null;
 }
 });
 set.start();
 mCurrentAnimator = set;
 // Upon clicking the zoomed-in image, it should zoom back down
 // to the original bounds and show the thumbnail instead of
 // the expanded image.
 // 再次点击返回小的图片,就是上面扩大的反向动画。即预览完成
 final float startScaleFinal = startScale;
 expandedImageView.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {
  if (mCurrentAnimator != null) {
  mCurrentAnimator.cancel();
  }
  // Animate the four positioning/sizing properties in parallel,
  // back to their original values.
  AnimatorSet set = new AnimatorSet();
  set.play(ObjectAnimator
   .ofFloat(expandedImageView, View.X, startBounds.left))
   .with(ObjectAnimator
    .ofFloat(expandedImageView,
     View.Y,startBounds.top))
   .with(ObjectAnimator
    .ofFloat(expandedImageView,
View.SCALE_X, startScaleFinal))
   .with(ObjectAnimator
    .ofFloat(expandedImageView,
View.SCALE_Y, startScaleFinal));
  set.setDuration(mShortAnimationDuration);
  set.setInterpolator(new DecelerateInterpolator());
  set.addListener(new AnimatorListenerAdapter() {
  @Override
  public void onAnimationEnd(Animator animation) {
   thumbView.setAlpha(1f);
   expandedImageView.setVisibility(View.GONE);
   mCurrentAnimator = null;
  }
  @Override
  public void onAnimationCancel(Animator animation) {
   thumbView.setAlpha(1f);
   expandedImageView.setVisibility(View.GONE);
   mCurrentAnimator = null;
  }
  });
  set.start();
  mCurrentAnimator = set;
 }
 });
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

(0)

相关推荐

  • Android菜单(动画菜单、360波纹菜单)

    前言:Android菜单常用集合:FragmentTabHost系统菜单.上移式菜单.360波纹菜单.展开式菜单.详解注释,可直接拿来用! 效果: 开发环境:AndroidStudio2.1.2 部分代码(Activity) public class NormalActivity extends AppCompatActivity { private FragmentTabHost mTabHost; private String[] mTabTitle = new String[]{"首页&q

  • Android仿支付宝的头部伸缩动画效果

    Android5.0推出的MaterialDesign库包含了处理头部工具栏的多个控件,不但允许自定义顶部导航栏,而且导航栏高度是可以伸缩的.如此一来,一方面导航栏能够放得下更多控件,另一方面在用户想看具体内容时也能腾出更多的屏幕空间. 这么说可能比较抽象,那就先来看看两张导航栏的效果图,第一张是导航栏完全展开时的界面,此时页面头部的导航栏占据了较大部分的高度: 第二张是导航栏完全收缩时的界面,此时头部导航栏只剩矮矮的一个长条. 看起来很眼熟是不是,上面的截图正是仿支付宝首页的头部效果.如果你熟

  • Android中的popupwindow进入和退出的动画效果

    废话不多说了直接给大家贴代码了,具体代码如下所示: <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="0" android:toXDelta="0" andro

  • Android 动画实现几种方案

    Android 动画实现几种方案 在 Android 的 FrameWork 中,为我们提供三种动画的实现方式:逐帧(Frame)动画.视图/补间动画(View Animation)和属性动画(Property Animation).由于,这三种动画的实现方式和针对面不一样,应用的范围也有所区别,因此我们需要根据具体的需求来选择正确动画类型. 根据 SDK 中的描述,这三者的功能强大程度为:逐帧动画 < 视图动画 < 属性动画. 一.逐帧动画(Frame Animation) 该动画的方式就是

  • Android Activity进出动画三种方法

     Android Activity进出动画三种方法 实现activity的进出场动画总共有3种方式,下面会一一列出,首先给出示例的动画xml文件. 动画的xml文件 <?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromYDelta="

  • Android SpringAnimation弹性动画解析

    也许你想在Android上实现这种反弹的动画效果.Android Support Library 25.3.0引入了Dynamic-animation增强动画,里面提供了几个类用于使动画呈现实现真实的物理效果. 你会想,自己的动画里加上 BounceInterpolator或OvershootInterpolator 插值器也能达到这种效果,然而实际上达不到.当然你也可以自己写插值器,如果你不嫌麻烦的话. SpringAnimation弹性动画实现方法 gradle引入,最低支持API16 de

  • Android实现图片点击预览效果(zoom动画)

    参考:https://developer.android.google.cn/training/animation/zoom.html 1.创建Views 下面的布局包括了你想要zoom的大版本和小版本的view. 1.ImageButton是小版本的,能点击的,点击后显示大版本的ImageView. 2.ImageView是大版本的,可以显示ImageButton点击后的样式. 3.ImageView一开始是不可见的(invisible),当ImageButton点击后,它会实现zoom动画,

  • 基于Jquery制作图片文字排版预览效果附源码下载

    基于jQuery图文排版图片预览特效.这是一款基于jQuery+CSS3实现的鼠标点击图片弹出画廊切换特效. 效果图如下所示,怎么样感兴趣吗,感兴趣的朋友继续往下学习哦. 效果演示    源码下载 html代码: <div id="fullscreen"> <div id="fullscreen-inner"> <div id="fullscreen-inner-left" class="fullscree

  • input type=file 选择图片并且实现预览效果的实例

    通过<input />标签,给它指定type类型为file,可提供文件上传: accept:可选择上传类型,如:只要传图片,且不限制图片格式,为image/*: multiple:规定是否可以选择多个文件: 规定只可上传图片,且可以选择多个文件 <input type="file" accept="image/*" multiple="multiple"/> 当然,直接一个input type=file 只能选择上传的文件

  • jQuery实现图片上传预览效果功能完整实例【测试可用】

    本文实例讲述了jQuery实现图片上传预览效果功能.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>www.jb51.net jquery图片上传预览效果</title> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.j

  • JS实现图片剪裁并预览效果

    今天又疯狂学习了web前端的图片剪裁效果,可以有个区域来框住图片的某一部分,并可以预览框住的部分 效果图如下: 看着是不是很炫呢 简单介绍下实现方法吧 1.布局就是左右两块div,右边的好说,主要是左边的,左边的用绝对布局的方式分了3层,最下面一层是一个半透明的图片,中间一层是原图,但被剪切成只有一块,也只显示这一块,可以用clip:rect方法实现,然后最上面一层就是自己写的一个边框,在边框上加了8个点,分别给这8个点定义位置. 2.然后JS代码用了鼠标的点击事件来实现. 下面贴上自己的代码:

  • Vue+SSM实现图片上传预览效果

    现在的需求是:有一个上传文件按钮,当我们点击按钮时,可以选择需要上传的文件,确定后图片显示在界面上. 说明:本项目前端使用的Vue,后台用的SSM搭建的,服务器是Tomcat,数据库是MySQL 实现思路: 前端界面:当用户点击上传文件按钮,选中待上传图片并点击确认后,这时应该把图片数据传给后台.当后台经过处理后返回结果,前端在根据响应结果做后续工作. 后端:后台拿到前端传过来的数据时,将图片文件存到固定的文件夹下(这个问题是我思考了很久的,我认为应该存在服务器下,原先我是存在本地文件夹下,然后

  • JavaScript使用FileReader实现图片上传预览效果

    FileReader是HTML5 File API的一部分.它实现了一种异步文件读取机制.可以把FileReader想象为XMLHttpRequest,区别只是它读取的是文件系统,而不是远程服务器.为了读取文件中的数据,FileReader提供了如下几个方法. readAsText(file,encoding):以纯文本的方式读取文件,将读取到的文件保存到result属性中. readAsDataURL(file):读取文件并将文件以数据URI的形式保存在result属性中. readAsBin

  • Android实现本地图片选择及预览缩放效果

    在做项目时经常会遇到选择本地图片的需求,以前都是懒得写直接调用系统方法来选择图片,但是这样并不能实现多选效果,最近又遇到了,所以还是写一个demo好了,以后也方便使用.还是首先来看看效果: 显示的图片使用RecyclerView实现的,利用Glide来加载:下面弹出的图片文件夹效果是采用PopupWindow实现,这里比采用PopupWindow更方便,弹出显示的左边图片是这个文件夹里的第一张图片:选中的图片可以进行预览,使用网上一个大神写的来实现的:至于图片的获取是用ContentProvid

  • Android使用ViewPager实现图片滑动预览效果

    本文为大家分享了Android ViewPager实现图片滑动预览效果展示的具体代码,供大家参考,具体内容如下 效果图: 滑动前: 滑动后: 代码非常简单,实现起来很容易 xml代码: <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/ap

  • JS交互点击WKWebView中的图片实现预览效果

    Swift 4.0 WKWebView 1.注入js代码 (重点) func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { let jsGetImages = "function getImages(){" + "var objs = document.getElementsByTagName(\"img\");" + "var imgScr =

随机推荐