使用方式:直接在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. phantomjs 解码url

    以下为部分代码: var htmlnodeInfo=(allADUrlElements.snapshotItem(i).getAttribute("href").match(/\* ...

  2. vuejs初学入门环境搭建

    一.Nodejs:    1.安装下载:http://nodejs.cn/download/    2.Node.js安装配置: http://www.runoob.com/nodejs/nodejs ...

  3. centos6.5/centos7安装部署企业内部知识管理社区系统wecenter

    企业内部知识系统wecenter社区系统安装及部署 centos 6.5环境安装 因为是公司内部使用在线人数不会太多,使用yum安装lamp环境即可 1.安装lamp基本环境 yum -y insta ...

  4. Spark学习之概念了解

    Spark简介: Spark是一个快速且通用的集群计算模型: 1.Spark是快速的:快速是指处理几T到几批数据量的时候,他的处理时间是几秒钟或几分钟,相对于hadoop的几分钟到几小时是非常快速的, ...

  5. https协议的接口测试

    用jmeter测试https接口: 和传统的http协议套路不太一样. 注意细节: 1.取样器正常选择http请求,端口号:为443(具体根据接口文档我刚开始用的80端口所以错了) 2.请求方法,一定 ...

  6. PYTHON-基本数据类型-数字类型,字符串类型,列表类型-练习

    # 字符串练习# 写代码,有如下变量,请按照要求实现每个功能 (共6分,每小题各0.5分)# name = " aleX"# # 1) 移除 name 变量对应的值两边的空格,并输 ...

  7. bert 词典扩充方案

  8. OneNET麒麟座应用开发之九:与SD卡通讯并保存数据

    由于需要记录的数据量比较大,而且有些时候,有的用户不方便实时上传数据,所以要求使用SD卡存储数据然后人工收取上传.为此我们选择了一种通用的SD卡读写器. 1.读卡器简介 该读卡器整合 SD 卡规范和 ...

  9. Java多线程中wait语句的具体使用技巧

    Java多线程在使用的时候会有很多语句需要我们具体的学习,在这其中wait()就是其中的一个.当然我们需要不断的努力学习才能掌握这一个语句的应用,下面的代码会对你学习Java多线程有所帮助. clas ...

  10. LeetCode(8):字符串转整数(atoi)

    Medium! 题目描述: 实现 atoi,将字符串转为整数. 在找到第一个非空字符之前,需要移除掉字符串中的空格字符.如果第一个非空字符是正号或负号,选取该符号,并将其与后面尽可能多的连续的数字组合 ...