学习andriod开发之 图片翻转so easy

大家好我是akira 今天咱们玩一个非常好玩的东西 来先看下面一段短片

SO 这是什么 想必大家在上下班或者出入商场的时候太常见了 他就是一个旋转门而已

我们人跟着旋转门进去 然后再出来 就这么简单 可能还有更简单的 就是只有一个翻转的门

这种在我们看一些电影里面都有一些类似的几关或者密道都是采用这种门 只不过后者更为简单 只是将两扇门精简成了一扇

但是效果一样 当然咱们今天说的不是研究什么门的问题 咱们既然是移动开发人员 自然会思考这玩意在我们的

andriod客户端会怎么实现

咱们今天介绍一种非常简单的办法 用普通的动画就能实现 有人可能会惊讶 因为这个东西是涉及到3D的一些效果 那么你用2D的

动画是可以实现的么 答案是yes。因为我们知道我们的肉眼是容易被欺骗的 一个简单的例子就是我们大家都看过魔术 什么光影魔术

近景魔术 我们大家都非常清楚 魔术是假的 但是我们的肉眼却非常清晰的看到这个东西确实是非常神奇的消失在了魔术师手中 那么我们就可以得到一个结论 有时候肉眼是靠不住的 他反而会给我带来一种欺骗的感觉 下面的一个例子就是最好的证明

怎么样 上图的柱子是圆的还是方的 你究竟看出来了么 或者说是有三个柱子还是有两个柱子呢

OK 既然肉眼是可以欺骗的 那么我们就可以做一个伪3D效果 核心类就是我们动画中的缩放动画

我们根据经验得知 人在看远处物体时会发现物体变小了 而看近时 发现物体变大

这个正符合我们的ScaleAnimation的特点

下面 就用下这个ScaleAnimation

对于ScaleAnimation最模糊的一点无非是他的一个构造 来解释下这里的问题

/**
     * Constructor to use when building a ScaleAnimation from code
     *
     * @param fromX Horizontal scaling factor to apply at the start of the
     *        animation
     * @param toX Horizontal scaling factor to apply at the end of the animation
     * @param fromY Vertical scaling factor to apply at the start of the
     *        animation
     * @param toY Vertical scaling factor to apply at the end of the animation
     * @param pivotXType Specifies how pivotXValue should be interpreted. One of
     *        Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
     *        Animation.RELATIVE_TO_PARENT.
     * @param pivotXValue The X coordinate of the point about which the object
     *        is being scaled, specified as an absolute number where 0 is the
     *        left edge. (This point remains fixed while the object changes
     *        size.) This value can either be an absolute number if pivotXType
     *        is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
     * @param pivotYType Specifies how pivotYValue should be interpreted. One of
     *        Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
     *        Animation.RELATIVE_TO_PARENT.
     * @param pivotYValue The Y coordinate of the point about which the object
     *        is being scaled, specified as an absolute number where 0 is the
     *        top edge. (This point remains fixed while the object changes
     *        size.) This value can either be an absolute number if pivotYType
     *        is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
     */
    public ScaleAnimation(float fromX, float toX, float fromY, float toY,
            int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
        mResources = null;
        mFromX = fromX;
        mToX = toX;
        mFromY = fromY;
        mToY = toY;

        mPivotXValue = pivotXValue;
        mPivotXType = pivotXType;
        mPivotYValue = pivotYValue;
        mPivotYType = pivotYType;
        initializePivotPoint();
    }

这个是ScaleAnimation的构造源码 上面的注释已经很清楚的说明了 我们下面的参数都代表了什么

先看第一个 fromX 显然是从 后面的是to 显然是到 加上X就是X坐标

OK 这个理解了 后面两个Y自然也就不难 那么问题来了 后面的那四个是什么呢

我们发现 后面的那苏哥都对应一个type和value 而且是一个X和Y 显然也就是x和y轴 知道了这点之后

