Android共享元素轉(zhuǎn)場(chǎng)動(dòng)畫實(shí)現(xiàn)

本文主要講如何一步一步實(shí)現(xiàn)ImageView共享元素轉(zhuǎn)場(chǎng)動(dòng)畫禀忆,按照國(guó)際慣例绰播,先上效果圖:


Demo.gif
Demo.gif

實(shí)現(xiàn)思路一:

這里假設(shè)從Activity A跳轉(zhuǎn)到Activity B国拇,共享的元素是ImageView:

  1. 在Activity A中獲得共享a(ImageView)的位置信息,在跳轉(zhuǎn)時(shí)硼婿,移除Activity默認(rèn)的轉(zhuǎn)場(chǎng)動(dòng)畫并將a的位置信息傳給B怒见;

  2. 在B中接收a的位置信息俗慈,獲得B中的目標(biāo)b(ImageView)在布局中的位置;到這里就獲得了a和b兩個(gè)imageView的位置信息了遣耍;

  3. 改變b的位置和大小闺阱,使b完全和a位置重合;

  4. 對(duì)改變后的b進(jìn)行動(dòng)畫變換配阵,讓b恢復(fù)到改變前

注意:關(guān)于共享元素轉(zhuǎn)場(chǎng)馏颂,這里并不一定需要Activity B是背景透明的;如果Activity B是一個(gè)全屏顯示ImageView的activity棋傍,那么背景透明的情況下感覺(jué)體驗(yàn)稍微好一點(diǎn)救拉;但如果Activity B是一個(gè)含多控件的activity,則并沒(méi)有什么區(qū)別瘫拣。

Activity A的布局和源碼

A布局:
<?xml version="1.0" encoding="utf-8"?>
<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">

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="200dp"
        android:layout_height="120dp"
        android:scaleType="centerInside"
        android:src="@drawable/ic_one_piece"/>

</RelativeLayout>

為了方便闡述亿絮,這里的ImageView固定尺寸大小,固定使用scaleType為centerInside,引用的是本地資源,下文會(huì)詳細(xì)說(shuō)明這些的派昧。圖片ic_one_piece如下:

ic_one_piece.png
A源碼:
//設(shè)置顯示的圖片
final ImageView imageView = (ImageView)findViewById(R.id.iv_icon);
findViewById(R.id.iv_icon).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(RectActivity.this,RectDetailActivity.class);
                //創(chuàng)建一個(gè)Rect,保存當(dāng)前imageView的位置信息
                Rect rect = new Rect();
                //將位置信息賦給rect
                imageView.getGlobalVisibleRect(rect);
                //將位置信息賦給intent
                intent.setSourceBounds(rect);
                //activity跳轉(zhuǎn)
                startActivity(intent);
                //屏蔽activity跳轉(zhuǎn)的默認(rèn)轉(zhuǎn)場(chǎng)效果
                overridePendingTransition(0,0);
            }
        });

使用Rect保存ImageView的位置信息黔姜,并傳遞給Activity B,記得屏蔽activity A的默認(rèn)轉(zhuǎn)場(chǎng)效果.

Activity B的布局和源碼

B布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_gravity="center_vertical"
        android:scaleType="centerInside"
        android:layout_width="300dp"
        android:layout_height="180dp"/>

</FrameLayout>

B布局中的ImageView的scaleType和A中的一致,圖片的寬高比例也一致蒂萎;

B源碼:
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.example.demoshareimageview.R;

public class RectDetailActivity extends AppCompatActivity {

