ImageFilterView 是 ConstraintLayout 提供的一个功能丰富的 ImageView 扩展类,用于轻松实现对图片的滤镜效果,包括亮度、饱和度和色调调整等。其主要用于动态地调整图片的视觉效果,例如在UI中加入动态色调过渡效果、图片平移、缩放、旋转等。
ImageFilterView
作为自定义View
,在XML
中定义了常用属性如下:
kotlin
<declare-styleable name="ImageFilterView">
<attr format="reference" name="blendSrc"/>
<attr format="reference" name="altSrc"/>
<attr format="float" name="saturation"/>
<attr format="float" name="brightness"/>
<attr format="float" name="warmth"/>
<attr format="float" name="contrast"/>
<attr format="float" name="crossfade"/>
<attr format="dimension" name="round"/>
<attr format="boolean" name="overlay"/>
<attr format="float" name="roundPercent"/>
<attr format="float" name="imagePanX"/>
<attr format="float" name="imagePanY"/>
<attr format="float" name="imageZoom"/>
<attr format="float" name="imageRotate"/>
</declare-styleable>
常用属性的含义:
- Saturation (饱和度):调整图像颜色的饱和度,1.0 表示不改变,0.1 将图像近乎去色,而 2.0 表示更高的饱和度。可以通过设置不同饱和度实现黑白效果或增强色彩鲜艳度。
- Brightness (亮度):设置图像的亮度,1.0 为原亮度,2.0 增加亮度,0.5 则会暗化。适用于图片需要调整亮度的场景,比如在较暗环境下提升可见度。
- Contrast (对比度):调节图像的对比度,1.0 为默认,值越大对比越强。适合需要增强对比的场景,让图像细节更清晰。
- Warmth (色温):控制图像的冷暖色调,1.0 表示原色温,低于 1.0 使图像偏冷色,高于 1.0 偏暖色。适合营造冷暖色调效果,如模拟日出或夕阳光照。
- Round (圆角):设置图像的圆角半径,以像素为单位,使边角更平滑。适用于给图像加圆角处理,常用于头像展示等场景。
- Round Percent (百分比圆角):设置圆角程度的百分比,1.0f 表示完全圆形。用于制作圆形头像显示效果,适合于需要完美圆形的场景。
- AltSrc (备用图像) :设置备用图像,并通过 crossfade 控制 src 和 altSrc 混合程度,比如
crossfade = 0.5f
表示主图与备用图各占 50%。适合做图像淡入淡出效果,或者不同滤镜组合的效果。代码示例:
kotlin
ivFilter.setAltImageResource(R.drawable.xxx)
ivFilter.crossfade = 0.5f
- Overlay (叠加图像):在图像上叠加一个图层,用于应用更多视觉效果。适合需要叠加水印、阴影等效果的场景。
- ImageRotate (旋转):旋转图像,单位为度,比如90f 表示顺时针旋转 90 度。用于图片旋转需求,例如左右旋转或倒置图像。
- ImageZoom (缩放) :缩放图像,
1.0
表示正常大小,0.5
为宽高缩小一半。适合缩放需求的场景,比如局部放大效果。
上述这些属性让 ImageFilterView 能实现复杂的图像处理效果,非常适合制作自定义图片展示和特效。使用示例:
kotlin
companion object {
const val TYPE_SATURATION = 1 // 色彩饱和度
const val TYPE_BRIGHT_NESS = 6 // 对比度
const val TYPE_CONTRACT = 7 // 亮度
const val TYPE_WARMTH = 2 // 色温
const val TYPE_ROUND = 3 // 设置圆角
const val TYPE_ROUND_PERCENT = 4 //圆角大小百分比
const val TYPE_ALT_SCR = 5 //覆盖在src上面的交叉图片
const val TYPE_IMG_ROTATE = 9 //图片旋转
const val TYPE_IMG_ZOOM = 10 //图片缩放
const val TYPE_OTHER = 11 //其他
}
data class ImageItem(val type: Int, val description: String)
private val mRvImgFilter: RecyclerView by id(R.id.rv_img_filter)
mRvImgFilter.layoutManager = GridLayoutManager(context, 3)
// 示例数据
val imageList = mutableListOf<ImageItem>().apply {
add(ImageItem(TYPE_SATURATION, "色彩饱和度saturation=0.1f"))
add(ImageItem(TYPE_BRIGHT_NESS, "亮度brightness=2f"))
add(ImageItem(TYPE_CONTRACT, "对比度contrast=0.5f"))
add(ImageItem(TYPE_WARMTH, "色温warmth=0.5f"))
add(ImageItem(TYPE_ROUND, "圆角round=10dp"))
add(ImageItem(TYPE_ROUND_PERCENT, "圆角百分比\nroundPercent=1.0f"))
add(ImageItem(TYPE_ALT_SCR, "覆盖在src上面的交叉图片altSrc"))
add(ImageItem(TYPE_IMG_ROTATE, "图片旋转\nimageRotate=90f"))
add(ImageItem(TYPE_IMG_ZOOM, "图片缩放imageZoom=0.5f"))
}
mRvImgFilter.adapter = ImageAdapter(imageList)
class ImageAdapter(private val imageList: List<ImageItem>) :
RecyclerView.Adapter<ImageAdapter.ImageViewHolder>() {
inner class ImageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imgFilterView: ImageFilterView = itemView.findViewById(R.id.imageView)
val textView: TextView = itemView.findViewById(R.id.textView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_image_filter_view, parent, false)
return ImageViewHolder(view)
}
override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
val item = imageList[position]
val ivFilter = holder.imgFilterView
when (item.type) {
TYPE_SATURATION -> ivFilter.saturation = 0.1f
TYPE_BRIGHT_NESS -> ivFilter.brightness = 2f
TYPE_CONTRACT -> ivFilter.contrast = 0.5f
TYPE_WARMTH -> ivFilter.warmth = 0.5f
TYPE_ROUND -> ivFilter.round = 10.dp2px().toFloat()
TYPE_ROUND_PERCENT -> ivFilter.roundPercent = 1.0f
TYPE_ALT_SCR -> {
ivFilter.setAltImageResource(R.drawable.icon_cat_h)
//上方图片的透明度
ivFilter.crossfade = 0.5f
}
TYPE_IMG_ROTATE -> { ivFilter.imageRotate = 90f }
TYPE_IMG_ZOOM -> { ivFilter.imageZoom = 0.5f }
}
holder.textView.text = item.description
}
override fun getItemCount(): Int = imageList.size
}
执行结果: