TextView:阴影Dx / Dy /半径以dip为单位?

19

我们如何以dip指定TextView的shadowDx/Dy/Radius值?目前我有:

<style name="foo">
  <item name="android:shadowDx">-1</item>
  <item name="android:shadowDy">-1</item>
  <item name="android:shadowRadius">1</item>
</style>

我似乎无法在这些地方指定"1dip"。除了在代码中设置并进行设备密度乘法,还有其他方法吗?

谢谢。

3个回答

25
我制作了一个带有自定义XML属性的覆盖TextView,以便以方便的方式处理此问题。
这也可作为库使用:https://github.com/rongi/text-view-shadow-dips
public class TextViewShadowDips extends TextView {

public TextViewShadowDips(Context context, AttributeSet attrs) {
    super(context, attrs);

    final TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.TextViewShadowDips);
    // App can crash on some devices if shadow radius is more than 25 pixels
    // On Samsung Galaxy S6 this crash happens when you copy a text from an input field
    // https://dev59.com/M1PTa4cB1Zd3GeqPnu5g
    final float shadowRadius = Math.min(
        attributes.getDimension(R.styleable.TextViewShadowDips_shadowRadius, 0f),
        25f
    );
    final float shadowDx = attributes.getDimension(R.styleable.TextViewShadowDips_shadowDx, 0f);
    final float shadowDy = attributes.getDimension(R.styleable.TextViewShadowDips_shadowDy, 0f);
    final int shadowColor = attributes.getColor(R.styleable.TextViewShadowDips_shadowColor, 0);
    if (shadowColor != 0) {
        setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
    } else {
        getPaint().clearShadowLayer();
    }
    attributes.recycle();
}

在“values”资源文件夹中的attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="TextViewShadowDips">
        <attr name="shadowRadius" format="dimension"/>
        <attr name="shadowDx" format="dimension"/>
        <attr name="shadowDy" format="dimension"/>
        <attr name="shadowColor" format="color"/>
    </declare-styleable>

</resources>

使用示例:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <my.package.name.TextViewShadowDips 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:shadowColor="#000000"
        app:shadowRadius="2dp"
        app:shadowDx="2dp"
        app:shadowDy="2dp"
        />

</RelativeLayout>

@boulder 在某些 Android 版本上,阴影功能无法使用,因为它不受 GPU 支持,需要像 :setLayerType(LAYER_TYPE_SOFTWARE, mShadow) 这样的东西吗? - android developer
@boulder 谢谢。我一直在想为什么有些视图无法实现它。 - android developer
请注意,将shadowRadius设置为大于25像素的值可能会导致某些设备崩溃。阴影半径本身不应该使用DP单位来指定,而应始终使用PX单位。此值指定阴影的模糊程度,而不是阴影的大小。阴影的大小由文本的大小决定。 - Andrew Kelly
@AndrewKelly 感谢您关于崩溃报告的反馈。关于半径。是的,半径是阴影边缘模糊程度的半径。但为什么它应该以PX为单位?它仍然是一个半径,应该以DP为单位。 - Dmitry Ryadnenko
显示剩余3条评论

19

很不幸,那是唯一的方法,抱歉 :(


2
阴影参数的单位是什么?是像素(px)、磅(pt)、密度无关像素(dp)还是可缩放像素(sp)...? - android developer
这个会被改变吗?有点烦人!另外,为什么半径为0.1的阴影被转换为0,因此没有显示出来? - Sam
这里的文档真的很缺乏。没有指定度量单位! - Bip901

17

正如Romain所说,你不能直接在XML中设置dip值。但是你仍然可以在XML中进行设置,而不必在代码中进行混乱的缩放计算。

诀窍是除了正常的values文件夹之外,还要有独立的values-hdpivalues-mdpivalues-ldpi文件夹。在每个文件夹内,创建一个单独的styles.xml,其中包含应用阴影的文本样式。

例如,在values-mdpi/styles.xml中可能会有以下内容:

<style name="my_shadow">
  <item name="android:shadowDx">0.0</item>
  <item name="android:shadowDy">-1.0</item>
  <item name="android:shadowRadius">1.0</item>
</style>

values-hdpi/styles.xml中,你有相同的样式,但值已缩放到更高密度:

<style name="my_shadow">
  <item name="android:shadowDx">0.0</item>
  <item name="android:shadowDy">-1.5</item>
  <item name="android:shadowRadius">1.5</item>
</style>

6
我强烈反对这样做。这里存在一个基本假设,即存在一组固定的像素密度,但事实并非如此。例如,您没有指定xhdpi或tvdpi(较新的像素密度),因此您将无法获得正确的值。 - hackbod
7
但是根据这个论点,在任何情况下都不能使用密度限定词。 - HRJ
在 values.xml 中使用密度桶是没有问题的。这种方法是可以的。 - portfoliobuilder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接