我们在EasyConstraintLayout中初始化paint,并且关闭硬件加速,然后在drawChild中实现阴影逻辑,最终代码如下。

public class EasyConstraintLayout extends ConstraintLayout {
private Paint shadowPaint;
private Paint clipPaint;

public EasyConstraintLayout(Context context, AttributeSet attrs) {
super(context, attrs);
shadowPaint = new Paint();
shadowPaint.setAntiAlias(true);
shadowPaint.setDither(true);
shadowPaint.setFilterBitmap(true);
shadowPaint.setStyle(Paint.Style.FILL);

clipPaint = new Paint();
clipPaint.setAntiAlias(true);
clipPaint.setDither(true);
clipPaint.setFilterBitmap(true);
clipPaint.setStyle(Paint.Style.FILL);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

@Override
public ConstraintLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}

@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
for (int i = 0, size = getChildCount(); i < size; i++) {
View v = getChildAt(i);
ViewGroup.LayoutParams lp = v.getLayoutParams();
if (lp instanceof EasyLayoutParams) {
EasyLayoutParams elp = (EasyLayoutParams) lp;
elp.getData().initPaths(v);
}
}
}

@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
ViewGroup.LayoutParams lp = child.getLayoutParams();
boolean ret = false;
if (lp instanceof EasyLayoutParams) {
EasyLayoutParams elp = (EasyLayoutParams) lp;
LayoutParamsData data = elp.getData();
if (isInEditMode()) {//预览模式采用裁剪
canvas.save();
canvas.clipPath(data.widgetPath);
ret = super.drawChild(canvas, child, drawingTime);
canvas.restore();
return ret;
}
if (!data.hasShadow && !data.needClip)
return super.drawChild(canvas, child, drawingTime);
//为解决锯齿问题,正式环境采用xfermode
if (data.hasShadow) {
int count = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
shadowPaint.setShadowLayer(data.shadowEvaluation, data.shadowDx, data.shadowDy, data.shadowColor);
shadowPaint.setColor(data.shadowColor);
canvas.drawPath(data.widgetPath, shadowPaint);
shadowPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
shadowPaint.setColor(Color.WHITE);
canvas.drawPath(data.widgetPath, shadowPaint);
shadowPaint.setXfermode(null);
canvas.restoreToCount(count);

}
if (data.needClip) {
int count = canvas.saveLayer(child.getLeft(), child.getTop(), child.getRight(), child.getBottom(), null, Canvas.ALL_SAVE_FLAG);
ret = super.drawChild(canvas, child, drawingTime);
clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
clipPaint.setColor(Color.WHITE);
canvas.drawPath(data.clipPath, clipPaint);
clipPaint.setXfermode(null);
canvas.restoreToCount(count);
}
}
return ret;
}

static class LayoutParams extends ConstraintLayout.LayoutParams implements EasyLayoutParams {

private LayoutParamsData data;

public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
data = new LayoutParamsData(c, attrs);
}

