Android一种实现任意View圆角的方案

一种实现迫不得已的圆角实现方案

该方案只针对那些“善变”的View如 SurfaceView、ListView、Viewpager等可滑动实现的圆角方案,一般情况下你不会用到,用到说明你已经基本无奈了。
这是一种经过调研后的“无奈之下”实现的圆角方案,其中需求背景是在ViewPager、ListView等可滑动系列View的圆角方案,并可在SurfaceView、TextureView上使用圆角。用background 设置一个带圆角的drawable,事实表明该方案只能实现当前View的一种背景圆角。重写ondraw试了好几种方案没有找到合适的实现方案(surfaceview、textureview无效),如果该View是一个ViewGroup系列,则子View还带有自己的“前景”效果。如ImageView设置了一个src,或surfaceView播放视频这种情况下,圆角将会失效。产品说了,不实现圆角不准下班陪老婆带孩子,mmp就有了如下“迫不得已”的实现方案。

实现原理

1、将属于四个角与圆角弧线并集的部分背景图获取到,将view的位置获取出来计算出内贴圆角矩形,将获取出来的背景图掏空一个圆角矩形
2、将掏空后的带四圆角图片贴到目标view上方,达到一种圆角效果

1、将属于四个角与圆角并集的部分背景图获取到

当程序员之前:
Android一种实现任意View圆角的方案_第1张图片
当程序员之后:
Android一种实现任意View圆角的方案_第2张图片
可以看到,几位小帅哥的身体已经被掏空,第一步就完成了最关键的一步。
但事实上,有两种情况需要君处理才能投入使用,第一种是截取下来的图片是包含需要区域内的大图,需要截图目标部分来下使用;第二种,图片原图问题,可能来源于非界面上的资源,图片过大或过小,需要匹配目标view的大小,那就需要缩放。在截取和缩放之后,接下来就来看看怎么贴和贴到哪了。

2、将view的位置获取出来计算出内贴圆角矩形

这里涉及截取view所在区域显示,可以有几种方法:

获取当前壁纸
当前activity截图
获取当前view视图

第一种:

WallpaperManager wm = (WallpaperManager)getActivity().getSystemService(Context.WALLPAPER_SERVICE);
                Bitmap wallBitmap = wm.getBitmap();

第二种:

    private Bitmap captureScreen(Activity context) {
        View cv = context.getWindow().getDecorView();
        cv.setDrawingCacheEnabled(true);
        cv.buildDrawingCache();
        Bitmap bmp = cv.getDrawingCache();
        if (bmp == null) {
            return null;
        }
        bmp.setHasAlpha(false);
        bmp.prepareToDraw();
        return bmp;
    }

第三种:

请看第二种

有了图,获取到目标view的定位,啪一声贴在上方。
获取view位置

view.getLocationOnScreen(mLocations);

结合第一步绘制

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mFrameBitmap != null) {
            int width = getMeasuredWidth();
            int height = getMeasuredHeight();
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setAntiAlias(true);
            setLayerType(LAYER_TYPE_SOFTWARE, null);
            mPaint.setShader(mBitmapShader);
            mRectF.left = 0;
            mRectF.top = 0;
            mRectF.right =mRectF.left + width ;
            mRectF.bottom =mRectF.top + height ;
            mPath.reset();//一定要这句
            mPath.addRoundRect(mRectF, mRadius, mRadius, Path.Direction.CCW);
            mPath.toggleInverseFillType();
            canvas.drawPath(mPath, mPaint);
        }
    }

完成。这不失为一种“foreground”圆角解决方案,个人建议能用“background”圆角解决的就不要用这种方案,记录一下,可能以后还会“无奈之下”用到!

你可能感兴趣的:(Android技术集锦,view的绘制,自定义view)