参考: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;
}
});
}

zoom动画,实现图片点击预览效果的更多相关文章

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

    为大家带来一篇input type=file 选择图片并且实现预览效果的实例. 通过<input />标签,给它指定type类型为file,可提供文件上传: accept:可选择上传类型, ...

  2. 用html5文件api实现移动端图片上传&预览效果

    想要用h5在移动端实现图片上传&预览效果,首先要了解html5的文件api相关知识(所有api只列举本功能所需): 1.Blob对象  Blob表示原始二进制数据,Html5的file对象就继 ...

  3. Jquery图片上传预览效果

    uploadPreview.js jQuery.fn.extend({ uploadPreview: function (opts) { var _self = this, _this = $(thi ...

  4. input type=file 选择图片并且实现预览效果

    通过<input />标签,给它指定type类型为file,可提供文件上传: accept:可选择上传类型,如:只要传图片,且不限制图片格式,为image/*: multiple:规定是否 ...

  5. JS实现图片上传预览效果:方法一

    <script type="text/javascript"> //处理file input加载的图片文件 $(document).ready(function(e) ...

  6. input file图片上传预览效果

    两种方法,方法一: js代码: //头像上传预览 $("#up").change(function() { var $file = $(this); var fileObj = $ ...

  7. 使用iframe实现图片上传预览效果

    原理:将图片上传的页面放在iframe中,这样就可以在iframe中将图片提交到服务器而不需要页面刷新,提交成功后用脚本实现主页面显示上传的图片. Default.aspx: <%@ Page ...

  8. ASP.NET工作笔记之一:图片上传预览及无刷新上传

    转自:http://www.cnblogs.com/sibiyellow/archive/2012/04/27/jqueryformjs.html 最近项目里面涉及到无刷新上传图片的功能,其实也就是上 ...

  9. ivew-admin 点击预览图片

    1. ivew-admin table { title: '产品图片', key: 'avatar1', align: 'center', render: (h, params) => { re ...

随机推荐

  1. BZOJ 1050: [HAOI2006]旅行comf (并查集 或 单调队列)

    这是建空间后做的第一道题啊= =好水 排序,枚举最小边,然后并查集求出联通时的最大边 或者排次序,从小到大插边,如果插边时最小的边拿掉不会使s与t不联通,就删去。 code: #include< ...

  2. android学习3——长宽的单位问题dp,px,dpi

    android设备的单位px,pt,dp,sp 分辨率 先通俗说下分辨率的概念.可以把屏幕想想成一个个正方形格子组成的.如果横向有1280个格子,竖向有720个格子.那么分辨率就是1280*720.这 ...

  3. TCP详解

    1. 数据进入协议栈的封装过程 2. TCP连接的三次握手 3. TCP连接的三次握手和关闭时的四次握手 各个状态的意义如下: LISTEN - 侦听来自远方TCP端口的连接请求: SYN-SENT ...

  4. Activiti工作流(一)之基本操作介绍

    工作流的概念: 工作流(Workflow),就是"业务过程的部分或整体在计算机应用环境下的自动化",它主要解决的是"使在多个参与者之间按照某种预定义的规则传递文档.信息或 ...

  5. 前端数据统计用做Bootstrap的一些柱状图、饼状图和折线图案例

    Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷. Bootstrap ...

  6. PHP中include()与require()的区别

    require 的使用方法如 require("MyRequireFile.php"); .这个函数通常放在 PHP 程序的最前面,PHP 程序在执行前,就会先读入 require ...

  7. Boot Sector - Hello world

    1. code bits org 7c00h mov ax, cs mov ds, ax mov es, ax call DispStr jmp $ DispStr: mov ax, BootMess ...

  8. 文件系统:ext4,zfs测评结果

    测试环境 操作系统:ubuntu16.04 内核版本: 磁盘: 本人使用的是青云的云主机,磁盘使用的其性能型: Cpu信息: 4核 2399MHz 内存:8G 文件系统: 本人使用的是ubuntu16 ...

  9. 项目架构开发:数据访问层之UnitOfWork

    接上文 项目架构开发:数据访问层之IQuery 本章我们继续IUnitOfWork的开发,从之前的IRepository接口中就可以看出,我们并没有处理单元事务, 数据CUD每次都是立即执行的,这样有 ...

  10. 如何用好消息推送(JPush)为app拉新、留存、促活

    如何用好消息推送(JPush)为app拉新.留存.促活 作为移动端APP产品运营最重要的运营手段,消息推送(JPush)被越来越多的APP厂商所重视,在信息泛滥的移动互联网时代,手机APP应用安装得越 ...