使用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.image).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ShareView.get()
.activity(MainActivity.this)
.shareView(findViewById(R.id.image))
.startActivity(new Intent(getApplicationContext(),SecondAct.class));
}
});
}
}
activity_main.xml
<?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:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wanjian.shareview.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="First Act"/>
<LinearLayout
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@drawable/img"/>
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginLeft="5dp"
android:src="@drawable/img"/>
</LinearLayout>
</RelativeLayout>
public class SecondAct extends AppCompatActivity {
String TAG = "AnimView";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sec);
ShareView.get().activity(this).shareView(findViewById(R.id.image)).onCreate(new ShareView.AnimListener() {
@Override
public void onStart() {
Log.d(TAG, "onStart: ");
}
@Override
public void onUpdate(float degree) {
//Log.d(TAG, "onUpdate: " + degree);
}
@Override
public void onEnd() {
Log.d(TAG, "onEnd: ");
}
});
View v=findViewById(R.id.image);
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ShareView.get().activity(SecondAct.this).shareView(v).startActivity(new Intent(getApplicationContext(),ThreedAct.class));
}
});
}
}
activity_sec.xml
<?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:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wanjian.shareview.MainActivity">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="#e1e1e1"
android:orientation="vertical">
<LinearLayout
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/img"/>
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="5dp"
android:src="@drawable/img"/>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="second"
android:textColor="#000"
android:textSize="20sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="90dp"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test"/>
<Button
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test"/>
<Button
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test"/>
<Button
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test"/>
<Button
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test"/>
<Button
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test"/>
</LinearLayout>
</RelativeLayout>
package com.wanjian.shareview;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
/**
* Created by wanjian on 2016/10/18.
*/
public class ThreedAct extends AppCompatActivity {
String TAG = "AnimView";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_three);
ShareView.get().activity(this).shareView(findViewById(R.id.image)).onCreate(new ShareView.AnimListener() {
@Override
public void onStart() {
Log.d(TAG, "onStart: ");
}
@Override
public void onUpdate(float degree) {
//Log.d(TAG, "onUpdate: " + degree);
}
@Override
public void onEnd() {
Log.d(TAG, "onEnd: ");
}
});
}
}
activity_three.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical"
tools:context="com.wanjian.shareview.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="test"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="test"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#e1e1e1"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="250dp"
android:layout_height="250dp"
android:src="@drawable/img"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="three"
android:textColor="#f00"
android:textSize="30sp"/>
</LinearLayout>
</LinearLayout>
ShareView源码
package com.wanjian.shareview;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import java.lang.ref.WeakReference;
/**
* Created by wanjian on 2016/10/18.
* <p>
* <p>
* 基本思路:<p>
* 获取当前activity中所需共享view的影像bitmap(view.draw(new Canvas(bitmap))),和在屏幕上位置,宽高。<p>
* 启动新activity时设置没有动画过度act.overridePendingTransition(0, 0)。<p>
* 获取新activty中共享view在屏幕上的位置,宽高。<p>
* 为新activity添加蒙层(FrameLayout) act.getWindow().getDecorView().addView(animView)<p>
* 开启动画(mScroller),绘制之前activty共享view的影像bitmap,通过Matrix对其移动和缩放<p>
* <p>
* 优点:<p>
* 不受布局限制,可以是任何布局,两个activty中共享view可以没有任何联系,大小,位置,随意
* (git上PreLollipopTransition是在父布局内进行属性动画变化,若父布局比较小,则动画过程显示不完整)。
* <p>
* <p>
* 若没有动画,可能是由于bitmap被回收了,logcat会输出如下<p>
* preLaunch: android.graphics.Bitmap@32d90820<p>
* onCreate:... android.widget.LinearLayout{deb1680 V.E..... ......I. 0,0-0,0 #7f0b0029 app:id/image} null<p>
*
* 该demo在魅族mx5上只需多耗费2M内存
*/
public class ShareView {
private String TAG = "AnimView";
private static WeakReference<Activity> sActivityRef;
private static WeakReference<View> sViewRef;
private static WeakReference<Bitmap> sBitmapRef;
private static int[] sViewLocation;
private static int width;
private static int height;
private static ShareView sShareView;
public static ShareView get() {
return sShareView = new ShareView();
}
public ShareView activity(Activity activity) {
sActivityRef = new WeakReference<>(activity);
return this;
}
public ShareView shareView(View view) {
sViewRef = new WeakReference<>(view);
return this;
}
public void startActivity(Intent intent) {
if (sActivityRef == null) {
return;
}
Activity act = sActivityRef.get();
if (act == null) {
return;
}
preLaunch();
act.startActivity(intent);
act.overridePendingTransition(0, 0);
}
// public void startActivity(Intent intent, @Nullable Bundle options) {
// if (sActivityRef == null) {
// return;
// }
// Activity act = sActivityRef.get();
// if (act == null) {
// return;
// }
// preLaunch();
// act.startActivity(intent, potions);
// act.overridePendingTransition(0, 0);
// }
public void startActivityForResult(Intent intent, int requestCode) {
if (sActivityRef == null) {
return;
}
Activity act = sActivityRef.get();
if (act == null) {
return;
}
preLaunch();
act.startActivityForResult(intent, requestCode);
act.overridePendingTransition(0, 0);
}
// public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
// if (sActivityRef == null) {
// return;
// }
// Activity act = sActivityRef.get();
// if (act == null) {
// return;
// }
// preLaunch();
// act.startActivityForResult(intent, requestCode, options);
// act.overridePendingTransition(0, 0);
// }
public void onCreate(final AnimListener animlistener) {
Log.d(TAG, "onCreate: " + sActivityRef + " " + sViewRef + " " + sBitmapRef + " " + sViewLocation);
if (sActivityRef == null || sViewRef == null || sBitmapRef == null || sViewLocation == null) {
return;
}
final Activity act = sActivityRef.get();
final View view = sViewRef.get();
final Bitmap bmp = sBitmapRef.get();
Log.d(TAG, "onCreate: " + act + " " + view + " " + bmp);
if (act == null || view == null || bmp == null || bmp.isRecycled()) {
return;
}
if (!(act.getWindow().getDecorView() instanceof FrameLayout)) {
return;
}
final FrameLayout animContainer = (FrameLayout) act.getWindow().getDecorView();
final int viewState = view.getVisibility();
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
Log.d(TAG, "onGlobalLayout: ");
view.setVisibility(View.INVISIBLE);
int curLocation[] = new int[2];
view.getLocationOnScreen(curLocation);
final AnimView animView = new AnimView(act);
animContainer.addView(animView);
animView.startAnim(bmp, sViewLocation[0], sViewLocation[1], width, height, curLocation[0], curLocation[1], view.getWidth(), view.getHeight(), new AnimListener() {
@Override
public void onStart() {
if (animlistener != null) {
animlistener.onStart();
}
}
@Override
public void onUpdate(float degree) {
if (animlistener != null) {
animlistener.onUpdate(degree);
}
}
@Override
public void onEnd() {
animContainer.removeView(animView);
Log.d(TAG, "onEnd: ---- ");
if (animlistener != null) {
view.setVisibility(viewState);
animlistener.onEnd();
}
}
});
}
});
}
private void preLaunch() {
if (sViewRef == null) {
return;
}
View view = sViewRef.get();
if (view != null && (width = view.getWidth()) > 0 && (height = view.getHeight()) > 0) {
try {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);//设置背景白色
view.draw(canvas);
sBitmapRef = new WeakReference<>(bitmap);
sViewLocation = new int[2];
view.getLocationOnScreen(sViewLocation);
Log.d(TAG, "preLaunch: " + bitmap);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
}
interface AnimListener {
void onStart();
void onUpdate(float degree);
void onEnd();
}
}
animView
package com.wanjian.shareview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.Scroller;
/**
* Created by wanjian on 2016/10/18.
*/
public class AnimView extends View {
private static final String TAG = "AnimView";
public AnimView(Context context) {
super(context);
init();
}
public AnimView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public AnimView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@SuppressLint("NewApi")
public AnimView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private final int DURATION = 1000;
private Scroller mScroller;
private Matrix mMatrix;
private Bitmap bitmap;
private int origL;
private int origT;
private int origW;
private int origH;
private int curL;
private int curT;
private int curW;
private int curH;
private ShareView.AnimListener listener;
private Runnable mTask;
private void init() {
mMatrix = new Matrix();
mTask = new Runnable() {
@Override
public void run() {
if (listener != null) {
listener.onEnd();
}
}
};
mScroller = new Scroller(getContext(), new AccelerateDecelerateInterpolator());
}
public void startAnim(final Bitmap bitmap, int origL, int origT, int origW, int origH, int curL, int curT, int curW, int curH, final ShareView.AnimListener listener) {
this.bitmap = bitmap;
this.origL = origL;
this.origT = origT;
this.origW = origW;
this.origH = origH;
this.curL = curL;
this.curT = curT;
this.curW = curW;
this.curH = curH;
this.listener = listener;
if (listener != null) {
listener.onStart();
}
mScroller.startScroll(0, 0, 0, 0, DURATION);
invalidate();
postDelayed(mTask, DURATION);
}
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
if (listener != null) {
listener.onUpdate(1.0f * mScroller.timePassed() / DURATION);
}
invalidate();
}
}
@Override
protected void onDetachedFromWindow() {
if (!bitmap.isRecycled()) {
bitmap.recycle();
}
getHandler().removeCallbacks(mTask);
Log.d(TAG, "onDetachedFromWindow: " + bitmap.isRecycled());
super.onDetachedFromWindow();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d(TAG, "onDraw: ");
if (bitmap.isRecycled()) {
return;
}
float degree = 1.0f * mScroller.timePassed() / DURATION;
float curX = origL + (curL - origL) * degree;
float curY = origT + (curT - origT) * degree;
mMatrix.setTranslate(curX, curY);
float scaleX = 1.0f * ((curW - origW) * degree + origW) / origW;
float scaleY = 1.0f * ((curH - origH) * degree + origH) / origH;
mMatrix.preScale(scaleX, scaleY);
canvas.drawBitmap(bitmap, mMatrix, null);
}
}