    private ImageView mImageView;
    //動(dòng)畫時(shí)間
    public static final int DURATION = 300;
    //動(dòng)畫插值器
    private static final AccelerateDecelerateInterpolator DEFAULT_INTERPOLATOR = new AccelerateDecelerateInterpolator();
    //上一個(gè)界面的圖片位置信息
    private Rect mSourceRect;
    //上一個(gè)界面的圖片的寬度
    private int mSourceWidth;
    //上一個(gè)界面的圖片的高度
    private int mSourceHeight;
    //當(dāng)前界面的目標(biāo)圖片的位置
    private Rect mTargetRect = new Rect();
    //前后兩個(gè)圖片的收縮比
    private float mScaleWidth, mScaleHeight;
    //前后兩個(gè)圖片的位移距離
    private float mTransitionX, mTransitionY;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rect_detail);
        //初始化控件
        initView();
        //初始化場(chǎng)景
        initBehavior();
    }

    /**
     * 初始化控件
     */
    private void initView(){
        mImageView = (ImageView)findViewById(R.id.iv_icon);
        //設(shè)置圖片,也可以直接在xml布局中設(shè)置:android:src="@drawable/ic_one_piece"
        mImageView.setImageResource(R.drawable.ic_one_piece);
    }

    /**
     * 初始化場(chǎng)景
     */
    private void initBehavior(){
        //獲取上一個(gè)界面?zhèn)鬟^(guò)來(lái)的Rect
        mSourceRect = getIntent().getSourceBounds();
        //計(jì)算上一個(gè)界面圖片的寬度和高度
        mSourceWidth = mSourceRect.right-mSourceRect.left;
        mSourceHeight = mSourceRect.bottom-mSourceRect.top;
        //當(dāng)界面的imageView測(cè)量完成后秆吵,即高度和寬度確定后
        mImageView.post(new Runnable() {
            @Override
            public void run() {
                //獲取目標(biāo)imageView在布局中的位置
                mImageView.getGlobalVisibleRect(mTargetRect);
                //更改mImageView的位置,使其和上一個(gè)界面的圖片的位置重合
                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(mSourceWidth,mSourceHeight);
                params.setMargins(mSourceRect.left,mSourceRect.top-getStatusBarHeight()-getActionBarHeight(),
                        mSourceRect.right,mSourceRect.bottom);
                mImageView.setLayoutParams(params);
                //計(jì)算圖片縮放比例和位移
                calculateInfo();
                // 設(shè)置入場(chǎng)動(dòng)畫
                runEnterAnim();
            }
        });
    }

    /**
     * 獲取狀態(tài)欄高度
     * @return
     */
    private int getStatusBarHeight() {
        //獲取status_bar_height資源的ID
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根據(jù)資源ID獲取響應(yīng)的尺寸值
            return getResources().getDimensionPixelSize(resourceId);
        }
        return -1;
    }

    /**獲取ActionBar高度
     * @return
     */
    private int getActionBarHeight(){
        //如果有ActionBar
        if(getSupportActionBar()!=null){
            return getSupportActionBar().getHeight();
        }
        return 0;
    }
    /**
     * 計(jì)算圖片縮放比例五慈,以及位移距離
     *
     */
    private void calculateInfo() {
        // 計(jì)算目標(biāo)imageView的寬高
        int targetWidth = mTargetRect.right - mTargetRect.left;
        int targetHeight = mTargetRect.bottom - mTargetRect.top;

        //獲得收縮比
        mScaleWidth = (float) targetWidth / mSourceWidth;
        mScaleHeight = (float) targetHeight / mSourceHeight;
        //x,y上的位移
        mTransitionX = (mTargetRect.left+(mTargetRect.right - mTargetRect.left) / 2)
                - (mSourceRect.left + (mSourceRect.right - mSourceRect.left) / 2);
        mTransitionY = (mTargetRect.top + (mTargetRect.bottom - mTargetRect.top) / 2)
                - (mSourceRect.top + (mSourceRect.bottom - mSourceRect.top) / 2);
    }

    /**
     * 入場(chǎng)動(dòng)畫:屬性動(dòng)畫
     */
    private void runEnterAnim() {
        mImageView.animate()
                .setInterpolator(DEFAULT_INTERPOLATOR)
                .setDuration(DURATION)
                .scaleX(mScaleWidth)
                .scaleY(mScaleHeight)
                .translationX(mTransitionX)
                .translationY(mTransitionY)
                //withEndAction要求版本在16以上
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
                    }
                })
                .start();
    }

    /**
     * 退場(chǎng)動(dòng)畫:屬性動(dòng)畫
     */
    private void runExitAnim() {
        mImageView.animate()
                .setInterpolator(DEFAULT_INTERPOLATOR)
                .setDuration(DURATION)
                .scaleX(1)
                .scaleY(1)
                .translationX(0)
                .translationY(0)
                //withEndAction要求版本在16以上
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        finish();
                        overridePendingTransition(0, 0);
                    }
                })
                .start();
    }

    @Override
    public void onBackPressed() {
        // 使用退場(chǎng)動(dòng)畫
        runExitAnim();
    }

}

