使用方式:直接在xml中使用即可。

<com.base.baseview.RoundLayout
android:id="@+id/example_view"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:layout_gravity="center_horizontal"
app:attr_round_corner="7dp">
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout; /**
* 圆角布局
* 支持自定义属性见<>declare-styleable name="RoundLayout"</>
* <p>
* 需要圆角的View作为<>RoundLayout</>的子View即可,设置<>attr_round_corner</>圆角半径
*/
public class RoundLayout extends RelativeLayout {
public float[] radii = new float[8]; // top-left, top-right, bottom-right, bottom-left
public Path mClipPath; // 剪裁区域路径
public Paint mPaint; // 画笔
public int mStrokeColor; // 描边颜色
public int mStrokeWidth; // 描边半径
public boolean mClipBackground; // 是否剪裁背景
public Region mAreaRegion; // 内容区域
public RectF mLayer; // 画布图层大小
private int mRoundCorner; // 圆角大小 public RoundLayout(Context context, int radius) {
this(context);
this.mRoundCorner = PixelUtils.dip2px(context, radius);
} public RoundLayout(Context context) {
this(context, null);
} public RoundLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public RoundLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context, attrs);
} @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mLayer.set(0, 0, w, h);
refreshRegion(this);
} @Override
protected void dispatchDraw(Canvas canvas) {
canvas.saveLayer(mLayer, null, Canvas.ALL_SAVE_FLAG);
super.dispatchDraw(canvas);
onClipDraw(canvas);
canvas.restore();
} @Override
public void draw(Canvas canvas) {
refreshRegion(this);
if (mClipBackground) {
canvas.save();
canvas.clipPath(mClipPath);
super.draw(canvas);
canvas.restore();
} else {
super.draw(canvas);
}
} public void initAttrs(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundLayout);
mStrokeColor = ta.getColor(R.styleable.RoundLayout_attr_stroke_color, Color.WHITE);
mStrokeWidth = ta.getDimensionPixelSize(R.styleable.RoundLayout_attr_stroke_width, 0);
mClipBackground = ta.getBoolean(R.styleable.RoundLayout_attr_clip_background, false);
if (mRoundCorner == 0) {
mRoundCorner = ta.getDimensionPixelSize(R.styleable.RoundLayout_attr_round_corner, 4);
} int roundCornerTopLeft = ta.getDimensionPixelSize(
R.styleable.RoundLayout_attr_round_corner_top_left, mRoundCorner);
int roundCornerTopRight = ta.getDimensionPixelSize(
R.styleable.RoundLayout_attr_round_corner_top_right, mRoundCorner);
int roundCornerBottomLeft = ta.getDimensionPixelSize(
R.styleable.RoundLayout_attr_round_corner_bottom_left, mRoundCorner);
int roundCornerBottomRight = ta.getDimensionPixelSize(
R.styleable.RoundLayout_attr_round_corner_bottom_right, mRoundCorner);
ta.recycle(); radii[0] = roundCornerTopLeft;
radii[1] = roundCornerTopLeft; radii[2] = roundCornerTopRight;
radii[3] = roundCornerTopRight; radii[4] = roundCornerBottomRight;
radii[5] = roundCornerBottomRight; radii[6] = roundCornerBottomLeft;
radii[7] = roundCornerBottomLeft; mLayer = new RectF();
mClipPath = new Path();
mAreaRegion = new Region();
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setAntiAlias(true); setLayerType(View.LAYER_TYPE_HARDWARE, null);
} public void refreshRegion(View view) {
int w = (int) mLayer.width();
int h = (int) mLayer.height();
RectF areas = new RectF();
areas.left = view.getPaddingLeft();
areas.top = view.getPaddingTop();
areas.right = w - view.getPaddingRight();
areas.bottom = h - view.getPaddingBottom();
mClipPath.reset(); mClipPath.addRoundRect(areas, radii, Path.Direction.CW);
Region clip = new Region((int) areas.left, (int) areas.top,
(int) areas.right, (int) areas.bottom);
mAreaRegion.setPath(mClipPath, clip);
} public void onClipDraw(Canvas canvas) {
if (mStrokeWidth > 0) {
// 将与描边区域重叠的内容裁剪掉
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mPaint.setColor(Color.WHITE);
mPaint.setStrokeWidth(mStrokeWidth * 2);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawPath(mClipPath, mPaint);
// 绘制描边
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
mPaint.setColor(mStrokeColor);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawPath(mClipPath, mPaint);
}
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawPath(mClipPath, mPaint);
}
}

喜欢的朋友点个赞吧,真的是非常好用!

