今天看到了@Anderson大碼渣寫的文章繁扎,對5.0以上默認使用ViewAnimationUtils.createCircularReveal(view, centerX, centerY, startRadius, endRadius);
來實現(xiàn)漸變怒炸,
4.0以上兼容
要想在低版本中也能正常使用贡羔,我們可以直接自定義一個viewGroup云稚,掛載在decorview上,然后使用canvas.clipPath
裁剪一個圓进统,這樣達到覆蓋的目的助币。
public class CircularRevealLayout extends FrameLayout {
private static final String TAG = "CircularRevealLayout";
private float revealRadius;
private int centerX;
private int centerY;
private float startRadius;
private float endRadius;
private View childRevealView;
private boolean isRunning = false;//動畫是否正在執(zhí)行
private Path path;//繪制路徑
public CircularRevealLayout(Context context) {
this(context, null, 0);
}
public CircularRevealLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircularRevealLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
path = new Path();
setFocusable(false);
}
/**
* 設置要揭示的子view
* @param childRevealView
*/
public void setChildRevealView(View childRevealView) {
this.childRevealView = childRevealView;
}
/**
* 設置要揭示的子view的下標
* @param index
*/
public void setChildRevealViewIndex(int index) {
if(getChildCount()>index){
this.childRevealView=getChildAt(index);
}
}
/**
* 設置揭示半徑
* @param revealRadius
*/
private void setRevealRadius(float revealRadius) {
this.revealRadius = revealRadius;
Log.e(TAG, "revealRadius=" + revealRadius);
invalidate();
}
/**
* 設置揭示的中心點x坐標
* @param centerX
*/
public void setCenterX(int centerX) {
this.centerX = centerX;
}
/**
* 設置揭示的中心點y坐標
* @param centerY
*/
public void setCenterY(int centerY) {
this.centerY = centerY;
}
/**
* 設置揭示的開始半徑
* @param startRadius
*/
public void setStartRadius(float startRadius) {
this.startRadius = startRadius;
}
/**
* 設置揭示的結束半徑
* @param endRadius
*/
public void setEndRadius(float endRadius) {
this.endRadius = endRadius;
}
public Animator getAnimator() {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "revealRadius", startRadius, endRadius);
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
isRunning = true;
}
@Override
public void onAnimationEnd(Animator animator) {
isRunning = false;
}
@Override
public void onAnimationCancel(Animator animator) {
isRunning = false;
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
return objectAnimator;
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (isRunning && child == childRevealView) {
final int state = canvas.save();
path.reset();
path.addCircle(centerX, centerY, revealRadius, Path.Direction.CW);//Pat.Direction.CW:順時針
canvas.clipPath(path);//裁剪
boolean isInvalided = super.drawChild(canvas, child, drawingTime);
canvas.restoreToCount(state);
return isInvalided;
}
return super.drawChild(canvas, child, drawingTime);
}
}
再實現(xiàn)兼容的ViewAnimationCompatUtils
public class ViewAnimationCompatUtils {
private static final String TAG = "ViewAnimationCompatUtil";
public static Animator createCircularReveal(@NonNull View view, int centerX, int centerY, float startRadius, float endRadius) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, startRadius, endRadius);
}
//如果父view已經(jīng)是CircularRevealLayout,則設置參數(shù)后直接返回animator
if (view.getParent() != null && view.getParent() instanceof CircularRevealLayout) {
Log.e(TAG, "parent is CircularRevealLayout");
CircularRevealLayout circularRevealLayout = (CircularRevealLayout) view.getParent();
circularRevealLayout.setCenterX(centerX);
circularRevealLayout.setCenterY(centerY);
circularRevealLayout.setStartRadius(startRadius);
circularRevealLayout.setEndRadius(endRadius);
circularRevealLayout.setChildRevealView(view);
return circularRevealLayout.getAnimator();
}
Log.e(TAG, "parent is not CircularRevealLayout");
//如果父view不是CircularRevealLayout螟碎,則先為view添加父view CircularRevealLayout
//之后將CircularRevealLayout替換掉原來的view
CircularRevealLayout circularRevealLayout = new CircularRevealLayout(view.getContext());
//開啟硬件加速
circularRevealLayout.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
circularRevealLayout.setCenterX(centerX);
circularRevealLayout.setCenterY(centerY);
circularRevealLayout.setStartRadius(startRadius);
circularRevealLayout.setEndRadius(endRadius);
circularRevealLayout.setChildRevealView(view);
ViewGroup.LayoutParams params = view.getLayoutParams();
ViewGroup parent = (ViewGroup) view.getParent();
int index = 0;
if (parent != null) {
index = parent.indexOfChild(view);//記錄view在原先父view的下標
Log.e(TAG, "index=" + index);
parent.removeView(view);
circularRevealLayout.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
parent.addView(circularRevealLayout, index, params);
}
return circularRevealLayout.getAnimator();
}
}
寫到這兒眉菱,已經(jīng)能正常顯示了,不過在@Anderson大碼渣](http://www.reibang.com/p/d4b421795154)的基礎上我們最好再繼續(xù)做一定的修改掉分,上文在AnimationHelper的startActivityForResult中寫了個延遲任務俭缓,
view.postDelayed(new Runnable() {
@Override
public void run() {
Animator anim = ViewAnimationCompatUtils.createCircularReveal(imageview, xCenter, yCenter, finalRadius, 0);
anim.setDuration(durationMills);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
try {
decorView.removeView(imageview);
imageview.setVisibility(View.GONE);
} catch (Exception e) {
e.printStackTrace();
}
}
});
anim.start();
}
}, 1000);
在4.0的系統(tǒng)上退回到前一個activity的時候動畫有時候會顯示不出來克伊,所以最在在baseactivity的onresume中寫一個回調,當回調時調用此動畫執(zhí)行华坦。
BaseActivity...
@Override
protected void onResume() {
super.onResume();
if (resume != null) {
resume.setResume();
}
}
public void setResume(IonResume resume) {
this.resume = resume;
}
private IonResume resume;
public interface IonResume {
void setResume();
}
...
thisActivity.setResume(new BaseActivity.IonResume() {
@Override
public void setResume() {
if (imageview.getVisibility()==View.VISIBLE){
Animator anim = ViewAnimationCompatUtils.createCircularReveal(imageview, xCenter, yCenter, finalRadius, 0);
anim.setDuration(800);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
try {
decorView.removeView(imageview);
imageview.setVisibility(View.GONE);
} catch (Exception e) {
e.printStackTrace();
}
}
});
anim.start();
}
}
});
Github代碼下載
也歡迎大家關注我的簡書愿吹、CSDN