Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TextView:shadowDx/Dy/Radius in dip?

Tags:

android

How can we specify a TextView's shadowDx/Dy/Radius values in dip? Right now I have:

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

I can't seem to specify "1dip" in these places. Is there a way to do it other than setting them in code and doing the device density multiplication ourselves?

Thanks

like image 512
user291701 Avatar asked Jan 31 '11 19:01

user291701


3 Answers

I made an overridden TextView with custom xml attributes to handle this in a convenient way.

Which is also available as a library: 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://stackoverflow.com/questions/4866928/ranges-for-radius-in-shadowradius-and-visiblity-in-textview?lq=1
    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();
}

attrs.xml inside "values" resource folder

<?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>

Usage example:

<?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>
like image 127
Dmitry Ryadnenko Avatar answered Nov 20 '22 13:11

Dmitry Ryadnenko


Unfortunately that's the only way, sorry :(

like image 36
Romain Guy Avatar answered Nov 20 '22 12:11

Romain Guy


As Romain says, you can't set dip values directly in XML. You can still do it in XML, though, without having to do messy scaling calculations in your code.

The trick is to have separate values-hdpi, values-mdpi and values-ldpi folders, in addition to your normal values folder. Inside each, create a separate styles.xml containing a style for your text with the shadow applied.

For example, you might have this in 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>

And in values-hdpi/styles.xml, you have the same style but with the values scaled for the higher density:

<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>
like image 17
Graham Borland Avatar answered Nov 20 '22 13:11

Graham Borland