在Android開發中我們會在設計稿中看到各種陰影效果,我們知道CardView可以添加陰影效果,不過可能并不是我們設計稿想要的效果,那我們如何可以更加靈活地給我們原生控件添加陰影效果,這就是下面所要描述的,當然也可以讓設計師給個陰影切圖,我們做下.9處理然后使用切圖實現陰影效果。
下面看看如何用代碼更靈活地去為原生控件實現陰影效果,源碼可以查看 XSelector GitHub, 結尾也會貼出ShadowHelper
源碼。
先看效果圖:
shadow.png
如果使用XSelector工具庫引入對應的庫implementation 'com.android.util:xselector:1.0.2'
,使用方法如下,也可以直接使用該ShadowHelper
類去完成陰影效果。
XSelector.shadowHelper().setShape(ShadowHelper.SHAPE_CIRCLE)
.setBgColor(Color.parseColor("#FF3D00"))
.setShapeRadius(dpToPx(6))
.setShadowColor(Color.parseColor("#991DE9B6"))
.setShadowRadius(dpToPx(6))
.setOffsetX(dpToPx(4))
.setOffsetY(dpToPx(4))
.into(textView5);
使用方法存在但不限于上述使用方法,具體詳細方法如下:
模塊 | 方法名 | 描述 |
---|---|---|
ShadowHelper | setShape | 設置背景形狀,橢圓或者圓形 |
setBgColor | 背景顏色 | |
setShapeRadius | 設置背景半徑 | |
setShadeSide | 設置陰影方向,默認四周 | |
setShadeRadius | 設置陰影半徑 | |
setShadowColor | 設置陰影顏色 | |
setOffsetX | 設置陰影X軸偏移量 | |
setOffsetY | 設置陰影Y軸偏移量 | |
setShadowAlpha | 設置陰影透明度 | |
into | 目標View |
ShadowHelper
源碼如下:
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.view.View;
/**
* 類名稱:ShadowHelper
* 創建者:Create by liujc
* 創建時間:Create on 2018/5/28
* 描述:控件陰影效果
*/
public class ShadowHelper extends Drawable {
static ShadowHelper shadowHelper;
private Paint mPaint;
/**
* 陰影模糊半徑,越大越模糊
*/
private int mShadowRadius;
/**
* 陰影顏色
*/
private int mShadowColor;
/**
* 背景形狀
*/
private int mShape;
/**
* 背景圓角半徑
*/
private int mShapeRadius;
/**
* 陰影x偏移(右偏移)
*/
private int mOffsetX;
/**
* 陰影y偏移(下偏移)
*/
private int mOffsetY;
/**
* 背景顏色
*/
private int mBgColor[];
private RectF mRect;
public final static int SHAPE_ROUND = 1;
public final static int SHAPE_CIRCLE = 2;
public static final int ALL = 0x1111;
public static final int LEFT = 0x0001;
public static final int TOP = 0x0010;
public static final int RIGHT = 0x0100;
public static final int BOTTOM = 0x1000;
/**
* 陰影邊 例:0x1100 表示RIGHT和BOTTOM
*/
private int shadowSide = ALL;
private ShadowHelper(){
mShape = ShadowHelper.SHAPE_ROUND;
mShapeRadius = 0;
mShadowColor = Color.parseColor("#4d000000");
mShadowRadius = 18;
mOffsetX = 0;
mOffsetY = 0;
mBgColor = new int[1];
mBgColor[0] = Color.TRANSPARENT;
mPaint = new Paint();
mPaint.setColor(Color.TRANSPARENT);
mPaint.setAntiAlias(true);
mPaint.setShadowLayer(mShadowRadius, mOffsetX, mOffsetY, mShadowColor);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
}
public static ShadowHelper getInstance() {
shadowHelper = new ShadowHelper();
return shadowHelper;
}
public ShadowHelper setShape(int mShape) {
this.mShape = mShape;
return this;
}
public ShadowHelper setShadowSide(int shadowSide) {
this.shadowSide = shadowSide;
return this;
}
public ShadowHelper setShapeRadius(int ShapeRadius) {
this.mShapeRadius = ShapeRadius;
return this;
}
/**
* 設置陰影顏色
* @param shadowColor 例:R.color.colorPrimary
* @return
*/
public ShadowHelper setShadowColor(int shadowColor) {
this.mShadowColor = shadowColor;
mPaint.setShadowLayer(mShadowRadius, mOffsetX, mOffsetY, mShadowColor);
return this;
}
/**
* 設置陰影顏色
* @param shadowColor 例:#ffffff
* @return
*/
public ShadowHelper setShadowColor(String shadowColor) {
this.mShadowColor = Color.parseColor(shadowColor);
mPaint.setShadowLayer(mShadowRadius, mOffsetX, mOffsetY, mShadowColor);
return this;
}
public ShadowHelper setShadowRadius(int shadowRadius) {
this.mShadowRadius = shadowRadius;
mPaint.setShadowLayer(mShadowRadius, mOffsetX, mOffsetY, mShadowColor);
return this;
}
public ShadowHelper setOffsetX(int OffsetX) {
this.mOffsetX = OffsetX;
mPaint.setShadowLayer(mShadowRadius, mOffsetX, mOffsetY, mShadowColor);
return this;
}
public ShadowHelper setOffsetY(int OffsetY) {
this.mOffsetY = OffsetY;
mPaint.setShadowLayer(mShadowRadius, mOffsetX, mOffsetY, mShadowColor);
return this;
}
/**
* 設置背景顏色
* @param BgColor 例:R.color.colorPrimary
* @return
*/
public ShadowHelper setBgColor(int BgColor) {
this.mBgColor[0] = BgColor;
return this;
}
/**
* 設置背景顏色
* @param bgColor 例:#ffffff
* @return
*/
public ShadowHelper setBgColor(String bgColor) {
this.mBgColor[0] = Color.parseColor(bgColor);
return this;
}
public ShadowHelper setBgColor(int[] BgColor) {
this.mBgColor = BgColor;
return this;
}
public ShadowHelper setBgColor(String[] bgColor) {
int length = bgColor.length;
int[] color = new int[length];
for(int i=0;i < length;i++){
color[i] = Color.parseColor(bgColor[i]);
}
this.mBgColor = color;
return this;
}
public ShadowHelper setShadowAlpha(int i) {
setAlpha(i);
return this;
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
int leftShadow = (shadowSide & LEFT) == LEFT ? mShadowRadius - mOffsetX : -mShapeRadius;
int topShadow = (shadowSide & TOP) == TOP ? mShadowRadius - mOffsetY : -mShapeRadius;
int rightShadow = (shadowSide & RIGHT) == RIGHT ? mShadowRadius + mOffsetX : -mShapeRadius;
int bottomShadow = (shadowSide & BOTTOM) == BOTTOM ? mShadowRadius + mOffsetY : -mShapeRadius;
mRect = new RectF(bounds.left + leftShadow, bounds.top + topShadow, bounds.right - rightShadow,
bounds.bottom - bottomShadow);
}
@Override
public void draw(@NonNull Canvas canvas) {
Paint newPaint = new Paint();
if (mBgColor != null) {
if (mBgColor.length == 1) {
newPaint.setColor(mBgColor[0]);
} else {
newPaint.setShader(new LinearGradient(mRect.left, mRect.height() / 2, mRect.right, mRect.height() / 2, mBgColor,
null, Shader.TileMode.CLAMP));
}
}
newPaint.setAntiAlias(true);
if (mShape == SHAPE_ROUND) {
canvas.drawRoundRect(mRect, mShapeRadius, mShapeRadius, mPaint);
canvas.drawRoundRect(mRect, mShapeRadius, mShapeRadius, newPaint);
} else {
canvas.drawCircle(mRect.centerX(), mRect.centerY(), Math.min(mRect.width(), mRect.height())/ 2, mPaint);
canvas.drawCircle(mRect.centerX(), mRect.centerY(), Math.min(mRect.width(), mRect.height())/ 2, newPaint);
}
}
@Override
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
public static void setShadowHelper(View view, Drawable drawable) {
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
ViewCompat.setBackground(view, drawable);
}
public void into(View view){
if (view == null){
return;
}
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
ViewCompat.setBackground(view, this);
}
}