而看上面注释我们不难发现 这里的X和Y实际上是根据什么进行缩放 也就是我们经常说的参照物 Ok

简单了 接下来我们只需要知道有什么type这个事就搞定了

回到分析问题的轨迹上来 我们既然知道了缩放动画 我们不难得知旋转实际上就是一个缩进和展开的过程

只不过这里的缩进和展开进行了切换欺骗了我们的肉眼 让我们认为它是旋转着的

看下布局的代码

<LinearLayout 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"  tools:context=".MainActivity">

    <!--<TextView android:text="@string/hello_world" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />-->
    <ImageView
        android:id="@+id/img_ad"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/bg"
        android:scaleType="matrix"
        />

</LinearLayout>

就是一张图 很简单 这里你会发现 我指定了一个matrix 这是因为下面我们要使其在转的时候有一个镜像的效果

代码如下

public class MainActivity extends Activity {

    private ImageView mImageView;

    private ScaleAnimation out;
    private ScaleAnimation in;

    private boolean ismirror= false;//是否为镜像

    private MediaPlayer mPlayer;
    String path = "";//播放路径
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        if(mPlayer==null)
        mPlayer = new MediaPlayer();
//            MediaPlayer mp = MediaPlayer.create(this,R.m);//这时就不用
        try {
            mPlayer.setDataSource(path);
            mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mPlayer.prepare();
            mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mPlayer.start();

                }
            });

        } catch (IOException e) {
            e.printStackTrace();
        }
       /**/

        mImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Matrix matrix = new Matrix();
                if(!ismirror){
                    out = new ScaleAnimation(-1.0f,1.0f,1.0f,1.0f, Animation.RELATIVE_TO_PARENT,0.5f,Animation.RELATIVE_TO_PARENT,0.5f);
                    out.setDuration(1200);
                    out.setFillAfter(true);
                    mImageView.startAnimation(out);
                    matrix.postScale(-1, 1);//-1代表取相反数, 1 代表保持不变
                    matrix.postTranslate(mImageView.getMeasuredWidth(), 0);
                    mImageView.setImageMatrix(matrix);
                    ismirror = true;
                }else{
                    in = new ScaleAnimation(1.0f,-1.0f,1.0f,1.0f,Animation.RELATIVE_TO_PARENT,0.5f,Animation.RELATIVE_TO_PARENT,0.5f);
                    in.setDuration(1200);
                    in.setFillAfter(true);
                    mImageView.startAnimation(in);
//                    Matrix matrix =  mImageView.getMatrix();
//                    Matrix matrix = new Matrix();
                    matrix.postScale(1, 1);//-1代表取相反数, 1 代表保持不变
                    matrix.postTranslate(-mImageView.getMeasuredWidth(),0);
                    mImageView.setImageMatrix(matrix);
                    ismirror = false;
                   }

            }
        });
    }

    private void initView() {
        mImageView = (ImageView) findViewById(R.id.img_ad);

        }

    @Override
    protected void onDestroy() {
        mPlayer.stop();
        mPlayer=null;
        super.onDestroy();

    }
}

这里的代码比较简单 核心的旨在两个动画中 这里我们用一个布尔值做判断 是否为镜像

然后利用 postScale取反设置镜面效果 然后去平移这里都是用的post 不能用set和pre除非你是第一次

还有一点要注意的是postTranslate 这里平移的是位移而不是坐标 Ok 如果你还想使用音乐的话

可以利用mediaplayer进行一个播放 这里我没有做

PS:如果要播放最好建议利用service去做 正好也符合mvc思想

效果如下

下面还有一种情况是我们可能会遇到真的想变戏法一样的情况 就是说我转进去和转出来的不一样

其实这种也是利用了scaleanimation的特性 只不过 我们改变了参数而已

布局还是一张图

<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"  tools:context=".MainActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"
        android:background="@drawable/bg"
        />

</RelativeLayout>

代码却不是前面的代码

代码如下

