My question is how to add a shadow to text when TextView is selected or View that TextView is in gets selected. For example I have a CheckedTextView which changes background
Yeah, I ran into the same problem, you can change the text color using a selector in xml, but not the shadowcolor.
So in order to solve the problem, you might have to extend CheckedTextView
or whatever View you need, and then override onDraw(Canvas canvas)
according to the state of the View
Thus, you need to use
public void setShadowLayer (float radius, float dx, float dy, int color)
defined in here
for example:
@Override
protected void onDraw(Canvas canvas) {
if(isPressed()){
setShadowLayer(1, 0, 1, Color.RED);
}else{
if(isFocused()){
setShadowLayer(1, 0, 1, Color.WHITE);
}else{
setShadowLayer(1, 0, 1, Color.BLACK);
}
}
super.onDraw(canvas);
}
I hope that works
This is a current limitation of the Android SDK.
I extended TextView
for it to work, you can use it freely:
CustomTextView.java:
import android.widget.TextView;
import android.util.AttributeSet;
import android.content.res.TypedArray;
import android.content.Context;
import com.client.R;
public class CustomTextView extends TextView
{
private static String TAG = "CustomTextView";
private ColorStateList mShadowColors;
private float mShadowDx;
private float mShadowDy;
private float mShadowRadius;
public CustomTextView(Context context)
{
super(context);
}
public CustomTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
init(context, attrs);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init(context, attrs);
}
/**
* Initialization process
*
* @param context
* @param attrs
* @param defStyle
*/
private void init(Context context, AttributeSet attrs, int defStyle)
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView, defStyle, 0);
final int attributeCount = a.getIndexCount();
for (int i = 0; i < attributeCount; i++) {
int curAttr = a.getIndex(i);
switch (curAttr) {
case R.styleable.CustomTextView_shadowColors:
mShadowColors = a.getColorStateList(curAttr);
break;
case R.styleable.CustomTextView_android_shadowDx:
mShadowDx = a.getFloat(curAttr, 0);
break;
case R.styleable.CustomTextView_android_shadowDy:
mShadowDy = a.getFloat(curAttr, 0);
break;
case R.styleable.CustomTextView_android_shadowRadius:
mShadowRadius = a.getFloat(curAttr, 0);
break;
default:
break;
}
}
a.recycle();
updateShadowColor();
}
private void updateShadowColor()
{
if (mShadowColors != null) {
setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColors.getColorForState(getDrawableState(), 0));
invalidate();
}
}
@Override
protected void drawableStateChanged()
{
super.drawableStateChanged();
updateShadowColor();
}
}
You also need to add this to your attr.xml (or create one): attr.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Theme">
<attr format="reference" name="CustomTextView"/>
</declare-styleable>
<declare-styleable name="CustomTextView">
<attr name="shadowColors" format="color|reference"/>
<attr name="android:shadowDx"/>
<attr name="android:shadowDy"/>
<attr name="android:shadowRadius"/>
</declare-styleable>
</resources>
So finally you'll be able to use it in your xmls, like this:
<com.client.ui.textviews.CustomTextView
xmlns:client="http://schemas.android.com/apk/res/com.client"
android:id="@+id/join_text"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="1"
client:shadowColors="@color/btn_green_shadow_color"/>
Where @color/btn_green_shadow_color
points to a selector such a this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="@android:color/white"/>
<item android:state_pressed="true" android:color="@color/BzDarkGray"/>
<item android:color="@android:color/black"/>
</selector>
If you are not familiar with how to use custom attributes (with the custom xml namespace I used), please refer to this good StackOverFlow question.
This is what I ended up doing:
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if(isPressed()) {
setShadowLayer(15, 0, 0, getTextColors().getDefaultColor());
} else {
setShadowLayer(0, 0, 0, Color.TRANSPARENT);
}
}