爱学习的小蜗牛 發表於 2019-7-8 14:34:00

Android开发 View的阴影详解

<h1><span style="color: rgba(0, 128, 128, 1)">版权声明</span></h1>
<p>本文来自博客园,作者:观心静&nbsp;,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/11151036.html</p>
<div>本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。</div>
<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1>
<p>  Android的阴影概念是跟随Material Design设计风格出现的,因为Material Design的设计有Z轴概念,就是每个View都有自己的深度层级。Z轴的概念有了之后必然有表现这一概念的阴影效果的实现。所以google在Android5.0版本添加这阴影效果的支持。此篇博客不啰嗦Material Design的部分,我们只聊聊阴影的实现。</p>
<h1><span style="color: rgba(0, 128, 128, 1)">实现阴影功能的Api组件有那些?</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">  这里,先给出彻底了解阴影效果实现能涉及到的属性或者Api表。这样有一个笼统的概念,后面会一一讲解,就会了解这些组件各种涉及的功能范围。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">1</span>.设置View的Z轴高度 &nbsp;<span style="color: rgba(0, 0, 0, 1)">android:elevation="10dp"</span>&nbsp;&nbsp;<span style="color: rgba(0, 0, 0, 1)"> 对应代码&nbsp; setElevation();&nbsp; </span></p>
<p><span style="color: rgba(0, 0, 0, 1)">2.设置View的Z轴高度&nbsp; </span> <span style="color: rgba(0, 0, 0, 1)">android:translationZ="10dp" 对应代码 setTranslationZ()</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">3.设置View<span style="color: rgba(0, 0, 0, 1)">阴影</span>轮廓范围的模式&nbsp; android:outlineProvider="" 对应代码&nbsp; setOutlineProvider();</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">4.设置View的阴影颜色 android:outlineSpotShadowColor="#03A9F4" 对应代码 setOutlineSpotShadowColor()(<strong><span style="color: rgba(255, 0, 0, 1)">请注意!</span></strong>此条属性必需在高于Android10版本包含10的版本才有效果)</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">5.设置View的阴影光环颜色,但是基本看</span>不到,非常迷惑的属性。 <span style="color: rgba(0, 0, 0, 1)">android:outlineAmbientShadowColor="#03A9F4" 对应代码 setOutlineAmbientShadowColor(<strong><span style="color: rgba(255, 0, 0, 1)">请注意!</span></strong>此条属性必需在高于Android10版本包含10的版本才有效果)</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">6.设置View自定义形状的阴影 </span>setOutlineProvider(<span style="color: rgba(0, 0, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">new ViewOutlineProvider(){ //略..}</span>);</span></p>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">特别需要注意的地方</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">  在开始之前,还是说一下要避坑的地方。</span></p>
<ol>
<li><span style="color: rgba(0, 0, 0, 1)">请开启硬件加速功能 </span><span style="color: rgba(102, 14, 122, 1); font-weight: bold">android</span><span style="color: rgba(0, 0, 255, 1); font-weight: bold">:hardwareAccelerated</span><span style="color: rgba(0, 128, 0, 1); font-weight: bold">="true" </span><span style="color: rgba(0, 128, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">,</span></span><span style="color: rgba(0, 0, 0, 1)">现在的设备一般是默认开启硬件加速的。但是如果你主动设置关闭会出现没有阴影效果的问题。</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">请检查好自己的Android版本,必需在5.0以上。设置阴影颜色效果必需需要在10.0以上。</span></li>
<li><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">阴影是绘制于父控件上的,所以控件与父控件的边界之间需有足够空间绘制出阴影才行。</span></span></li>
<li><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">如果未设置 </span></span><span style="color: rgba(0, 0, 0, 1)">android:</span><span style="color: rgba(0, 0, 0, 1)">outlineProvider="bounds</span><span style="color: rgba(0, 0, 0, 1)">" ,那么</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">控件这个属性会默认为</span></span></span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">android:</span><span style="color: rgba(0, 0, 0, 1)">outlineProvider="</span></span></span>background</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">", 这个时候View</span>必须设置背景色,且不能为透明,否则会没有阴影。</span></span></span></li>
<li><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">不能将</span></span></span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">elevation 或者 </span></span></span></span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">translationZ 的值设置的比整个View还大,这样会有阴影效果。但是阴影的渐进效果会被拉的很长很长,会看不清楚阴影效果,你会错认觉得没有阴影效果。</span></span></span></span></span></li>
</ol>
<h1><span style="color: rgba(0, 128, 128, 1)">android:elevation与android:translationZ</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">这两个属性都是设置View的Z轴高度,他们的关系是: 实际View</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">Z轴高度</span> = elevation + translationZ</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">google为什么要这么别扭的弄出2个一样功能的实现来配置Z轴高度呢?这就是涉及到他们2个的区别:</span></p>
<ul>
<li><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><strong>elevation</strong> 是View的默认值Z轴高度 </span></span></li>
<li><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><strong>translationZ</strong> 是View的动态Z轴高度,什么是动态高度? 就是假设你需要实现阴影动画,改变Z轴高度,你就应该使用此条属性。</span></span></span></li>
</ul>
<h3><strong>实现阴影动画例子</strong></h3>
<p>xml:</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">TextView
      </span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/view_1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:text</span><span style="color: rgba(0, 0, 255, 1)">="内容1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:elevation</span><span style="color: rgba(0, 0, 255, 1)">="10dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:gravity</span><span style="color: rgba(0, 0, 255, 1)">="center"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_marginTop</span><span style="color: rgba(0, 0, 255, 1)">="30dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:outlineProvider</span><span style="color: rgba(0, 0, 255, 1)">="bounds"</span><span style="color: rgba(255, 0, 0, 1)">
      android:outlineSpotShadowColor</span><span style="color: rgba(0, 0, 255, 1)">="#FF1100"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintTop_toTopOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintLeft_toLeftOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintRight_toRightOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">TextView</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p>&nbsp;</p>