public class MainActivity extends Activity {

    private ImageView mImageViwe;
    private ScaleAnimation inTwo;
    private ScaleAnimation outTwo;
    private boolean zero = true;//是否是第一张
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        mImageViwe.setOnClickListener(new MyOnImageCilckListener());

    }

    private void init() {
        mImageViwe = (ImageView) findViewById(R.id.image);
        inTwo = new ScaleAnimation(1.0f,0.0f,1.0f,1.0f, Animation.RELATIVE_TO_PARENT,0.5f, Animation.RELATIVE_TO_PARENT,0.5f);
        inTwo.setDuration(500);
        inTwo.setFillAfter(true);
        outTwo = new ScaleAnimation(0.0f,1.0f,1.0f,1.0f, Animation.RELATIVE_TO_PARENT,0.5f, Animation.RELATIVE_TO_PARENT,0.5f);
        outTwo.setDuration(500);
        outTwo.setFillAfter(true);
    }

    /*@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }*/
    class MyOnImageCilckListener implements View.OnClickListener{

        @Override
        public void onClick(View v) {
            if(zero){
                mImageViwe.startAnimation(inTwo);
                inTwo.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {

                        mImageViwe.startAnimation(outTwo);
                        Bitmap map2 =  BitmapFactory.decodeResource(getResources(), R.drawable.bg2);
                        mImageViwe.setImageBitmap(map2);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
                zero = false;
            }else{
                mImageViwe.startAnimation(inTwo);
                inTwo.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        mImageViwe.startAnimation(outTwo);
                        Bitmap map =  BitmapFactory.decodeResource(getResources(),R.drawable.bg);
                        mImageViwe.setImageBitmap(map);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
                zero = true;
            }

        }
    }
}

这个周期什么的都是你自己去定义 相反如果你不定义周期 那么你的动画将不会有任何效果

这里还是用布尔值做判断 我们发现由于是绕着中心去转动 所以当转没了 也就是动画结束后出现白屏之前 我们得要把下一张展现出来

这里就利用了animationListener这个监听 在onAnimationEnd结束的回调中去展示一张新的

好了 这样我们的第二种就做好了

看下效果

哈哈 买demo送零式 已经成了目前国内主机玩家的一个梗 不过个人还是非常期待FF新作的

本期咱们就到这 下期我和各位不见不散

时间: 2024-11-02 07:35:02

学习andriod开发之 图片翻转so easy的相关文章

学习andriod开发之 异步加载图片--- 使用系统进度条

大家好 我是akira 学习图片异步加载的例子 说道这里有人可能要问了 什么是异步 为什么要用异步 why? 说白了很简单 省时间 省资源 我举个例子你就懂了 比如你在下东西 至于下什么 那些邪恶的骚年们又要YY了 不去管他们.比如你在下东西 这个时候 另外一个人也在下同一个东西 那么那个人怎么办 他就等你下完 等到天荒地老?ありえないこと impossible 他肯定也要下 那么问题就来了 他如何下?这个时候就要用到异步 说道这里 有人可能问什么叫同步 什么叫异步 我在这里在给大家举一个简单的

学习andriod开发之 异步加载图片(二)--- 使用其他进度条

大家好 我是akira上一节 我们讲到使用AsyncTask 这个类进行异步的下载 主要是涉及到一些图片的更新 这次我们继续上一个demo的改进 . 不知道你是否发现一个问题 上一节我们遗留了两个bug 1 在无网络情况下 点击会崩 咱们说 软件开发最忌讳的就是crash 而这个是在bug解决方案中的一级要解决的 所以这个问题 必须搞定 2 就是我们会发现进度并未更新 而图片是显示完毕了的 3 就是一个扩展 这次我将会带来 daimajia的新库 也是做库小达人的最新作品 NumberProgr

C#程序员学习Android开发系列之Android项目的目录结构