首先從intent拿到A中imageView的位置信息mSourceRect纳寂,在B的imageView測(cè)量完成后,用mTargetRect保存泻拦,然后更改mImageView的位置毙芜,使其和A圖片的位置重合;對(duì)比mSourceRect和mTargetRect,計(jì)算出imageView的縮放比例和位移距離争拐,最后執(zhí)行入場(chǎng)動(dòng)畫腋粥。當(dāng)退出Activity時(shí),執(zhí)行退場(chǎng)動(dòng)畫架曹,記得屏蔽B退出的默認(rèn)轉(zhuǎn)場(chǎng)動(dòng)畫隘冲。到這里,一個(gè)初步的共享元素轉(zhuǎn)場(chǎng)動(dòng)畫就完成了音瓷。效果如下:

1.gif
1.gif

在上面的操作中对嚼,實(shí)際上是對(duì)兩個(gè)ImageView控件的轉(zhuǎn)場(chǎng)動(dòng)畫夹抗,并不是對(duì)兩個(gè)ImageView中圖片的轉(zhuǎn)場(chǎng)動(dòng)畫绳慎。由activity A和B的布局文件中看出imageView的大小是固定并且比例是“算好”的,目的就是使ImageView中的圖片能基本填充滿整個(gè)ImageView控件漠烧,從而在對(duì)控件作轉(zhuǎn)場(chǎng)時(shí)產(chǎn)生期望的效果杏愤。當(dāng)將B布局中ImageView的高度設(shè)為“400dp”時(shí),效果如下:

2.gif
2.gif

可以看到最終的imageView被拉伸了已脓,因?yàn)樗皇怯汕耙粋€(gè)imageView的放大拉伸得到的珊楼,顯示的內(nèi)容是一模一樣的,但很多時(shí)候度液,小圖和大圖并非一模一樣的厕宗,可能小圖所顯示的圖片是被截掉一部分的,而大圖則是完全顯示出來(lái)的堕担;除此之外已慢,還有一個(gè)問(wèn)題:在一般的應(yīng)用場(chǎng)景中,ImageView的圖片常常不會(huì)鋪滿整個(gè)控件的霹购,上面的方法中佑惠,作縮放時(shí)是以ImageView控件的寬高為比例,這是不對(duì)的,正確的應(yīng)該是以imageView內(nèi)實(shí)際繪制的圖片的寬高為比例膜楷。我們接著改進(jìn)一下:
由于我們需要知道ImageView內(nèi)實(shí)際繪制圖片的寬高旭咽,所以需要拿到activity A的實(shí)際圖片寬高。保持activity A的布局不變赌厅,修改A源碼穷绵。

A源碼:
private int mSourceDrawableWidth;
private int mSourceDrawableHeight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawable);
        //設(shè)置顯示的圖片
        final ImageView imageView = (ImageView)findViewById(R.id.iv_icon);
        findViewById(R.id.iv_icon).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(DrawableActivity.this,DrawableDetailActivity.class);
                //創(chuàng)建一個(gè)Rect,保存當(dāng)前imageView的位置信息
                Rect rect = new Rect();
                //將位置信息賦給rect
                imageView.getGlobalVisibleRect(rect);
                //將位置信息賦給intent
                intent.setSourceBounds(rect);
                //計(jì)算imageView中顯示圖片的實(shí)際繪制的寬高
                calDrawableWidthAndHeight(imageView);
                intent.putExtra("sourceDrawableWidth", mSourceDrawableWidth);
                intent.putExtra("sourceDrawableHeight", mSourceDrawableHeight);
                //activity跳轉(zhuǎn)
                startActivity(intent);
                //屏蔽activity跳轉(zhuǎn)的默認(rèn)轉(zhuǎn)場(chǎng)效果
                overridePendingTransition(0,0);
            }
        });
    }

    /**計(jì)算imageView中顯示圖片的實(shí)際繪制的寬高
     * @param imageView
     */
    private void calDrawableWidthAndHeight(ImageView imageView){
        Drawable imgDrawable = imageView.getDrawable();
        if (imgDrawable != null) {
            //獲得ImageView中Image的真實(shí)寬高,
            int dw = imageView.getDrawable().getBounds().width();
            int dh = imageView.getDrawable().getBounds().height();

            //獲得ImageView中Image的變換矩陣
            Matrix m = imageView.getImageMatrix();
            float[] values = new float[10];
            m.getValues(values);

            //Image在繪制過(guò)程中的變換矩陣特愿,從中獲得x和y方向的縮放系數(shù)
            float sx = values[0];
            float sy = values[4];

            //計(jì)算Image在屏幕上實(shí)際繪制的寬高
            mSourceDrawableWidth = (int) (dw * sx);
            mSourceDrawableHeight = (int) (dh * sy);
        }
    }