<p>注意,因为下面的效果图是git,但是git图压缩的很厉害,为了阴影效果看的更清楚,所以我这里设置了 <span style="color: rgba(0, 0, 0, 1)">android:outlineProvider="bounds" 属性 与 改变了阴影颜色 <span style="color: rgba(0, 0, 0, 1)">android:outlineSpotShadowColor="#FF1100"</span> 让下面的效果图更明显。 如果你是自己实验此代码可以忽略这2个属性。</span></p>
<p>java</p>
<div class="cnblogs_code">
<pre>     mView1 =<span style="color: rgba(0, 0, 0, 1)"> findViewById(R.id.view_1);
      mView1.setOnClickListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View.OnClickListener() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onClick(View v) {
                </span><span style="color: rgba(0, 0, 255, 1)">float</span>[] floats = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">float</span>[]{50, 30, 0<span style="color: rgba(0, 0, 0, 1)">};
                ObjectAnimator objectAnimator </span>= ObjectAnimator.ofFloat(mView1, "translationZ"<span style="color: rgba(0, 0, 0, 1)">, floats);
                objectAnimator.setDuration(</span>10 * 1000<span style="color: rgba(0, 0, 0, 1)">);
                objectAnimator.setInterpolator(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> CycleInterpolator(3f));
                objectAnimator.start();
            }
      });</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2020.cnblogs.com/blog/1497956/202004/1497956-20200429201757361-1127924315.gif" alt=""></p>
