公司要出新的版本,界面的风格有了一些改变,对于一些View要加一些阴影的风格,使用cardview以及elevation实现了阴影,但是达不到设计图的那种阴影效果,所以只有通过自定义了。
radius : 模糊半径,radius越大越模糊,越小越清晰,当radius=0时,则阴影消失不见
dx: 阴影在x轴的偏移距离,正值向右偏移,负值向左偏移
dy: 阴影在y轴的偏移距离,正值向下偏移,负值向上偏移
color:阴影的颜色
代码
/**
* 初始化画笔
*/
private fun initPaint() {
//画笔重置
mPaint.reset()
//设置抗锯齿
mPaint.isAntiAlias = true
//设置透明度
mPaint.color = Color.TRANSPARENT
/**
* 参数1 模糊半径 越大越模糊
* 参数2 阴影在x轴的距离
* 参数3 阴影在y轴的距离
* 参数4 阴影颜色
*/
mPaint.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColor)
}
//关闭单个view的硬件加速
setLayerType(View.LAYER_TYPE_SOFTWARE, null)
this.setWillNotDraw(false)
自定义属性
<declare-styleable name="ShadowLayout">
<!--阴影颜色-->
<attr name="shadowColor" format="color"/>
<!--阴影距离-->
<attr name="shadowRadius" format="dimension"/>
<!--在x轴的阴影-->
<attr name="shadowDx" format="dimension"/>
<!--在y轴的阴影-->
<attr name="shadowDy" format="dimension"/>
<!--阴影的方向-->
<attr name="shadowSide" format="integer"/>
<!--阴影的形状-->
<attr name="shadowShape" format="integer"/>
读取用户自定义属性
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShadowLayout)
mShadowColor = typedArray.getColor(R.styleable.ShadowLayout_shadowColor, Color.BLACK)
mShadowRadius = typedArray.getDimension(R.styleable.ShadowLayout_shadowRadius, 0f)
mShadowDx = typedArray.getDimension(R.styleable.ShadowLayout_shadowDx, 0f)
mShadowDy = typedArray.getDimension(R.styleable.ShadowLayout_shadowDy, 0f)
mShadowSide = typedArray.getInt(R.styleable.ShadowLayout_shadowSide, 0)
mShadowShape = typedArray.getInt(R.styleable.ShadowLayout_shadowShape, 0)
typedArray.recycle()
/**
* 对View进行测量
*/
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val effect = mShadowRadius
var rectLeft = 0f
var rectTop = 0f
var rectRight = this.measuredWidth.toFloat()
var rectBottom = this.measuredHeight.toFloat()
var paddingLeft = 0f
var paddingRight = 0f
var paddingTop = 0f
var paddingBottom = 0f
when (mShadowSide) {
LEFT -> {
rectLeft = effect
paddingLeft = effect
}
RIGHT -> {
rectRight = this.measuredWidth - effect
paddingRight = effect
}
TOP -> {
rectTop = effect
paddingTop = effect
}
BOTTOM -> {
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
LEFT_RIGHT -> {
rectLeft = effect
paddingLeft = effect
rectRight = this.measuredWidth - effect
paddingRight = effect
}
LEFT_TOP -> {
rectLeft = effect
paddingLeft = effect
rectTop = effect
paddingTop = effect
}
LEFT_BOTTOM -> {
rectLeft = effect
paddingLeft = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
RIGHT_TOP -> {
rectRight = this.measuredWidth - effect
paddingRight = effect
rectTop = effect
paddingTop = effect
}
RIGHT_BOTTOM ->{
rectRight = this.measuredWidth - effect
paddingRight = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
TOP_BOTTOM ->{
rectTop = effect
paddingTop = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
LEFT_TOP_BOTTOM ->{
rectLeft = effect
paddingLeft = effect
rectTop = effect
paddingTop = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
LEFT_TOP_RIGHT ->{
rectLeft = effect
paddingLeft = effect
rectTop = effect
paddingTop = effect
rectRight = this.measuredWidth - effect
paddingRight = effect
}
RIGHT_LEFT_BOTTOM ->{
rectLeft = effect
paddingLeft = effect
rectRight = this.measuredWidth - effect
paddingRight = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
else ->{
paddingLeft = effect
paddingRight = effect
paddingTop = effect
paddingBottom = effect
rectLeft = effect
rectRight = this.measuredWidth - effect
rectTop = effect
rectBottom = this.measuredHeight - effect
}
}
mRectF.left = rectLeft
mRectF.right = rectRight
mRectF.top = rectTop
mRectF.bottom = rectBottom
this.setPadding(paddingLeft.toInt(), paddingTop.toInt(), paddingRight.toInt(), paddingBottom.toInt())
}
if (mShadowShape == SHAPE_RECENTAGE) {//绘制长方形
canvas.drawRect(mRectF, mPaint)
} else if (mShadowShape == SHAPE_OVAL) {
canvas.drawCircle(mRectF.centerX(), mRectF.centerY(), Math.min(mRectF.width(), mRectF.height()) / 2, mPaint)
}
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
import android.widget.RelativeLayout
class ShadowLayout @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr) {
/**标识符 阴影在布局的显示位置*/
private val LEFT: Int = 0
private val RIGHT: Int = 1
private val TOP: Int = 2
private val BOTTOM: Int = 3
private val LEFT_RIGHT: Int = 4
private val LEFT_TOP: Int = 5
private val LEFT_BOTTOM: Int = 6
private val RIGHT_TOP: Int = 7
private val RIGHT_BOTTOM: Int = 8
private val TOP_BOTTOM: Int = 9
private val LEFT_TOP_BOTTOM: Int = 10
private val LEFT_TOP_RIGHT: Int = 11
private val RIGHT_LEFT_BOTTOM: Int = 12
private val ALL: Int = 13
/**标识符 阴影的形状*/
private val SHAPE_RECENTAGE = 0
private val SHAPE_OVAL = 1
/**阴影的颜色*/
private var mShadowColor: Int = Color.TRANSPARENT
/**阴影的距离*/
private var mShadowRadius: Float = 0.0f
/**阴影在x轴的距离*/
private var mShadowDx: Float = 0.0f
/**阴影在y轴的距离*/
private var mShadowDy: Float = 0.0f
/**阴影的方向*/
private var mShadowSide: Int = ALL
/**阴影的形状*/
private var mShadowShape: Int = SHAPE_RECENTAGE
/**画笔*/
private val mPaint by lazy {
Paint()
}
/***/
private val mRectF: RectF by lazy {
RectF()
}
init {
initAttrs(attrs, context)
initPaint()
}
/**
* 初始化自定义属性
*/
private fun initAttrs(attrs: AttributeSet?, context: Context) {
//关闭单个view的硬件加速
setLayerType(View.LAYER_TYPE_SOFTWARE, null)
this.setWillNotDraw(false)
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShadowLayout)
mShadowColor = typedArray.getColor(R.styleable.ShadowLayout_shadowColor, Color.BLACK)
mShadowRadius = typedArray.getDimension(R.styleable.ShadowLayout_shadowRadius, 0f)
mShadowDx = typedArray.getDimension(R.styleable.ShadowLayout_shadowDx, 0f)
mShadowDy = typedArray.getDimension(R.styleable.ShadowLayout_shadowDy, 0f)
mShadowSide = typedArray.getInt(R.styleable.ShadowLayout_shadowSide, 0)
mShadowShape = typedArray.getInt(R.styleable.ShadowLayout_shadowShape, 0)
typedArray.recycle()
}
/**
* 初始化画笔
*/
private fun initPaint() {
//画笔重置
mPaint.reset()
//设置抗锯齿
mPaint.isAntiAlias = true
//设置透明度
mPaint.color = Color.TRANSPARENT
/**
* 参数1 模糊半径 越大越模糊
* 参数2 阴影在x轴的距离
* 参数3 阴影在y轴的距离
* 参数4 阴影颜色
*/
mPaint.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColor)
}
/**
* 对View进行测量
*/
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val effect = mShadowRadius
var rectLeft = 0f
var rectTop = 0f
var rectRight = this.measuredWidth.toFloat()
var rectBottom = this.measuredHeight.toFloat()
var paddingLeft = 0f
var paddingRight = 0f
var paddingTop = 0f
var paddingBottom = 0f
when (mShadowSide) {
LEFT -> {
rectLeft = effect
paddingLeft = effect
}
RIGHT -> {
rectRight = this.measuredWidth - effect
paddingRight = effect
}
TOP -> {
rectTop = effect
paddingTop = effect
}
BOTTOM -> {
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
LEFT_RIGHT -> {
rectLeft = effect
paddingLeft = effect
rectRight = this.measuredWidth - effect
paddingRight = effect
}
LEFT_TOP -> {
rectLeft = effect
paddingLeft = effect
rectTop = effect
paddingTop = effect
}
LEFT_BOTTOM -> {
rectLeft = effect
paddingLeft = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
RIGHT_TOP -> {
rectRight = this.measuredWidth - effect
paddingRight = effect
rectTop = effect
paddingTop = effect
}
RIGHT_BOTTOM ->{
rectRight = this.measuredWidth - effect
paddingRight = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
TOP_BOTTOM ->{
rectTop = effect
paddingTop = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
LEFT_TOP_BOTTOM ->{
rectLeft = effect
paddingLeft = effect
rectTop = effect
paddingTop = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
LEFT_TOP_RIGHT ->{
rectLeft = effect
paddingLeft = effect
rectTop = effect
paddingTop = effect
rectRight = this.measuredWidth - effect
paddingRight = effect
}
RIGHT_LEFT_BOTTOM ->{
rectLeft = effect
paddingLeft = effect
rectRight = this.measuredWidth - effect
paddingRight = effect
rectBottom = this.measuredHeight - effect
paddingBottom = effect
}
else ->{
paddingLeft = effect
paddingRight = effect
paddingTop = effect
paddingBottom = effect
rectLeft = effect
rectRight = this.measuredWidth - effect
rectTop = effect
rectBottom = this.measuredHeight - effect
}
}
mRectF.left = rectLeft
mRectF.right = rectRight
mRectF.top = rectTop
mRectF.bottom = rectBottom
this.setPadding(paddingLeft.toInt(), paddingTop.toInt(), paddingRight.toInt(), paddingBottom.toInt())
}
/**
* 对View进行绘制
*/
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
initPaint()
if (mShadowShape == SHAPE_RECENTAGE) {//绘制长方形
canvas.drawRect(mRectF, mPaint)
} else if (mShadowShape == SHAPE_OVAL) {
canvas.drawCircle(mRectF.centerX(), mRectF.centerY(), Math.min(mRectF.width(), mRectF.height()) / 2, mPaint)
}
}
public fun setShadowRadius(mShadeRadiu: Int) {
this.mShadowRadius = mShadowRadius
//重新对View进行布局
requestLayout()
//在主线程/非主线程进行刷新
postInvalidate()
}
public fun setShadowColor(mShadeColor: Int) {
this.mShadowColor = mShadeColor
//重新对View进行布局
requestLayout()
//在主线程/非主线程进行刷新
postInvalidate()
}
}
<view.com.shadowlayoutall.ShadowLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="20dp"
app:shadowColor="#12000000"
app:shadowRadius="19dp"
app:shadowShape="0"
app:shadowSide="12">
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@android:color/white"/>
</view.com.shadowlayoutall.ShadowLayout>
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- baoquwan.com 版权所有 湘ICP备2024080961号-7
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务