這里多做一個(gè)事情:獲取ImageView內(nèi)的實(shí)際繪制圖片的寬高并傳遞給activity B请垛。

B布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/ll_rootView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_icon"
        android:visibility="invisible"
        android:layout_gravity="center_vertical"
        android:scaleType="centerInside"
        android:layout_width="300dp"
        android:layout_height="180dp"/>

</FrameLayout>

稍微修改B布局,將imageView設(shè)為不可見(jiàn)洽议。注意宗收,這里要使用android:visibility="invisible",而不是android:visibility="gone",因?yàn)橐谶\(yùn)行過(guò)程中測(cè)量imageView的寬高亚兄,設(shè)為gone就拿不到寬高了混稽。

B源碼:
public class DrawableDetailActivity extends AppCompatActivity {

    private FrameLayout llRootView;
    private ImageView mImageView;
    private ImageView mTempImageView;
    //動(dòng)畫時(shí)間
    public static final int DURATION = 300;
    //動(dòng)畫插值器
    private static final AccelerateDecelerateInterpolator DEFAULT_INTERPOLATOR = new AccelerateDecelerateInterpolator();
    //上一個(gè)界面的圖片位置信息
    private Rect mSourceRect;
    //上一個(gè)界面的imageView的寬度
    private int mSourceWidth;
    //上一個(gè)界面的imageView的高度
    private int mSourceHeight;
    //上一個(gè)界面,imageView內(nèi)容繪制圖片的實(shí)際寬度
    private int mSourceDrawableWidth;
    //上一個(gè)界面审胚,imageView內(nèi)容繪制圖片的實(shí)際高度
    private int mSourceDrawableHeight;
    //當(dāng)前界面的目標(biāo)圖片的位置
    private Rect mTargetRect = new Rect();
    //前后兩個(gè)圖片的收縮比
    private float mScaleWidth, mScaleHeight;
    //前后兩個(gè)圖片的位移距離
    private float mTransitionX, mTransitionY;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawable_detail);
        //初始化控件
        initView();
        //初始化場(chǎng)景
        initBehavior();
    }

    /**
     * 初始化控件
     */
    private void initView(){
        llRootView = (FrameLayout)findViewById(R.id.ll_rootView);
        mImageView = (ImageView)findViewById(R.id.iv_icon);
        //設(shè)置圖片,也可以直接在xml布局中設(shè)置:android:src="@drawable/ic_one_piece"
        mImageView.setImageResource(R.drawable.ic_one_piece);
    }

    /**
     * 初始化場(chǎng)景
     */
    private void initBehavior(){
        //獲取上一個(gè)界面?zhèn)鬟^(guò)來(lái)的Rect
        mSourceRect = getIntent().getSourceBounds();
        //計(jì)算上一個(gè)界面圖片的寬度和高度
        mSourceWidth = mSourceRect.right-mSourceRect.left;
        mSourceHeight = mSourceRect.bottom-mSourceRect.top;
        mSourceDrawableWidth = getIntent().getIntExtra("sourceDrawableWidth",0);
        mSourceDrawableHeight = getIntent().getIntExtra("sourceDrawableHeight",0);
        //當(dāng)界面的imageView測(cè)量完成后匈勋,即高度和寬度確定后
        mImageView.post(new Runnable() {
            @Override
            public void run() {
                //獲取目標(biāo)imageView在布局中的位置
                mImageView.getGlobalVisibleRect(mTargetRect);
                mTempImageView = new ImageView(DrawableDetailActivity.this);
                mTempImageView.setImageResource(R.drawable.ic_one_piece);
                mTempImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
                //更改mTempImageView的位置,使其和上一個(gè)界面的圖片的位置重合
                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(mSourceWidth,mSourceHeight);
                params.setMargins(mSourceRect.left,mSourceRect.top-getStatusBarHeight()-getActionBarHeight(),mSourceRect.right,mSourceRect.bottom);
                mTempImageView.setLayoutParams(params);
                //把view添加進(jìn)來(lái)
                llRootView.addView(mTempImageView);
                //計(jì)算圖片縮放比例和位移
                calculateInfo();
                // 設(shè)置入場(chǎng)動(dòng)畫
                runEnterAnim();
            }
        });
    }

    /**
     * 獲取狀態(tài)欄高度
     * @return
     */
    private int getStatusBarHeight() {
        //獲取status_bar_height資源的ID
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根據(jù)資源ID獲取響應(yīng)的尺寸值
            return getResources().getDimensionPixelSize(resourceId);
        }
        return -1;
    }

    /**獲取ActionBar高度
     * @return
     */
    private int getActionBarHeight(){
        //如果有ActionBar
        if(getSupportActionBar()!=null){
            return getSupportActionBar().getHeight();
        }
        return 0;
    }
    /**
     * 計(jì)算圖片縮放比例膳叨,以及位移距離
     *
     */
    private void calculateInfo() {
        // 計(jì)算目標(biāo)imageView的中實(shí)際繪制圖片的寬高
        int targetDrawableWidth = 0;
        int targetDrawableHeight = 0;
        Drawable imgDrawable = mImageView.getDrawable();
        if (imgDrawable != null) {
            //獲得ImageView中Image的真實(shí)寬高洽洁,
            int dw = mImageView.getDrawable().getBounds().width();
            int dh = mImageView.getDrawable().getBounds().height();

            //獲得ImageView中Image的變換矩陣
            Matrix m = mImageView.getImageMatrix();
            float[] values = new float[10];
            m.getValues(values);

            //Image在繪制過(guò)程中的變換矩陣,從中獲得x和y方向的縮放系數(shù)
            float sx = values[0];
            float sy = values[4];

            //計(jì)算Image在屏幕上實(shí)際繪制的寬高
            targetDrawableWidth = (int) (dw * sx);
            targetDrawableHeight = (int) (dh * sy);
        }

        //獲得收縮比
        mScaleWidth = (float) targetDrawableWidth / mSourceDrawableWidth;
        mScaleHeight = (float) targetDrawableHeight / mSourceDrawableHeight;
        //x,y上的位移
        mTransitionX = (mTargetRect.left+(mTargetRect.right - mTargetRect.left) / 2)
                - (mSourceRect.left + (mSourceRect.right - mSourceRect.left) / 2);
        mTransitionY = (mTargetRect.top + (mTargetRect.bottom - mTargetRect.top) / 2)
                - (mSourceRect.top + (mSourceRect.bottom - mSourceRect.top) / 2);
    }

    /**
     * 入場(chǎng)動(dòng)畫:屬性動(dòng)畫
     */
    private void runEnterAnim() {
        mTempImageView.animate()
                .setInterpolator(DEFAULT_INTERPOLATOR)
                .setDuration(DURATION)
                .scaleX(mScaleWidth)
                .scaleY(mScaleHeight)
                .translationX(mTransitionX)
                .translationY(mTransitionY)
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        mTempImageView.setVisibility(View.INVISIBLE);
                        mImageView.setVisibility(View.VISIBLE);
                    }
                })
                .start();
    }

    /**
     * 退場(chǎng)動(dòng)畫:屬性動(dòng)畫
     */
    private void runExitAnim() {
        if(mTempImageView==null){
            finish();
            return;
        }
        mImageView.setVisibility(View.INVISIBLE);
        mTempImageView.setVisibility(View.VISIBLE);
        mTempImageView.animate()
                .setInterpolator(DEFAULT_INTERPOLATOR)
                .setDuration(DURATION)
                .scaleX(1)
                .scaleY(1)
                .translationX(0)
                .translationY(0)
                //withEndAction要求版本在16以上
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        finish();
                        overridePendingTransition(0, 0);
                    }
                })
                .start();
    }

    @Override
    public void onBackPressed() {
        // 使用退場(chǎng)動(dòng)畫
        runExitAnim();
    }

}