<h1><span style="color: rgba(0, 128, 128, 1)">android:outlineSpotShadowColor 与 android:outlineAmbientShadowColor</span></h1>
<p>&nbsp;在上面已经说明过了,就是改变阴影的颜色,但是此api一定得需要Android10.0以上(包含10)版本才能生效。效果图也可以参考上面的。</p>
<h1><span style="color: rgba(0, 128, 128, 1)">android:outlineProvider</span></h1>
<p>&nbsp;  阴影有一个轮廓的概念,那就是这个View的是什么形状的,换句话说这个View背景是什么形状的,阴影就需要根据View的背景形状而改变阴影形状的。举一个栗子:假如有一个圆形背景的View出现了一个正方形轮廓的阴影。多么怪异,阴影都到圆形的外面了,不是环绕的圆形阴影。所以,深入了解<span style="color: rgba(0, 0, 0, 1)">android:outlineProvider可以配置4个属性</span>对你需要什么轮廓的阴影是非常有意义的。</p>
<h3><span style="color: rgba(0, 0, 0, 1)">background</span></h3>
<p>设置这个属性,阴影轮廓将跟随 <span style="color: rgba(102, 14, 122, 1); font-weight: bold">android<span style="color: rgba(0, 0, 255, 1); font-weight: bold">:background<span style="color: rgba(0, 128, 0, 1); font-weight: bold">="@drawable/circle" </span></span></span><span style="color: rgba(0, 0, 0, 1)">设置的shape形状改变。 但是其实非常鸡肋,个人亲自验证过只有 以下2种shape才会有轮廓阴影如下。其他2个ring与line,空心矩形,都不支持。另外不支持矢量图与位图,这2个别多想了</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">支持的圆形</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">shape </span><span style="color: rgba(255, 0, 0, 1)">xmlns:android</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/apk/res/android"</span><span style="color: rgba(255, 0, 0, 1)">
    android:shape</span><span style="color: rgba(0, 0, 255, 1)">="oval"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">solid </span><span style="color: rgba(255, 0, 0, 1)">android:color</span><span style="color: rgba(0, 0, 255, 1)">="@color/colorAccent"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">shape</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p>支持的圆角矩形</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;?</span><span style="color: rgba(255, 0, 255, 1)">xml version="1.0" encoding="utf-8"</span><span style="color: rgba(0, 0, 255, 1)">?&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">shape </span><span style="color: rgba(255, 0, 0, 1)">xmlns:android</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/apk/res/android"</span><span style="color: rgba(255, 0, 0, 1)">
    android:shape</span><span style="color: rgba(0, 0, 255, 1)">="rectangle"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">solid </span><span style="color: rgba(255, 0, 0, 1)">android:color</span><span style="color: rgba(0, 0, 255, 1)">="@color/colorAccent"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">corners </span><span style="color: rgba(255, 0, 0, 1)">android:radius</span><span style="color: rgba(0, 0, 255, 1)">="20dp"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">shape</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<h4>例子:</h4>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">TextView
      </span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/view_1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:text</span><span style="color: rgba(0, 0, 255, 1)">="内容1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:elevation</span><span style="color: rgba(0, 0, 255, 1)">="10dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:gravity</span><span style="color: rgba(0, 0, 255, 1)">="center"</span><span style="color: rgba(255, 0, 0, 1)">
      android:background</span><span style="color: rgba(0, 0, 255, 1)">="@drawable/circle"</span><span style="color: rgba(255, 0, 0, 1)">
      android:outlineProvider</span><span style="color: rgba(0, 0, 255, 1)">="background"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_marginTop</span><span style="color: rgba(0, 0, 255, 1)">="30dp"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintTop_toTopOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintLeft_toLeftOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintRight_toRightOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">TextView</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p>效果图:</p>
<p>&nbsp;</p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(102, 14, 122, 1); font-weight: bold"><span style="color: rgba(0, 0, 255, 1); font-weight: bold"><span style="color: rgba(0, 128, 0, 1); font-weight: bold"><img src="https://img2020.cnblogs.com/blog/1497956/202004/1497956-20200429212131274-796959361.png" alt=""></span></span></span></span></p>
<h3><span style="color: rgba(0, 0, 0, 1)"> none </span></h3>
<p><span style="color: rgba(0, 0, 0, 1)">设置阴影轮廓为null,设置后View将没有阴影。</span></p>
<h3><span style="color: rgba(0, 0, 0, 1)"><strong>bounds</strong></span></h3>
<p><span style="color: rgba(0, 0, 0, 1)">设置这个属性,为视图View的边界生成不透明的轮廓</span></p>
<h3><span style="color: rgba(0, 0, 0, 1)">paddedBounds</span></h3>
<p>&nbsp;与<span style="color: rgba(0, 0, 0, 1)">bounds类似,设置这个属性,为视图View的填充边界生成不透明的轮廓。</span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">setOutlineProvider</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">&nbsp;  此api其实就是对应android:outlineProvider这个属性的,除了可以在代码上设置3种不同的属性&nbsp;<span style="font-weight: bold">BACKGROUND</span>,<span style="font-weight: bold">BOUNDS</span>,<span style="font-weight: bold">PADDED_BOUNDS </span></span>(是的,少了none)。</p>
<p>3个预设属性</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">      mView1.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
      mView1.setOutlineProvider(ViewOutlineProvider.BOUNDS);
      mView1.setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);</span></pre>
</div>
<p>与直接设置<span style="color: rgba(0, 0, 0, 1)">android:outlineProvider不同的地方是,它可以自定义阴影轮廓。所以,这里就只重点关注怎么<span style="background-color: rgba(255, 255, 255, 1); color: rgba(255, 0, 0, 1)"><strong>自定义阴影轮廓</strong></span>。</span></p>
<h2>自定义阴影轮廓</h2>
<div class="cnblogs_code">
<pre>      mView1.setOutlineProvider(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ViewOutlineProvider() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> getOutline(View view, Outline outline) {

            }
      });</span></pre>
</div>
<p>实现自定义,我们需要new一个<span style="color: rgba(0, 0, 0, 1)">ViewOutlineProvider抽象方法,重写<span style="color: rgba(0, 0, 0, 1)">getOutline</span>方法。这里面<strong><span style="color: rgba(255, 0, 0, 1)">Outline</span></strong>这个返回值是处理阴影轮廓的重点。</span></p>
<p>&nbsp;</p>
<h3><span style="color: rgba(0, 0, 0, 1)">Outline的Api<br></span></h3>
<p>&nbsp;</p>
<ul>
<li class="_mce_tagged_br"><span style="color: rgba(0, 0, 0, 1)">public void setOval(int left, int top, int right, </span>int bottom)&nbsp;&nbsp;             &nbsp;设置圆形阴影轮廓,参数是4个边的坐标值</li>
<li class="_mce_tagged_br" style="color: rgba(0, 0, 0, 1)">public void setOval(@NonNull Rect rect)                   &nbsp;设置圆形阴影轮廓,包含4个坐标值的Rect</li>
<li class="_mce_tagged_br" style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">public void setRoundRect(int left, int top, int right, int bottom, </span>float radius)    &nbsp; 设置圆角矩形阴影轮廓,参数是4个边的坐标值与一个圆角半径</li>
<li class="_mce_tagged_br" style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">public void setRoundRect(@NonNull Rect rect, </span>float radius)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;     设置圆角矩形阴影轮廓,包含4个坐标值的Rect与一个圆角半径</li>
<li class="_mce_tagged_br" style="color: rgba(0, 0, 0, 1)">public void setEmpty()                       &nbsp;    &nbsp;设置为空,无阴影</li>
<li class="_mce_tagged_br" style="color: rgba(0, 0, 0, 1)">public void set(@NonNull Outline src)                    设置另一个Outline并且复制成为当前View的阴影轮廓</li>
<li class="_mce_tagged_br" style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">public void setAlpha(@FloatRange(from=0.0, to=1.0) </span>float alpha)       &nbsp; <span style="color: rgba(0, 0, 0, 1)">设置阴影的透明度,取值范围是0.0到 1.0</span></li>
<li class="_mce_tagged_br" style="color: rgba(0, 0, 0, 1)">public void setConvexPath(@NonNull Path convexPath)           &nbsp; 设置传入一个凸Path,成为阴影轮廓</li>
<li class="_mce_tagged_br" style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">public void offset(int dx, int dy)                       设置阴影的坐标偏移</span></li>
</ul>
<h3><span style="color: rgba(0, 0, 0, 1)">setOval()</span></h3>
<p><span style="color: rgba(0, 0, 0, 1)">设置阴影轮廓为圆形</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">xml</span></p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">TextView
      </span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/view_1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:text</span><span style="color: rgba(0, 0, 255, 1)">="内容1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:elevation</span><span style="color: rgba(0, 0, 255, 1)">="20dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:background</span><span style="color: rgba(0, 0, 255, 1)">="@android:color/holo_orange_dark"</span><span style="color: rgba(255, 0, 0, 1)">
      android:gravity</span><span style="color: rgba(0, 0, 255, 1)">="center"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_marginTop</span><span style="color: rgba(0, 0, 255, 1)">="30dp"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintTop_toTopOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintLeft_toLeftOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintRight_toRightOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">TextView</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p>java</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">      mView1.setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                outline.setOval(0, 0, view.getWidth(), view.getHeight());
            }
      });
      mView1.setClipToOutline(true);//开启裁剪到轮廓</span></pre>
</div>
<p>这里设置 <span style="color: rgba(0, 0, 0, 1)">mView1.setClipToOutline(true); 这个属性,在设置阴影轮廓为圆形的同时,也会将View的背景裁剪成圆。所以,有一些人会有一些奇思妙想,比如把这个作为裁剪View的手段。比如把ImageView裁剪成圆形,这样设置的ImageView的图片也会变成圆形。这种用法没错,但是与google的目的有些背道而驰,google只是希望快速的方便你根据阴影形状改变下View的背景形状,而不是将它作为裁剪View背景的方法。如果将<span style="color: rgba(0, 0, 0, 1)">setOutlineProvider</span>与<span style="color: rgba(0, 0, 0, 1)">setClipToOutline</span>的组合理解成裁剪View的背景,那就大错特错了。并且<span style="color: rgba(0, 0, 0, 1)">setClipToOutline 这个方法十分鸡肋,根本无法满足你裁剪View背景的需求,这个后面在说。(裁剪View的背景的正道还是自定义View,自己去实现onDraw方法)</span></span></p>
<p>效果图:</p>
<p><img src="https://img2020.cnblogs.com/blog/1497956/202004/1497956-20200430142053546-717842873.png" alt=""></p>
<h3><span style="color: rgba(0, 0, 0, 1)">setRoundRect()</span></h3>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">设置阴影轮廓为圆角矩形</span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)">xml</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">与上面圆形阴影一样</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">java</span></p>
<div class="cnblogs_code">
<pre>      mView1.setOutlineProvider(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ViewOutlineProvider() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> getOutline(View view, Outline outline) {
                outline.setRoundRect(</span>0, 0, view.getWidth(), view.getHeight(), 30<span style="color: rgba(0, 0, 0, 1)">);
            }
      });
      mView1.setClipToOutline(</span><span style="color: rgba(0, 0, 255, 1)">true</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">开启裁剪到轮廓</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2020.cnblogs.com/blog/1497956/202004/1497956-20200430143348550-1727715553.png" alt=""></p>
<h3>setConvexPath()</h3>
<p>这个方法就很有趣了,我经过多次尝试终于明白了,这个方法怎么使用。 这些说明setConvexPath方法的特别注意点:</p>
<p>1.setConvexPath 设置的Path必需是凸的</p>
<p>2.setConvexPath 无法配合 <span style="color: rgba(0, 0, 0, 1)">setClipToOutline方法裁剪View的背景,所以在前面说<span style="color: rgba(0, 0, 0, 1)">setClipToOutline</span>其实很鸡肋。</span></p>
<h4>setConvexPath 设置的Path必需是凸的</h4>
<p>这里我用2个图片举例,你就会明白什么是凸的图像。</p>
<p>凸图像:</p>
<p>凸图像的意思是,这个图像必需是闭合且是实心的。不能只是2个线条,必需是3个以上的线条组成的一个闭合实心图像。这个矩形就是凸的图像,它有4个边线组成且是实心的。</p>
<p><img src="https://img2020.cnblogs.com/blog/1497956/202004/1497956-20200430143852314-1718452740.png" alt=""></p>
<p>不是凸的图像:</p>
<p>这个空心矩形就不是凸的。</p>
<p><img src="https://img2020.cnblogs.com/blog/1497956/202004/1497956-20200430144029896-882506006.png" alt=""></p>
<h3>给一个View是三角形背景加阴影轮廓的例子</h3>
<p>给一个View是三角形背景加阴影轮廓,假设我们现在需要给下面的矢量图背景添加一个阴影轮廓。</p>
<p><img src="https://img2020.cnblogs.com/blog/1497956/202004/1497956-20200430144718475-2112999118.png" alt=""></p>
<h3>如果我们只使用xml属性的,期望<span style="color: rgba(102, 14, 122, 1); font-weight: bold">android<span style="color: rgba(0, 0, 255, 1); font-weight: bold">:outlineProvider<span style="color: rgba(0, 128, 0, 1); font-weight: bold">="background"</span></span></span> 这个属性实现阴影,可以看到完全没有阴影的View。因为之前说了 <span style="color: rgba(102, 14, 122, 1); font-weight: bold"><span style="color: rgba(0, 0, 255, 1); font-weight: bold"><span style="color: rgba(0, 128, 0, 1); font-weight: bold">background </span></span></span><span style="color: rgba(0, 0, 0, 1)">这个属性不支持矢量图与位图的。</span></h3>
<p><span style="color: rgba(0, 0, 0, 1)">xml</span></p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">TextView
      </span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/view_1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:text</span><span style="color: rgba(0, 0, 255, 1)">="内容1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:elevation</span><span style="color: rgba(0, 0, 255, 1)">="20dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:background</span><span style="color: rgba(0, 0, 255, 1)">="@drawable/ic_triangle"</span><span style="color: rgba(255, 0, 0, 1)">
      android:gravity</span><span style="color: rgba(0, 0, 255, 1)">="center"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_marginTop</span><span style="color: rgba(0, 0, 255, 1)">="30dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:outlineProvider</span><span style="color: rgba(0, 0, 255, 1)">="background"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintTop_toTopOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintLeft_toLeftOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintRight_toRightOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">TextView</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p><span style="color: rgba(0, 0, 0, 1)">没有阴影效果的View:</span></p>
<p><img src="https://img2020.cnblogs.com/blog/1497956/202004/1497956-20200430145331488-353933390.png" alt=""></p>
<h3>通过自定义阴影轮廓给View加上一个三角形的阴影轮廓</h3>
<p>xml</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">TextView
      </span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/view_1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:text</span><span style="color: rgba(0, 0, 255, 1)">="内容1"</span><span style="color: rgba(255, 0, 0, 1)">
      android:elevation</span><span style="color: rgba(0, 0, 255, 1)">="30dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:background</span><span style="color: rgba(0, 0, 255, 1)">="@drawable/ic_triangle"</span><span style="color: rgba(255, 0, 0, 1)">
      android:gravity</span><span style="color: rgba(0, 0, 255, 1)">="center"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_marginTop</span><span style="color: rgba(0, 0, 255, 1)">="30dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:outlineProvider</span><span style="color: rgba(0, 0, 255, 1)">="bounds"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintTop_toTopOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintLeft_toLeftOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintRight_toRightOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">TextView</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p>java</p>
<div class="cnblogs_code">
<pre>      mView1.setOutlineProvider(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ViewOutlineProvider() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> getOutline(View view, Outline outline) {
                Path path </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Path();
                path.moveTo(</span>0,0<span style="color: rgba(0, 0, 0, 1)">);
                path.lineTo(view.getWidth(), </span>0<span style="color: rgba(0, 0, 0, 1)">);
                path.lineTo(</span>0<span style="color: rgba(0, 0, 0, 1)">, view.getHeight());
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">闭合路径</span>
<span style="color: rgba(0, 0, 0, 1)">                path.close();
                outline.setConvexPath(path);

            }
      });</span></pre>
