欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-11-30 17:24:16
参考: 1.创建views 下面的布局包括了你想要zoom的大版本和小版本的view。 1.imagebutton是小版本的,能点击的,点击后显示大版本的imagev...

参考:

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;
 }
 });
}

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