`
pjwqq
  • 浏览: 81469 次
社区版块
存档分类
最新评论

Demo_ ZoomActivity 解读

阅读更多

     这个是developer.android.com的demo,初学android,做下笔记.

 

     目的: 实现点击缩略图,动画放大为大图,点击大图,反向动画为缩略图.

 

     思路: 最外层用FrameLayout,便于将加载大图的ImageView覆盖在缩略图之上,先将此imageView隐藏,动画时再显示. 

     layout

<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">

        <TextView style="?android:textAppearanceSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/message_zoom_touch_expand" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:orientation="horizontal">

            <!-- TouchHighlightImageButton是一个自定义ImageButton,点击时盖上一层半透明图层,以标识focused 和 pressed 状态-->

            <com.example.android.animationsdemo.TouchHighlightImageButton
                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" />

            <com.example.android.animationsdemo.TouchHighlightImageButton
                android:id="@+id/thumb_button_2"
                android:layout_width="100dp"
                android:layout_height="75dp"
                android:src="@drawable/thumb2"
                android:scaleType="centerCrop"
                android:contentDescription="@string/description_image_2" />

        </LinearLayout>

    </LinearLayout>
    <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>

  ZoomActivity

package com.example.android.animationsdemo;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;

public class ZoomActivity extends FragmentActivity {
    /**
     * 存放属性动画对象,方便后面中途取消动画时用.
     */
    private Animator mCurrentAnimator;

    /**
     * 动画过场时间
     */
    private int mShortAnimationDuration;

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

        //这里没什么好说的,thumb1View ,thumb2View 2个缩略图

        final View thumb1View = findViewById(R.id.thumb_button_1);
        thumb1View.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                zoomImageFromThumb(thumb1View, R.drawable.image1);
            }
        });

        final View thumb2View = findViewById(R.id.thumb_button_2);
        thumb2View.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                zoomImageFromThumb(thumb2View, R.drawable.image2);
            }
        });

        mShortAnimationDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);
       // mShortAnimationDuration = 2000; 可以改长一点观察动画的详细过程
    }


     //无关,不解释
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

   

     /*
     * @param thumbView  要放大的缩略图View.
     * @param imageResId 大图Id.
     */
    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);

        //重点开始: 计算动画的开始和结束边界,其实就是计算2个矩形
        final Rect startBounds = new Rect();
        final Rect finalBounds = new Rect();
        final Point globalOffset = new Point();

        // 获得缩略图的矩形,注意:使用的是绝对坐标,相对于全屏
        thumbView.getGlobalVisibleRect(startBounds);
        
        //获得大图的(这里是放置大图的FrameLayout,一回事)的矩形,和偏移量
        //所谓"偏移量",指绝对坐标和相对坐标之差,之于为什么要这么干,因为属性动画中用的全是相对坐标
        findViewById(R.id.container).getGlobalVisibleRect(finalBounds, globalOffset);
        
        //用偏移量修正2个矩形
        startBounds.offset(-globalOffset.x, -globalOffset.y);
        finalBounds.offset(-globalOffset.x, -globalOffset.y);
        
        // 1.计算高和宽的Scale,
        // 2.如果缩略图和大图的高宽比不一样,先在startBounds中修正它
        //    因为动画过程中出现拉伸的状况就不美了,我没测试过
        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;
        }

        // 准备开场,先将缩略图隐藏,接下来是大图的动画,跟它无关了.
        thumbView.setAlpha(0f);
        expandedImageView.setVisibility(View.VISIBLE);

        // 设置动画开始的SCALE_X 和SCALE_Y变化的左上角原点,如果不设置的话默认从View的center开始
        expandedImageView.setPivotX(0f);
        expandedImageView.setPivotY(0f);

        // 到这就没啥好说的了
        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))//最后的Scale肯定是1
                .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;

        //放大后再点击,缩回原状 
        final float startScaleFinal = startScale;
        expandedImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mCurrentAnimator != null) {
                    mCurrentAnimator.cancel();
                }

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

 

   主要知识点: 

       1. 绝对坐标及相对坐标的获取和转换, getGlobalVisibleRect(Rect r, Point offset);

       2. 属性动画使用的一些注意点,比如SCALE_X 和SCALE_Y变化原点的设置等.

 

   附上一个效果图



 

  • 大小: 228.9 KB
1
3
分享到:
评论
4 楼 pjwqq 2015-02-11  
pansong291PS 写道
pjwqq 写道
pansong291PS 写道
您好,请问那个图片是用什么做到的?谢谢

gifcam,gif录像

您好,请问有安卓机上使用的吗?谢谢

没,这个是PC上录的模拟器录像
3 楼 pansong291PS 2015-02-10  
pjwqq 写道
pansong291PS 写道
您好,请问那个图片是用什么做到的?谢谢

gifcam,gif录像

您好,请问有安卓机上使用的吗?谢谢
2 楼 pjwqq 2015-02-10  
pansong291PS 写道
您好,请问那个图片是用什么做到的?谢谢

gifcam,gif录像
1 楼 pansong291PS 2015-02-09  
您好,请问那个图片是用什么做到的?谢谢

相关推荐

    STM32开发工具 DfuSe_Demo_V3.0

    STM32开发工具 DfuSe_Demo_V3.0STM32开发工具 DfuSe_Demo_V3.0STM32开发工具 DfuSe_Demo_V3.0STM32开发工具 DfuSe_Demo_V3.0STM32开发工具 DfuSe_Demo_V3.0STM32开发工具 DfuSe_Demo_V3.0STM32开发工具 DfuSe_Demo_V...

    flash_loader_demo_v2.8.0

    《STM32串口下载程序:flash_loader_demo_v2.8.0详解》 在嵌入式系统开发中,STM32系列微控制器因其高性能、低功耗的特点,被广泛应用。其中,程序的烧录与更新是开发过程中的重要环节。本文将详细解析STM32的串口...

    DfuSe_Demo_V3.0.5_Setup

    "DfuSe_Demo_V3.0.5_Setup" 是一个针对STM32设备进行固件升级的工具,它利用了Device Firmware Upgrade(DFU)模式,这是一种通过USB接口对微控制器进行无硬件编程器的程序烧录方法。 DFU模式是STMicroelectronics...

    mmWave_Demo_Visualizer_3_毫米波雷达_DEMO

    "mmWave_Demo_Visualizer_3_毫米波雷达_DEMO"是一个用于展示和理解毫米波雷达功能的可视化工具。这个工具通过模拟和分析毫米波雷达数据,帮助用户直观地了解其工作原理和应用。 首先,毫米波雷达工作在毫米波频段,...

    DfuSe_Demo_V3.0.6_Setup.exe

    DfuSe_Demo_V3.0.6_Setup.exe DfuSe_Demo_V3.0.6_Setup.exe DfuSe_Demo_V3.0.6_Setup.exe DfuSe_Demo_V3.0.6_Setup.exe DfuSe_Demo_V3.0.6_Setup.exe

    SC92F8003_Demo_Code_SC92F8003_赛元_DEMO_赛元单片机_SC92F8003_Demo_Code_

    SC92F8003_Demo_Code 赛元单片机

    Ext_Demo.rar_DEMO_Ext demo_ext_demo_java ext demo_javaext demo

    【标题】"Ext_Demo.rar_DEMO_Ext demo_ext_demo_java ext demo_javaext demo" 指示了一个关于Java与EXT.js集成的演示项目。EXT是一个强大的JavaScript库,用于构建富客户端应用程序,而Java通常在后端提供数据和服务...

    Demo_writtengya_DEMO_应广demo_应广程序_demo应广_源码

    【标题】"Demo_writtengya_DEMO_应广demo_应广程序_demo应广_源码" 提供的是一个关于应广单片机的演示程序合集,其中包含了源代码,适合对单片机编程感兴趣的开发者进行学习和参考。 在单片机编程领域,源码是理解...

    DfuSe_Demo_V3.0.1安装包(32位+64位)

    标题中的"DfuSe_Demo_V3.0.1安装包(32位+64位)"意味着这是一个包含了32位和64位版本的DfuSe演示软件的安装程序。这表明软件已经考虑到了不同操作系统平台的需求,无论是基于32位还是64位架构的Windows系统,都能...

    DfuSe_Demo_V3.0 STM32 usb升级程序的工具

    【标题】:“DfuSe_Demo_V3.0 STM32 USB升级程序工具” 这个工具是专门用于STM32微控制器的USB固件更新(DFU:Device Firmware Upgrade)过程的,版本为V3.0。STM32是意法半导体(STMicroelectronics)推出的一款...

    K-Studio-Demo_x64_1.2.4.0.zip

    标题中的“K-Studio-Demo_x64_1.2.4.0.zip”表明这是一个名为K-Studio的演示版本,适用于64位操作系统,其版本号为1.2.4.0。这个软件可能是一个专业级的3D建模或编辑工具,提供对STL(标准三角形语言)文件的支持。 ...

    demo.zip_DEMO_php demo_php webdemo_smarty_smarty demo

    【标题】"demo.zip_DEMO_php demo_php webdemo_smarty_smarty demo" 指示这是一个包含PHP开发演示的压缩包,重点展示了PHP在构建Web应用程序中的应用,特别是结合了Smarty模板引擎的使用。 【描述】"经典的PHP网站...

    demo_3.5.record

    Apollo demo record

    超精简版cef.160527.rar_cef demo_replaceapp_soui_soui demo_精简cef

    一个精简版的CEF和SOUI搭配使用的demo。仅供大家学习。

    ps_demo_python_test

    ps_demo_python_test

    实验1 driver_demo_exp.rar_DEMO_QT_QT driver demo_pondwnd_test driv

    标题中的"driver_demo_exp.rar_DEMO_QT_QT driver demo_pondwnd_test driv"暗示了这是一个关于QT框架下的驱动程序(driver)演示项目,其中可能包含一个名为"pondwnd_test"的特定驱动示例。描述指出这是一个用于学习...

    flash_loader_demo_v2.8.0.7z

    STM32读写保护解锁 官方程序

    zedGraph_demo_5.0.9

    《zedGraph_demo_5.0.9:深入理解与应用》 zedGraph是一个强大的图表绘制库,主要用于.NET Framework环境下的Windows Forms和Web Forms应用程序。zedGraph_demo_5.0.9是一个包含zedGraph最新版本5.0.9的示例程序和...

Global site tag (gtag.js) - Google Analytics