</div>
<p>带三角形阴影轮廓的效果图:</p>
<p><img src="https://img2020.cnblogs.com/blog/1497956/202004/1497956-20200430150509783-329675312.png" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">如何取消Button控件阴影?</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">android:elevation="0dp" 设置为0就已经取消了控件的阴影.但是这里Button有一个坑...<br></span></p>
<h4><span style="color: rgba(0, 0, 0, 1)">关于Button坑</span></h4>
<p><span style="color: rgba(0, 0, 0, 1)">在Android5.1之后Button控件其实是强制保持在所有控件最上面的,<span style="color: rgba(0, 0, 0, 1)">android:elevation="0dp" </span>无法让Button的强制最上层属性被改变.这个时候需要就需要<span style="color: rgba(102, 14, 122, 1); font-weight: bold">android<span style="color: rgba(0, 0, 255, 1); font-weight: bold">:stateListAnimator=<span style="color: rgba(0, 128, 0, 1); font-weight: bold">"@null"</span></span></span>这个属性.</span></p>
<p>&nbsp;</p>
<div class="_mce_tagged_br">&nbsp;</div>
<div>&nbsp;</div>
<div>End</div>

</div>
<div id="MySignature" role="contentinfo">
    <div style="text-align: center">
    <p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/11151036.html </p>
    <div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/11151036.html
頁: [1]
查看完整版本: Android开发 View的阴影详解