@Override
public LayoutParamsData getData() {
return data;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
使用方法
<?xml version="1.0" encoding="utf-8"?>
<io.github.iamyours.easylayout.EasyConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<View
android:id="@+id/v_back"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_margin="10dp"
android:background="#fff"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_radius="4dp"
app:layout_shadowColor="#3ccc"
app:layout_shadowEvaluation="15dp" />

<ImageView
android:id="@+id/iv_head"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="10dp"
android:background="#eee"
app:layout_constraintBottom_toBottomOf="@id/v_back"
app:layout_constraintLeft_toLeftOf="@id/v_back"
app:layout_constraintTop_toTopOf="@id/v_back"
app:layout_radius="40dp"
app:layout_shadowColor="#5f00"
app:layout_shadowEvaluation="8dp" />

<View
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="30dp"
android:background="#ccc"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_back"
app:layout_radius="30dp"
app:layout_shadowColor="#8f0f"
app:layout_shadowDx="4dp"
app:layout_shadowDy="4dp"
app:layout_shadowEvaluation="10dp" />
</io.github.iamyours.easylayout.EasyConstraintLayout>
---------------------

drawChild中画阴影,裁剪出圆角的更多相关文章

  1. python—networkx:在一张图中画出多个子图

    通过plt.subplot能够在一张图中画出多个子图 #coding: utf-8 #!/usr/bin/env python """ Draw a graph with ...

  2. iOS高效裁剪图片圆角算法

    项目有个需求:裁剪图片,针对头像,下面是要求: 大家可以看到这张图片的圆角已经去除,下面说说我在项目利用了两种方式实现此裁剪以及查看技术文档发现更高效裁剪方式,下面一一讲解:看下来大约需要15-20分 ...

  3. 在ps中画两个同心圆并且把两个同心圆进行任意角度切割

    在工作中遇到要在ps中画如图两个同心圆,并且进行6等分.查找资料加自己摸索,可以通过以下方式实现: 1.新建一画布.并用通过标尺画出两条水平和垂直参考线,选择椭圆工具,并在选项设置中选择圆和从中心两个 ...

  4. Android Demo---如何敲出圆角的Button+圆角头像

    经常玩儿App的小伙伴都知道,APP上面有很多按钮都是圆角的,圆形给人感觉饱满,富有张力,不知道设计圆角按钮的小伙伴是不是和小编有着相同的想法`(*∩_∩*)′,听小编公司开发IOS的小伙伴说,他们里 ...

  5. css边框样式、边框配色、边框阴影、边框圆角、图片边框

     边框样式 点线式边框 破折线式边框 直线式边框 双线式边框 槽线式边框 脊线式边框 内嵌效果的边框 突起效果的边框 <div style="width: 300px; height: ...

  6. 如何在CorelDRAW中创建对象阴影

    阴影工具可以为对象创建光线映射的阴影效果,使对象产生较强的立体感.可以为大多数对象或群组对象添加阴影,其中包括美术字.段落文本和位图.创建对象阴影可以增加视觉层次,使图形更加逼真. CorelDRAW ...

  7. 用字体在网页中画Icon图标

    第一步,下载.IcoMoon网站选择字体图标并下载,解压后将fonts文件夹放在工程目录下.fonts文件夹内有四种格式的字体文件: 注:由于浏览器对每种字体的支持程度不一致,要想在所有浏览器中都显示 ...

  8. bootstrap中popover.js(弹出框)使用总结+案例

    bootstrap中popover.js(弹出框)使用总结+案例 *转载请注明出处: 作者:willingtolove: http://www.cnblogs.com/willingtolove/p/ ...

  9. 字体在网页中画ICON图标

    用字体在网页中画ICON图标有三种小技巧: 1.用CSS Sprite在网页中画小图标 实现方法: 首先将小图片整合到一张大的图片上 然后根据具体图标在大图上的位置,给背景定位.background- ...

随机推荐

  1. python基础-7模块,第三方模块安装方法,使用方法。sys.path os sys time datetime hashlib pickle json requests xml

    模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...

  2. POJ-1502 MPI Maelstrom 迪杰斯特拉+题解

    POJ-1502 MPI Maelstrom 迪杰斯特拉+题解 题意 题意:信息传输,总共有n个传输机,先要从1号传输机向其余n-1个传输机传输数据,传输需要时间,给出一个严格的下三角(其实就是对角线 ...

  3. [BZOJ 3731] Gty的超级妹子树 (树分块)

    [BZOJ 3731] Gty的超级妹子树 (树分块) 题面 给出一棵树(或森林),每个点都有一个值.现在有四种操作 1.查询x子树里>y的值有多少个 2.把点x的值改成y 3.添加一个新节点, ...

  4. python 导入re模块语法及规则

    正则表达式是功能比较强大的模块,应用在很多地方,抓网页,数据分析,数据验证等,下面讲述python 导入re模块语法及规则. 1,re模块语法 re.match 从头开始匹配 re.search 匹配 ...

  5. 配置sde使可以使用sde sql(ST_Geometry)操作空间数据

    用处:进行此配置后,可以用sql语言,与sde空间数据库进行空间查询,增删改图层的要素等 PS:同时也是解决 ORA-28595Extproc 代理 DLL 路径无效 的方法 ORA-06512: 在 ...

  6. AngularJS语法

    1,$scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带. $scope是一个对象,有可用的方法和属性. $scope可应用在视图和控制器上.2,所有的 ...

  7. linux Sersync 参数说明

    Sersync 的可选功能是通过 xml 配置文件来实现的,下面来为大家解释该文件! 在该文件中,使用<!--中间是注释内容-->的方式去注释信息,注意不是我们平时# [root@SERS ...

  8. CentOS7系统局域网内配置本地yum源解决cannot find a valid baseurl for repo

    一.     问题详情 因为服务器无法连接外网,所有直接用yum安装某些功能将受到影响,报错如下: Error: Cannot find a valid baseurl for repo: base ...

  9. nginx http正向代理简单配置及systemd 配置

    #user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #erro ...

  10. [php] phar

    build.php打包www目录: <?php class A{ public $a = 1; } $p = new Phar('test.phar',0,'test.phar'); $p-&g ...