這里的思路和第一種思路不一樣的地方是:在activity B中拿到上一個(gè)imageView的信息后菲嘴,創(chuàng)建一個(gè)臨時(shí)的mTempImageView饿自,并將這個(gè)view覆蓋原位置,再拿這個(gè)view做轉(zhuǎn)場(chǎng)動(dòng)畫龄坪,動(dòng)畫完成后昭雌,隱藏這個(gè)臨時(shí)的imageView,顯示實(shí)際在布局中編寫的目標(biāo)ImageView刨疼;當(dāng)退出activity B時(shí)叙量,也是使用臨時(shí)imageView實(shí)現(xiàn)轉(zhuǎn)場(chǎng)動(dòng)畫。現(xiàn)在無(wú)論我們?nèi)绾卧O(shè)置imageView的位置和寬高比例缝彬,都能達(dá)到期望的效果了妓局,如下:

3.gif
3.gif

現(xiàn)在基本能達(dá)到期望效果了总放,那么問(wèn)題來(lái)了,在上述的操作中好爬,ImageView的ScaleType都是centerInside局雄,如果前后兩個(gè)activity中ImageView的ScaleType不一樣呢?假設(shè)將activity A中的ScaleType設(shè)置為centerCrop抵拘,ImageView的寬度從180dp設(shè)置為100dp哎榴,達(dá)到A中圖片顯示不全的目的型豁;activity B中的ScaleType設(shè)置為centerInside(注意:臨時(shí)創(chuàng)建的mTempImageView也需要設(shè)置為centerCrop),將動(dòng)畫時(shí)間延遲到800尚蝌,看到的效果如下:

