-
Notifications
You must be signed in to change notification settings - Fork 175
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5f114d9
commit b8abd96
Showing
3 changed files
with
239 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 147 additions & 0 deletions
147
library/src/main/java/com/ruffian/library/widget/shadow/ShadowBitmapDrawable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package com.ruffian.library.widget.shadow; | ||
|
||
import android.graphics.Bitmap; | ||
import android.graphics.Canvas; | ||
import android.graphics.Paint; | ||
import android.graphics.Path; | ||
import android.graphics.Rect; | ||
import android.graphics.RectF; | ||
import android.graphics.drawable.BitmapDrawable; | ||
|
||
import com.ruffian.library.widget.utils.ReflectUtils; | ||
|
||
import java.util.Arrays; | ||
|
||
/** | ||
* ShadowBitmapDrawable | ||
* | ||
* @author ZhongDaFeng | ||
*/ | ||
public class ShadowBitmapDrawable extends BitmapDrawable { | ||
|
||
|
||
private int mShadowColor;//阴影颜色 | ||
private float mShadowRadius;//阴影半径 | ||
private float[] mRoundRadii;//矩形圆角半径 | ||
private int mShadowDx;//阴影x偏移 | ||
private int mShadowDy;//阴影y偏移 | ||
|
||
private RectF mBoundsF; | ||
|
||
public ShadowBitmapDrawable() { | ||
mBoundsF = new RectF(); | ||
} | ||
|
||
/** | ||
* RBaseHelp中属性修改时调用 | ||
* | ||
* @param shadowColor | ||
* @param shadowRadius | ||
* @param shadowDx | ||
* @param shadowDy | ||
* @param roundRadii | ||
*/ | ||
public void updateParameter(int shadowColor, float shadowRadius, int shadowDx, int shadowDy, float[] roundRadii) { | ||
boolean needUpdate = false; | ||
if (mShadowColor != shadowColor || mShadowRadius != shadowRadius | ||
|| mShadowDx != shadowDx || mShadowDy != shadowDy | ||
|| !Arrays.equals(mRoundRadii, roundRadii)) { | ||
needUpdate = true; | ||
} | ||
this.mShadowColor = shadowColor; | ||
this.mRoundRadii = roundRadii; | ||
this.mShadowRadius = shadowRadius; | ||
this.mShadowDx = shadowDx; | ||
this.mShadowDy = shadowDy; | ||
|
||
if (needUpdate) { | ||
//重新创建bitmap | ||
Bitmap bitmap = makeShadowBitmap((int) mBoundsF.width(), (int) mBoundsF.height(), mShadowRadius, mShadowDx, mShadowDy, mShadowColor, mRoundRadii); | ||
|
||
//反射调用函数 setBitmap 更新阴影图片 | ||
ReflectUtils.invokeMethod(this, "setBitmap", new Class[]{Bitmap.class}, new Object[]{bitmap}); | ||
} | ||
|
||
|
||
} | ||
|
||
@Override | ||
protected void onBoundsChange(Rect bounds) { | ||
super.onBoundsChange(bounds); | ||
if (bounds.right - bounds.left > 0 && bounds.bottom - bounds.top > 0) { | ||
updateBounds(bounds); | ||
} | ||
} | ||
|
||
/** | ||
* 更新Bounds | ||
* | ||
* @param bounds | ||
*/ | ||
private void updateBounds(Rect bounds) { | ||
if (bounds == null) bounds = getBounds(); | ||
|
||
float left = bounds.left + mShadowRadius + Math.abs(mShadowDx); | ||
float right = bounds.right - mShadowRadius - Math.abs(mShadowDx); | ||
float top = bounds.top + mShadowRadius + Math.abs(mShadowDy); | ||
float bottom = bounds.bottom - mShadowRadius - Math.abs(mShadowDy); | ||
|
||
mBoundsF.set(left, top, right, bottom); | ||
|
||
//重新创建bitmap(不等高列表复用时可能会出现内存抖动,待优化) | ||
Bitmap bitmap = makeShadowBitmap((int) mBoundsF.width(), (int) mBoundsF.height(), mShadowRadius, mShadowDx, mShadowDy, mShadowColor, mRoundRadii); | ||
|
||
//反射调用函数 setBitmap 更新阴影图片 | ||
ReflectUtils.invokeMethod(this, "setBitmap", new Class[]{Bitmap.class}, new Object[]{bitmap}); | ||
|
||
} | ||
|
||
|
||
/** | ||
* 创建阴影Bitmap | ||
* | ||
* @param shadowWidth | ||
* @param shadowHeight | ||
* @param shadowRadius | ||
* @param dx | ||
* @param dy | ||
* @param shadowColor | ||
* @param radii | ||
* @return | ||
*/ | ||
public Bitmap makeShadowBitmap(int shadowWidth, int shadowHeight, float shadowRadius, | ||
float dx, float dy, int shadowColor, float[] radii) { | ||
|
||
//容错处理 | ||
if (shadowWidth <= 0 || shadowHeight <= 0) | ||
return Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444); | ||
|
||
|
||
//阴影bitmap | ||
Bitmap output = Bitmap.createBitmap(shadowWidth, shadowHeight, Bitmap.Config.ARGB_4444); | ||
Canvas canvas = new Canvas(output); | ||
|
||
RectF shadowRect = new RectF(shadowRadius, shadowRadius, shadowWidth - shadowRadius, shadowHeight - shadowRadius); | ||
|
||
|
||
//存在偏移时重新计算阴影矩形大小 | ||
shadowRect.top += Math.abs(dy); | ||
shadowRect.bottom -= Math.abs(dy); | ||
shadowRect.left += Math.abs(dx); | ||
shadowRect.right -= Math.abs(dx); | ||
|
||
//阴影画笔 | ||
Paint shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); | ||
shadowPaint.setColor(shadowColor); | ||
shadowPaint.setShadowLayer(shadowRadius, dx, dy, shadowColor); | ||
|
||
//路径 | ||
Path path = new Path(); | ||
path.addRoundRect(shadowRect, radii, Path.Direction.CW); | ||
canvas.drawPath(path, shadowPaint); | ||
|
||
return output; | ||
} | ||
|
||
|
||
} |
63 changes: 63 additions & 0 deletions
63
library/src/main/java/com/ruffian/library/widget/utils/ReflectUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package com.ruffian.library.widget.utils; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
|
||
/** | ||
* 反射工具类 | ||
* | ||
* @author ZhongDaFeng | ||
*/ | ||
public class ReflectUtils { | ||
|
||
/** | ||
* 循环向上转型, 获取对象的 DeclaredMethod | ||
* | ||
* @param object 子类对象 | ||
* @param methodName 父类中的方法名 | ||
* @param parameterTypes 父类中的方法参数类型 | ||
* @return 父类中的方法对象 | ||
*/ | ||
public static Method getDeclaredMethod(Object object, String methodName, Class<?>... parameterTypes) { | ||
Method method = null; | ||
for (Class<?> clazz = object.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) { | ||
try { | ||
method = clazz.getDeclaredMethod(methodName, parameterTypes); | ||
return method; | ||
} catch (Exception e) { | ||
//这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。 | ||
//如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了 | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
/** | ||
* 直接调用对象方法, 而忽略修饰符(private, protected, default) | ||
* | ||
* @param object 子类对象 | ||
* @param methodName 父类中的方法名 | ||
* @param parameterTypes 父类中的方法参数类型 | ||
* @param parameters 父类中的方法参数 | ||
* @return 父类中方法的执行结果 | ||
*/ | ||
public static Object invokeMethod(Object object, String methodName, Class<?>[] parameterTypes, Object[] parameters) { | ||
//根据 对象、方法名和对应的方法参数 通过反射 调用上面的方法获取 Method 对象 | ||
Method method = getDeclaredMethod(object, methodName, parameterTypes); | ||
try { | ||
if (null != method) { | ||
//抑制Java对方法进行检查,主要是针对私有方法而言 | ||
method.setAccessible(true); | ||
//调用object 的 method 所代表的方法,其方法的参数是 parameters | ||
return method.invoke(object, parameters); | ||
} | ||
} catch (IllegalArgumentException e) { | ||
e.printStackTrace(); | ||
} catch (IllegalAccessException e) { | ||
e.printStackTrace(); | ||
} catch (InvocationTargetException e) { | ||
e.printStackTrace(); | ||
} | ||
return null; | ||
} | ||
} |