android圆角功能,非常好用,可以用在图片,视频,gif等上面的更多相关文章

  1. Android P 功能和 API

    Android P 功能和 API Android P 为用户和开发者引入众多新特性和新功能. 本文重点介绍面向开发者的新功能. 要了解新 API,请阅读 API 差异报告或访问 Android AP ...

  2. [译]:Xamarin.Android平台功能——位置服务

    返回索引目录 原文链接:Location Services. 译文链接:Xamarin.Android平台功能--位置服务 本部分介绍位置服务以及与如何使用位置提供商服务 Location Servi ...

  3. Android表情功能

    Android表情功能 标签(空格分隔): 未分类 转载自:android edittext插入表情(基于socket方式),并对文中不正确的内容进行整理和修正 [TOC] 涉及知识点: Androi ...

  4. Cocos2d-x使用android拍照功能加载照片内存过大,通过另存照片尺寸大小解决

    使用2dx调用android拍照功能,拍照结束后在2dx界面显示拍照照片,如果不对照片做处理,会出现内存过大的问题,导致程序崩溃,如果仅仅另存拍照照片,则照片质量大小均下降,导致照片不够清晰,后来发现 ...

  5. Android定位功能

    不说废话,直接说说实现android定位有关的API吧. 这些API都在android.location包下,一共有三个接口和八个类.它们配合使用即可实现定位功能. 三个接口: GpsStatus.L ...

  6. Android定位功能(二)

    在前文Android定位功能(一)中,已经大致介绍了一下在Android平台中,和定位功能相关的类,并举例获取了位置信息.但是前文是基于Criteria定制了一个标准,通过getBestProvide ...

  7. GlideDemo【Glide3.7.0版本的简单使用以及圆角功能】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本Demo主要记录Glide3.7.0版本的简单运用和实现圆角方案. 效果图 代码分析 Glide的centerCrop()和fit ...

  8. GlideNewDemo【Glide4.7.1版本的简单使用以及圆角功能】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 简单记录下Glide4.7.1版本的使用和实现圆角方案. 注意:关于详细使用请仔细阅读<官方指南>. 效果图 使用步骤 ...

  9. Delphi xe7 up1 调用android振动功能

    Delphi xe7 up1 调用android振动功能 振动用到以下4个单元: Androidapi.JNI.App,Androidapi.JNIBridge,Androidapi.JNI.Os,A ...

随机推荐

  1. Win7 启动修复

    先让我们看一下windows7的启动过程的常识:电脑加电后,首先是启动BIOS程序,BIOS自检完毕后,找到硬盘上的主引导记录MBR,MBR读取DPT(分区表),从中找出活动的主分区,然后读取活动主分 ...

  2. pyspider使用

    #!/usr/bin/env python # -*- encoding: utf-8 -*- # Created on 2018-11-08 22:33:55 # Project: qsbk fro ...

  3. 【转】assert预处理宏与预处理变量

    assert assert是一个预处理宏,由预处理器管理而非编译器管理,所以使用时都不用命名空间声明,如果你写成std::assert反而是错的.使用assert需要包含cassert或assert. ...

  4. phpstudy中apache的默认根目录的配置

    默认配置文件是:vhosts.conf. 安装laravel后需要把根目录配置到public. 下面的配置需要在本地计算机的host文件配置域名,一个是“localhost”,一个是“www.goho ...

  5. HDU 5288 OO&rsquo;s Sequence

    题意: 给你一个序列, 有一个函数 F(L,R) 其中 ai 均不能 被 aL - aR整除的  函数值是这个ai个数 思路 : 反过来求 满足这样的条件的 ai 的区间,然后求和 #include& ...

  6. robotium之does not have a signature matching问题

    今天发现个很low的问题,脚本都写好了,运行Robotium测试用例时报错如下: [2017-03-01 09:58:54 - baiduAppTest] Test run failed: Permi ...

  7. Protocol Buffers简明教程

    随着微服务架构的流行,RPC框架渐渐地成为服务框架的一个重要部分. 在很多RPC的设计中,都采用了高性能的编解码技术,Protocol Buffers就属于其中的佼佼者. Protocol Buffe ...

  8. Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)

    在Android 2.3(Gingerbread) 系统的时候,我写过一篇关于“Android 震动马达系统“的文章,当时的Linux内核还是2.6版本的.写那篇文章的目的,是想彻底的了解从硬件到驱动 ...

  9. C++ code:More Loop Designs

    1  逻辑判断 对于逻辑判断问题,一般都要考虑全部的可能性,然后从这些可能性中按条件逐一排查,直到最后获得某个结论. [百钱买百鸡问题] 问题描述: 雄鸡(cock)7元一只,母鸡(hen)5元一只, ...

  10. php中静态方法和静态属性的介绍

    静态分为两个部分:静态属性和静态方法 静态的东西都是给类用的(包括类常量),非静态的都是给对象用的 静态属性 在定义属性的时候,使用关键字static修饰的属性称之为静态属性. 静态方法 使用stat ...