4.gif
4.gif

可以看到在動(dòng)畫結(jié)束的時(shí)候迎变,圖片突然從顯示不全變成完整顯示,顯得較為突兀飘言。對(duì)于這種情況衣形,我的做法是縮短動(dòng)畫時(shí)間,比如說(shuō)縮短到100姿鸿,讓視覺(jué)上不容易觀察到突變谆吴。

更多

上面所描述的情況都是基于本地資源圖片的,對(duì)于網(wǎng)絡(luò)請(qǐng)求的圖片該如何處理呢苛预,如何實(shí)現(xiàn)從列表activity到列表activity的共享轉(zhuǎn)場(chǎng)呢句狼?限于篇幅,下篇文章再說(shuō)...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末热某,一起剝皮案震驚了整個(gè)濱河市腻菇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌昔馋,老刑警劉巖筹吐,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異秘遏,居然都是意外死亡丘薛,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門邦危,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)洋侨,“玉大人,你說(shuō)我怎么就攤上這事铡俐』硕遥” “怎么了妥粟?”我有些...
    開(kāi)封第一講書人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵审丘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我勾给,道長(zhǎng)滩报,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任播急,我火速辦了婚禮脓钾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘桩警。我一直安慰自己可训,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著握截,像睡著了一般飞崖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谨胞,一...
    開(kāi)封第一講書人閱讀 50,021評(píng)論 1 291
  • 那天固歪,我揣著相機(jī)與錄音,去河邊找鬼胯努。 笑死牢裳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的叶沛。 我是一名探鬼主播蒲讯,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼灰署!你這毒婦竟也來(lái)了伶椿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤氓侧,失蹤者是張志新(化名)和其女友劉穎脊另,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體约巷,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡偎痛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了独郎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片踩麦。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖氓癌,靈堂內(nèi)的尸體忽然破棺而出谓谦,到底是詐尸還是另有隱情,我是刑警寧澤贪婉,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布反粥,位于F島的核電站,受9級(jí)特大地震影響疲迂,放射性物質(zhì)發(fā)生泄漏才顿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一尤蒿、第九天 我趴在偏房一處隱蔽的房頂上張望郑气。 院中可真熱鬧,春花似錦腰池、人聲如沸尾组。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)讳侨。三九已至匕争,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間爷耀,已是汗流浹背甘桑。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歹叮,地道東北人跑杭。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像咆耿,于是被迫代替她去往敵國(guó)和親德谅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,851評(píng)論 25 707
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程萨螺,因...
    小菜c閱讀 6,375評(píng)論 0 17
  • 假設(shè)窄做,兩個(gè)有Activity A和B A啟動(dòng)B: A發(fā)生exit動(dòng)畫,B發(fā)生enter動(dòng)畫 B返回A:B發(fā)生ret...
    i冰點(diǎn)閱讀 17,243評(píng)論 7 42
  • 如果當(dāng)初我輕一點(diǎn)愛(ài)你 就不必在深夜里緬懷愛(ài)情 如果當(dāng)初我輕一點(diǎn)愛(ài)你 就不會(huì)在今夜想起學(xué)校食堂的樓梯 宿舍門口的超市...
    櫻花米米閱讀 418評(píng)論 0 0
  • 第十三天 但是……?ˉ?ˉ?…傻蛋沒(méi)有不爽慰技, 也沒(méi)有嫌我找麻煩 都很清楚詳細(xì)的解釋了原因 我也都給狗蛋看了 到了下...
    優(yōu)雅的爪牙閱讀 278評(píng)論 0 0