Sunday, February 24, 2013

Interface: Gradient TextView

Interface: Gradient TextView
Today we look at how you can add new properties to the elements of the example TextView, to paint it in a gradient.




Practice


To add new properties to the element, it is necessary to describe them as attributes in the xml-file values/attrs.xml.
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="GradientTextView">
        <attr name="colorStartGradient" format="integer" />
        <attr name="colorEndGradient" format="integer" />
    </declare-styleable>
</resources>

Will describe colors for our gradient (colors.xml):
<?xml version="1.0" encoding="utf-8"?>
<resources> 
       <color name="textview_start_gradient">#ffcccccc</color>
       <color name="textview_end_gradient">#ff56a9c7</color>
</resources>

Now developed a new class for our element. As an attribute of this class are the starting and ending color of the gradient. In the constructor of the class to get the attributes of the xml-file. Gradient set by the method setShader(). As the gradient to add a linear gradient.
Source code (GradientTextView.java):
public class GradientTextView extends TextView {

 private int colorStartGradient, colorEndGradient;
 
 public GradientTextView(Context context, AttributeSet attrs) {
  super(context, attrs);

  TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.GradientTextView);
  colorStartGradient = a.getColor(R.styleable.GradientTextView_colorStartGradient, -2);
  colorEndGradient = a.getColor(R.styleable.GradientTextView_colorEndGradient, -2);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  if (colorStartGradient != -2 && colorEndGradient != -2)
  { 
   getPaint().setShader(
     new LinearGradient(0, 0, 0, getHeight(), colorStartGradient,
       colorEndGradient, TileMode.MIRROR)); 
  }
  super.onDraw(canvas);
 }

}

Now we add our element in main.xml. To add new properties, you must write the following line: xmlns:app="http://schemas.android.com/apk/res/org.snowpard.proects.sixteen".

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/org.snowpard.proects.sixteen"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" >

    <org.snowpard.proects.sixteen.GradientTextView
        android:id="@+id/gradient_textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/app_name"
        android:textSize="35sp"
        app:colorEndGradient="@color/textview_end_gradient"
        app:colorStartGradient="@color/textview_start_gradient" />

</RelativeLayout>

Shadow

If you want to add a shadow to TextView, then the usual way (properties in xml) will give the wrong result because setShader change the color of the element TextView. Thus, the color of the shadow set using xml not draw. To add a shadow to our element, you must do the following:
  • Add a new color in color.xml:
<color name="textview_shadow">#ff674125</color>
  • Describe a new property for GradientTextView in attrs.xml:
<attr name="colorShadowGradient" format="integer" />
  • Add a property to shadows in main.xml
app:colorShadowGradient="@color/textview_shadow"
  • GradientTextView change class to work with shadow. The idea is to draw the element parts: first the shadow, then the element itself.
public class GradientTextView extends TextView {

 private int colorStartGradient, colorEndGradient, colorShadow;
 
 public GradientTextView(Context context, AttributeSet attrs) {
  super(context, attrs);

  TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.GradientTextView);
  colorShadow = a.getColor(R.styleable.GradientTextView_colorShadowGradient, -2);
  colorStartGradient = a.getColor(R.styleable.GradientTextView_colorStartGradient, -2);
  colorEndGradient = a.getColor(R.styleable.GradientTextView_colorEndGradient, -2);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  if (colorShadow != -2)
  {
   getPaint().setShadowLayer(3, 3, 5, colorShadow); 
   getPaint().setShader(null);
   super.onDraw(canvas);
  }
  if (colorStartGradient != -2 && colorEndGradient != -2)
  {
   getPaint().clearShadowLayer();
   getPaint().setShader(
     new LinearGradient(0, 0, 0, getHeight(), colorStartGradient,
       colorEndGradient, TileMode.MIRROR)); 
  }
  super.onDraw(canvas);
 }

}

Links

  • The source codes of this project can be downloaded here: zip