package com.owen.tvrecyclerview.example.bridge; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.view.View; import android.view.ViewGroup; import android.view.animation.DecelerateInterpolator; public class BaseEffectBridgeWrapper extends BaseEffectBridge { private static final float DEFAULT_SCALE = 1.0f; private static final int DEFAULT_TRAN_DUR_ANIM = 300; private MainUpView mMainUpView; private Drawable mDrawableShadow; private Drawable mDrawableUpRect; private Context mContext; private Rect mUpPaddingRect = new Rect(0, 0, 0, 0); private Rect mShadowPaddingRect = new Rect(0, 0, 0, 0); /** * 继承这个类重写的话.<br> * 记得要加 super.onInitBridge(view); */ @Override public void onInitBridge(MainUpView view) { mContext = view.getContext(); } /** * ==========设置阴影图片=========== */ @Override public void setShadowResource(int resId) { try { this.mDrawableShadow = mContext.getResources().getDrawable(resId); // 移动的边框. } catch (Exception e) { this.mDrawableShadow = null; e.printStackTrace(); } } /** * 当图片边框不自带阴影的话,可以自行设置阴影图片. 设置阴影. */ @Override public void setShadowDrawable(Drawable shadowDrawable) { this.mDrawableShadow = shadowDrawable; } @Override public Drawable getShadowDrawable() { return this.mDrawableShadow; } /** * 根据阴影图片边框 自行 填写 相差的边距. <br> * 比如 res/drawble/white_shadow.9.png的图片,边距就差很多. */ public void setDrawShadowPadding(int size) { setDrawShadowRectPadding(new Rect(size, size, size, size)); } /** * 根据阴影图片边框 自行 填写 相差的边距. <br> * 比如 res/drawble/white_shadow.9.png的图片,边距就差很多. */ @Override public void setDrawShadowRectPadding(Rect rect) { mShadowPaddingRect.set(rect); } @Override public Rect getDrawShadowRect() { return this.mShadowPaddingRect; } /** * ==========设置边框图片=========== */ @Override public void setUpRectResource(int resId) { try { this.mDrawableUpRect = mContext.getResources().getDrawable(resId); // 移动的边框. } catch (Exception e) { e.printStackTrace(); } } /** * 设置最上层的边框. */ @Override public void setUpRectDrawable(Drawable upRectDrawable) { this.mDrawableUpRect = upRectDrawable; } @Override public Drawable getUpRectDrawable() { return this.mDrawableUpRect; } /** * 根据图片边框 自行 填写 相差的边距. <br> * 比如 res/drawble/white_light_10.9.png的图片,边距就差很多. * * @param size * 负数边框减小,正数反之(阴影边框一样的). */ public void setDrawUpRectPadding(int size) { setDrawUpRectPadding(new Rect(size, size, size, size)); } /** * 根据图片边框 自行 填写 相差的边距. <br> * 比如 res/drawble/white_light_10.9.png的图片,边距就差很多. */ @Override public void setDrawUpRectPadding(Rect rect) { mUpPaddingRect.set(rect); } @Override public Rect getDrawUpRect() { return this.mUpPaddingRect; } /** * ==========焦点View处理=========== */ public void setFocusView(View newView, View oldView, float scale) { setFocusView(newView, scale); setUnFocusView(oldView); } /** * 设置焦点子控件的移动和放大. */ public void setFocusView(View view, float scale) { setFocusView(view, scale, scale); } public void setFocusView(View view, float scaleX, float scaleY) { onFocusView(view, scaleX, scaleY); } /** * 设置无焦点子控件还原. */ public void setUnFocusView(View view) { setUnFocusView(view, DEFAULT_SCALE, DEFAULT_SCALE); } public void setUnFocusView(View view, float scaleX, float scaleY) { onOldFocusView(view, scaleX, scaleY); } /** * 老的焦点View. */ @Override public void onOldFocusView(View oldFocusView, float scaleX, float scaleY) { if (oldFocusView != null) { oldFocusView.animate().scaleX(scaleX).scaleY(scaleY).setDuration(DEFAULT_TRAN_DUR_ANIM).start(); } } /** * 新的焦点View. */ @Override public void onFocusView(View focusView, float scaleX, float scaleY) { if (focusView != null) { focusView.animate().scaleX(scaleX).scaleY(scaleY).setDuration(DEFAULT_TRAN_DUR_ANIM).start(); // 放大焦点VIEW的动画. runTranslateAnimation(focusView, scaleX, scaleY); // 移动边框的动画。 } } /** * ==========绘制处理=========== */ /** * 需要绘制的东西. */ @Override public boolean onDrawMainUpView(Canvas canvas) { canvas.save(); // 绘制阴影. onDrawShadow(canvas); // 绘制最上层的边框. onDrawUpRect(canvas); canvas.restore(); return true; } /** * 绘制外部阴影. */ public void onDrawShadow(Canvas canvas) { Drawable drawableShadow = getShadowDrawable(); if (drawableShadow != null) { Rect shadowPaddingRect = getDrawShadowRect(); int width = getMainUpView().getWidth(); int height = getMainUpView().getHeight(); Rect padding = new Rect(); drawableShadow.getPadding(padding); drawableShadow.setBounds(-padding.left - (shadowPaddingRect.left), -padding.top - (shadowPaddingRect.top), width + padding.right + (shadowPaddingRect.right), height + padding.bottom + (shadowPaddingRect.bottom)); drawableShadow.draw(canvas); } } /** * 绘制最上层的移动边框. */ public void onDrawUpRect(Canvas canvas) { Drawable drawableUp = getUpRectDrawable(); if (drawableUp != null) { Rect paddingRect = getDrawUpRect(); int width = getMainUpView().getWidth(); int height = getMainUpView().getHeight(); Rect padding = new Rect(); // 边框的绘制. drawableUp.getPadding(padding); drawableUp.setBounds(-padding.left - (paddingRect.left), -padding.top - (paddingRect.top), width + padding.right + (paddingRect.right), height + padding.bottom + (paddingRect.bottom)); drawableUp.draw(canvas); } } public void runTranslateAnimation(View toView, float scaleX, float scaleY) { try { flyWhiteBorder(toView, getMainUpView(), scaleX, scaleY); } catch (Exception e) { e.printStackTrace(); } } public Rect findLocationWithView(View view) { ViewGroup root = (ViewGroup) getMainUpView().getParent(); Rect rect = new Rect(); root.offsetDescendantRectToMyCoords(view, rect); return rect; } public int[] getViewLocationScreen(View v) { int[] location = new int[2]; v.getLocationOnScreen(location); return location; } public void flyWhiteBorder(final View focusView, View moveView, float scaleX, float scaleY) { int newWidth = 0; int newHeight = 0; int oldWidth = 0; int oldHeight = 0; int newX = 0; int newY = 0; if (focusView != null) { newWidth = (int) (focusView.getMeasuredWidth() * scaleX); newHeight = (int) (focusView.getMeasuredHeight() * scaleY); oldWidth = moveView.getMeasuredWidth(); oldHeight = moveView.getMeasuredHeight(); Rect fromRect = findLocationWithView(moveView); Rect toRect = findLocationWithView(focusView); int x = toRect.left - fromRect.left; int y = toRect.top - fromRect.top; newX = x - Math.abs(focusView.getMeasuredWidth() - newWidth) / 2; newY = y - Math.abs(focusView.getMeasuredHeight() - newHeight) / 2; } ObjectAnimator transAnimatorX = ObjectAnimator.ofFloat(moveView, "translationX", newX); ObjectAnimator transAnimatorY = ObjectAnimator.ofFloat(moveView, "translationY", newY); // BUG,因为缩放会造成图片失真(拉伸). // hailong.qiu 2016.02.26 修复 :) ObjectAnimator scaleXAnimator = ObjectAnimator.ofInt(new ScaleView(moveView), "width", oldWidth, (int) newWidth); ObjectAnimator scaleYAnimator = ObjectAnimator.ofInt(new ScaleView(moveView), "height", oldHeight, (int) newHeight); // AnimatorSet mAnimatorSet = new AnimatorSet(); mAnimatorSet.playTogether(transAnimatorX, transAnimatorY, scaleXAnimator, scaleYAnimator); mAnimatorSet.setInterpolator(new DecelerateInterpolator(1)); mAnimatorSet.setDuration(DEFAULT_TRAN_DUR_ANIM); mAnimatorSet.start(); } /** * 用於放大的view */ public class ScaleView { private View view; private int width; private int height; public ScaleView(View view) { this.view = view; } public int getWidth() { return view.getLayoutParams().width; } public void setWidth(int width) { this.width = width; view.getLayoutParams().width = width; view.requestLayout(); } public int getHeight() { return view.getLayoutParams().height; } public void setHeight(int height) { this.height = height; view.getLayoutParams().height = height; view.requestLayout(); } } /** * 最上层的移动的view. */ @Override public void setMainUpView(MainUpView view) { this.mMainUpView = view; } /** * 最上层移动的view. */ @Override public MainUpView getMainUpView() { return this.mMainUpView; } }