圆角控件之ImageFilterView详解

简介

  我们以往显示圆角图形,一般使用三方库或者自己写一个控件来实现。在constraintlayout 2.0出来后,提供了一个圆角控件ImageFilterView,使用更加方便,并且自带滤镜功能。可以显示本地图片(R.drawable引用)和网络图片(比如Glide加载)。

属性

  • 圆角大小:取值0-size/2之间,超过就没什么意义了,默认0,就是方形;对于正方形来说,取值size/2就是圆形, 圆角是针对View的, 将View绘制成圆角.
  • 圆角比例:取值0-1之间,超过1就没什么意义了,默认0就是方形,1是圆形图片。和app:round意思一样,只不过一个是具体的大小,一个是百分比。
  • 缩放:放大或缩小图片大小,比如:2表示图片放大到原来的2倍,0.5表示图片缩小到原来的一半。View的大小不变,只是显示的图片缩放了。
  • 旋转:旋转图片的角度,比如90,表示图片旋转90度。View的角度和大小是不变的。
  • 交叉图:需要跟app:crossfade共同使用,app:crossfade取值0-1,默认0为交叉图完全透明,不展示。取值1交叉图完全展示,覆盖到src上。
  • 饱和度:float型,默认1,取值0为灰阶样式,大于1的数值都是超饱和状态,色彩非常艳丽,有点辣眼睛。
  • 亮度:float型,默认1,值越大亮度越高。
  • 色温:float型,默认值1,小于1是冷色调,大于1是暖色调。
  • 对比度:float型,默认1,取值0相当于图片变全黑,大于1都是高对比度状态。
  • ,官方释义:定义alt图像是在原始图像的顶部淡入,还是与其交叉淡入。默认值为true。对于半透明对象设置为false。

使用

1. 滤镜
  一般应用都是显示图片的原始效果图,鲜少使用滤镜功能,除非是相册等专门处理图片的应用。所以,这里不会专门介绍,只略提一笔。

//继承ImageView,本质上就是一个ImageView
public class ImageFilterView extends androidx.appcompat.widget.AppCompatImageView {
    //这个类就是用来处理滤镜功能的
    static class ImageMatrix {
        float[] m = new float[4 * 5];
        //颜色矩阵,用来实现各种滤镜效果
        ColorMatrix mColorMatrix = new ColorMatrix();
        ColorMatrix mTmpColorMatrix = new ColorMatrix();
        float mBrightness = 1;
        float mSaturation = 1;
        float mContrast = 1;
        float mWarmth = 1;

        void updateMatrix(ImageView view) {
            mColorMatrix.reset();
            boolean filter = false;
            //设置饱和度效果
            if (mSaturation != 1.0f) {
                saturation(mSaturation);
                mColorMatrix.set(m);
                filter = true;
            }
            //设置对比度效果
            if (mContrast != 1.0f) {
                mTmpColorMatrix.setScale(mContrast, mContrast, mContrast, 1);
                mColorMatrix.postConcat(mTmpColorMatrix);
                filter = true;
            }
            //设置色温效果
            if (mWarmth != 1.0f) {
                warmth(mWarmth);
                mTmpColorMatrix.set(m);
                mColorMatrix.postConcat(mTmpColorMatrix);
                filter = true;
            }
            //设置亮度效果
            if (mBrightness != 1.0f) {
                brightness(mBrightness);
                mTmpColorMatrix.set(m);
                mColorMatrix.postConcat(mTmpColorMatrix);
                filter = true;
            }
            //其实就是通过setColorFilter实现颜色的滤镜效果
            if (filter) {
                view.setColorFilter(new ColorMatrixColorFilter(mColorMatrix));
            } else {
                view.clearColorFilter();
            }
        }
    }

2. 缩放
  以下将图片的大小放大到原来的1.5倍。

    
image.png

效果图:屏幕背景绿色, View背景橙色. 左边是原图,右边是放大1.5倍图。可以看到,View大小是不变的,还是原图大小。

3. 旋转
  以下将图片的角度顺时针旋转60度。

    
imageRotate.jpg

效果图:屏幕背景绿色, View背景橙色. 左边是原图,右边是旋转60度的效果。可以看到,图片旋转后,超出View外是不会显示的。

3. 圆角
   将圆角设置为size/2, 圆角比例设置为1. 如下88px是view的size/2.

    

    
round.jpg

效果图:屏幕背景绿色, View背景橙色. 左边是原图,中间是设置圆角size/2的效果, 右边是设置圆角比例为1的效果。可以看到,设置圆角或圆角比例后, View的视图显示区域变化了.

那么问题来了, 圆角的大小怎么体现, 从View来看的话, 是哪里的值呢?


image.png

如图, 红色部分即圆角大小.

原理

1. 缩放和旋转
   其实就是通过Matrix, 设置Translate和Rotate值实现的.

    private void setMatrix() {
         ......
        float panX = (Float.isNaN(mPanX)) ? 0 : mPanX;
        float panY = (Float.isNaN(mPanY)) ? 0 : mPanY;
        float zoom = (Float.isNaN(mZoom)) ? 1 : mZoom;
        float rota = (Float.isNaN(mRotate)) ? 0 : mRotate;
        Matrix imageMatrix = new Matrix();
        imageMatrix.reset();
        float iw = getDrawable().getIntrinsicWidth();
        float ih = getDrawable().getIntrinsicHeight();
        float sw = getWidth();
        float sh = getHeight();
        float scale = zoom * ((iw * sh < ih * sw) ? sw / iw : sh / ih);
        imageMatrix.postScale(scale, scale);
        float tx = 0.5f * (panX * (sw - scale * iw) + sw - (scale * iw));
        float ty = 0.5f * (panY * (sh - scale * ih) + sh - (scale * ih));
        imageMatrix.postTranslate(tx, ty);
        imageMatrix.postRotate(rota, sw / 2, sh / 2);
        setImageMatrix(imageMatrix);
        setScaleType(ScaleType.MATRIX);
    }

2. 圆角
   通过Path和Outline实现, 圆角比例类似.

    public void setRound(float round) {
            ......
            if (mPath == null) {
                mPath = new Path();
            }
            if (mRect == null) {
                mRect = new RectF();
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                if (mViewOutlineProvider == null) {
                    mViewOutlineProvider = new ViewOutlineProvider() {
                        @Override
                        public void getOutline(View view, Outline outline) {
                            int w = getWidth();
                            int h = getHeight();
                            outline.setRoundRect(0, 0, w, h, mRound);
                        }
                    };
                    setOutlineProvider(mViewOutlineProvider);
                }
                setClipToOutline(true);
            }
            int w = getWidth();
            int h = getHeight();
            mRect.set(0, 0, w, h);
            mPath.reset();
            mPath.addRoundRect(mRect, mRound, mRound, Path.Direction.CW);
   
        if (change) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                invalidateOutline();
            }
        }

    }

总结

  ImageFilterView提供了非常方便的显示圆角的方式, 另外, ImageFilterButton也具有同样的功能, 实现也几乎一样, 唯一不同的是, ImageFilterView继承ImageView, 而ImageFilterButton继承ImageButton. 还有一个控件MotionButton, 继承Button, 也可以实现圆角功能, 但是没有滤镜功能.

你可能感兴趣的:(圆角控件之ImageFilterView详解)