今天开始正式学习Android开发的种种细节,首先从最基本的概念和操作学起. 首先看一下Android项目的目录结构. 这是我随便建立的一个test项目,我们重点关注一下几个方面的内容: 1.src目录:存放java源代码的目录,里面建立一个包,包里面有4个java源文件(分别都继承自Activity).由于java要求比较严格,因此要求类名与文件名一致. gen(Generated Java Files)目录:自动产生Java源文件的目录,是由工具自动生成的,一般不需要自己修改.里面主要有一个

【零基础学习iOS开发】【01-前言】02-准备

一.程序设计语言 上一讲已经说到:要想开发一款软件,首先得学习一些对应的程序设计语言. 至于iOS开发,须要学习的语言主要有:C.C++.Objective-C. 回到顶部 二.是否须要计算机专业知识 可能非常多人有这种疑问:学习编程一定得是计算机专业的么?这个不一定.有非常多程序猿曾经都不是计算机专业的,我身边有非常多这种样例. 有的在大学里是学物流管理的.学外语的.学金 融的.等等.事实上我也不是计算机专业的.也有一些人是从其它行业转过来的,比方曾经是修空调的.剪发的.当老师的,等等,他们如

Android开发之图片处理专题(三):利用ThreadPoolExcutor线程池实现多图片的异步加载

在上一篇专题Android开发之图片处理专题(二):利用AsyncTask和回调接口实现图片的异步加载和压缩中我们实现了listView的图片的大量加载.今天,我们换一种方式,采用线程池的方式来实现. 我们需要准备两个东西: 1.图片下载任务类 2.线程池. 1.图片下载任务类. 图片下载任务类,将需要显示的iamgeView,线程通讯消息管理者handler进行了封装.当图片下载无论成功还是失败,handler发送对应的消息,传入的iamgeView显示对应的图片.这里就不在应用软引用技术,采

20140613_JavaWeb学习之开发环境配置篇

本文所使用软件百度云盘网址:http://pan.baidu.com/s/1kTDRFwz 1安装JDK 操作系统:windows7-64bit 版本:jdk-7u51-windows-x64 安装路径(默认):C:\Program Files\Java\jdk1.7.0_51\ 安装到:C:\Program Files\Java\jre7\ 关闭, 安装完成. 2 配置环境变量 百度经验网址:http://jingyan.baidu.com/article/6dad5075d1dc40a123

新手篇——学习网页开发需要多长时间就能找到工作

近几年Web前端框架层出不穷,比如 React, Vue, AngulaJS等吸引了大量的注意力,前端技术发展势头迅猛,各大互联网公司也越来越重视前端开发,前端开发再也不是过去那种按照设计图做静态网页,再随便写点jQuery的职位了.现在,市场上对于前端开发的需求越来越大,我们经常听说前端开发入门难度低,但学习前端开发究竟需要多长时间呢?学多长时间就能找到工作赚到钱?结合了周边同事和自身的经验来谈谈学习网页开发到底需要花多长时间. Note:一定要下定决心,并且要坚持. 1. 网页设计的基本概念

学习IOS开发UI篇--UI知识点总结(一) UIButton/UITextField

UIkit框架下的几个基本控件,UIButton,UITextField,UILabel,UIImageView,UIScrollView,UITableView,UITableViewCell,UIPageControl; 他们的继承关系,UILabel,UIImageView,UIScrollView,UITableViewCell,直接继承自UIView; UIButton,UITextField,UIPageControl,继承自UIControl; UIControl继承自UIView

CSS3图片翻转切换案例及其中重要属性解析

图片翻转切换,在不使用CSS3的情况下,一般都是使用JS实现动画,同时操作元素的width和left,或者height和top以模拟翻转的效果,并在适当时候改变src或者z-index实现图片切换. 无意中发现CSS3的方案, http://www.webhek.com/css-flip/  赶紧学习并总结如下 先上代码(多数照搬自上述链接,有很大兼容问题,小心使用) HTML: <div class="flip-container"> <div class=&quo