1

I was searching for a while right now and I tested a lot of stuff, but nothing works. I have a TextView which should have a gradient fill-color and a stroke (not the background of the Textview but the text itself).

I started by writing a class GradientTextView. At the moment I have a text with gradient fill-color and a shadow (shadow was only a test perhaps I need one later. The stroke is important at the moment). But when I'm trying to add a stroke only the stroke or the gradient fill-color is shown. I tried a lot of stuff, for example the solution from here.

import com.qualcomm.QCARSamples.ImageTargets.R; import com.qualcomm.QCARSamples.ImageTargets.R.color; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Shader; import android.graphics.Shader.TileMode; import android.graphics.SweepGradient; import android.util.AttributeSet; import android.widget.TextView; public class GradientTextView extends TextView { public GradientTextView( Context context ) { super( context, null, -1 ); } public GradientTextView( Context context, AttributeSet attrs ) { super( context, attrs, -1 ); } public GradientTextView( Context context, AttributeSet attrs, int defStyle ) { super( context, attrs, defStyle ); } int start_gradient = getResources().getColor(R.color.textview_start_gradient); int end_gradient = getResources().getColor(R.color.textview_end_gradient); Paint gradientpaint, strokepaint; @Override protected void onDraw(Canvas canvas) { // draw the shadow getPaint().setShadowLayer(10, 1, 1, 0xbf000000); getPaint().setShader(null); super.onDraw(canvas); // draw the gradient filled text getPaint().clearShadowLayer(); getPaint().setShader(new LinearGradient(0, 0, 0, getHeight(), start_gradient, end_gradient, TileMode.CLAMP ) ); super.onDraw(canvas); // **Attempts here** } } 

(attempts inserted at "attempts here" comment)

First attempt:

super.onDraw(canvas); Paint one = new Paint(); one.setStyle(Style.STROKE); one.setTextSize(20); one.setStrokeWidth(5); setTextColor(Color.BLACK); canvas.drawText(VIEW_LOG_TAG, 0, 0, one); Paint two = new Paint(); two.setStyle(Style.FILL); two.setTextSize(20); two.setStrokeWidth(0); setTextColor(Color.BLUE); two.setShader(new LinearGradient(0, 0, 0, getHeight(), start_gradient, end_gradient, TileMode.CLAMP ) ); canvas.drawText(VIEW_LOG_TAG, 0, 0, two); 

Second attempt:

Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); getPaint().setShader(new LinearGradient(0, 0, 0, getHeight(), start_gradient, end_gradient, TileMode.CLAMP ) ); mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(32); super.onDraw(canvas); Paint mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCenterPaint.setStyle(Paint.Style.STROKE); mCenterPaint.setColor(Color.GREEN); mCenterPaint.setStrokeWidth(5); super.onDraw(canvas); 

Third attempt:

gradientpaint = this.getPaint(); gradientpaint.setShader(new LinearGradient(0, 0, 0, getHeight(), start_gradient, end_gradient, TileMode.CLAMP ) ); super.onDraw(canvas); strokepaint = new Paint(gradientpaint); strokepaint.setStyle(Paint.Style.STROKE); strokepaint.setStrokeWidth(30); strokepaint.setARGB(255, 0, 0, 0); super.onDraw(canvas); 

textview_start_gradient and textview_and_gradient are simply two colors for the gradient.

Each of these lacks either stroke or fill (totally transparent).

How can I do this?

No I tried this:

New Attempt:

// draw the shadow getPaint().setShadowLayer(10, 6, 6, 0xbf000000); getPaint().setShader(null); super.onDraw(canvas); // draw the stroke getPaint().clearShadowLayer(); getPaint().setColor(Color.BLACK); getPaint().setStyle(Style.STROKE); getPaint().setStrokeWidth(5); super.onDraw(canvas); // draw the gradient filled text getPaint().setStyle(Style.FILL); getPaint().setShader(new LinearGradient(0, 0, 0, getHeight(), start_gradient, end_gradient, TileMode.CLAMP )); //getPaint().setStrokeWidth(32); super.onDraw(canvas); 

Funny thing: the shadow, the fill-gradient and the stroke show up! *But the stroke is white (not black). I think the color setting is wrong and because of that it shows up white. Any ideas?

7
  • What didn't work in your attempts? Commented Jun 5, 2014 at 22:28
  • Mostly the stroke simply didn't show up. One time there was a stroke with the given gradient, but no fill-color (transparent). Commented Jun 5, 2014 at 22:32
  • I'd combine the second attempt's Paint objects into a single one. Avoid setting the text color in the second drawText, or it will cover the gradient. I'd also avoid the double call to super, and move it up, as in the first attempt. Commented Jun 6, 2014 at 7:30
  • Thanks to @DerGolem! So I tried something like this: super.onDraw(canvas); Paint mPaint = getPaint(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.GREEN); mPaint.setStrokeWidth(5); canvas.drawText(VIEW_LOG_TAG, 0, 0, mPaint); mPaint.setStyle(Paint.Style.FILL); getPaint().setShader(new LinearGradient(0, 0, 0, getHeight(), start_gradient, end_gradient, TileMode.CLAMP )); mPaint.setStrokeWidth(32); canvas.drawText(VIEW_LOG_TAG, 0, 0, mPaint); Commented Jun 6, 2014 at 8:25
  • ...So now I see my Text I wanted to fill in white (don't now why). This text is in my app at the right/top edge (landsacape-mode). Above this text I get another text with (I think so) the stroke and the fill but I can't see it because it's beyond the view. Probably I'm missing something stupid but I don't know what it could be! Can anyone help? Commented Jun 6, 2014 at 8:26

1 Answer 1

6

So after a lot of trying, I solved the problem. Now my TextView has a black stroke, a gradient-fill-color and a shadow.

I'm still having the same GradientTextView.java class, but my solution for the onDraw is:

if(isInEditMode()){ }else{ start_gradient = getResources().getColor(R.color.textview_start_gradient); end_gradient = getResources().getColor(R.color.textview_end_gradient); } // draw the shadow getPaint().setShadowLayer(10, 6, 6, 0xbf000000); getPaint().setShader(null); super.onDraw(canvas); // draw the stroke getPaint().clearShadowLayer(); getPaint().setStyle(Style.STROKE); getPaint().setStrokeWidth(5); getPaint().setShader(new LinearGradient(0, 0, 0, getHeight(), Color.BLACK, Color.BLACK, TileMode.CLAMP )); super.onDraw(canvas); // draw the gradient filled text getPaint().setStyle(Style.FILL); getPaint().setShader(new LinearGradient(0, 0, 0, getHeight(), start_gradient, end_gradient, TileMode.CLAMP )); //getPaint().setStrokeWidth(32); super.onDraw(canvas); } 

The getPaint().setColor(Color.BLACK); didn't worked, so I simply set a Shader with a Gradient in Black (don't know whether this is a nice solution but it works).

In my xml I simply added the class (with package) as xmlns to my top-layout

Something like this

xmlns:gradient="http://schemas.android.com/apk/lib/package-name"

and instead of TextView I wrote:

<package-name.GradientTextView android:id="@+id/textView_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|top" android:textSize="20sp" android:text="@string/main1" /> 

So thanks for all given help!

Hope this will help someone else!

Sign up to request clarification or add additional context in comments.

1 Comment

Dude, you did great, i did not need the shadow but took the other parts, in other solutions through other posts on stackoverflow, they were calling a function to redraw inside on onDraw which may cause a lot of issues, but your solution of drawing only twice or three times is very good. Thanks man!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.