Faded Text - TextView, first and last line should fade out (if needed)

767 views
asked Nov 22, 2017 in GUI Development by Christoph Friegel

Hi,

Using a TextView and a SlideTouchHandler allows me to implement a slideable Text within seconds.

However besides sliding through the text, I want also to show if there are more lines on the bottom or on the top. A good visual effect is to fade out the text.
This allows the user to see at first glance if he can slide along top or bottom.

Currently I fake this faded text via rectangle gradient, just like this:

How to do this the right way to get a smooth faded text?

1 Answer

0 votes
answered Nov 22, 2017 by rleberfinger
 
Best answer

Hello,
using the gradient to get a fade to dark impression is a simple way to do this, but this only works if there is a solid background.
To get real fade out effect, the colors of the text rendering funtions can be used.
Within the following example you can see a FadedVerticalText, derived from a Views::Text.

See attached example.

Here the interesting part is the usage of test rendering functions within the Draw() mothof of the view:

// Nothing to draw
if (( flowString == "" ) || ( pure Font == null ))
  return;

var Views::TextAlignment align    = pure Alignment;
var Resources::Font      font     = pure Font;
var rect                 rd       = pure Bounds + aOffset;
var color                ctl      = pure ColorTL;
var color                ctr      = pure ColorTR;
var color                cbr      = pure ColorBR;
var color                cbl      = pure ColorBL;
var int32                opacity  = ((( aOpacity + 1 ) * pure Opacity ) >> 8 ) + 1;
var int32                noOfRows = flowString[0];
var rect                 area     = GetContentArea() + aOffset;
var point                ofs      = rd.origin - area.origin - point( 0, font.Ascent );

// Modulate the color values by the opacity?
if ( opacity < 256 )
{
  ctl.alpha = uint8(( ctl.alpha * opacity ) >> 8 );
  ctr.alpha = uint8(( ctr.alpha * opacity ) >> 8 );
  cbr.alpha = uint8(( cbr.alpha * opacity ) >> 8 );
  cbl.alpha = uint8(( cbl.alpha * opacity ) >> 8 );
}

// Display a single text row
if ( noOfRows == 1 )
{
  var int32 count = int32( flowString[1]) - 2;

  // Don't show the <new line> sign at the end of a text row
  if ( flowString[ count + 2 ] == '\n' )
    count = count - 1;

  aCanvas.DrawText( aClip, font, flowString, 3, count, rd, ofs, 0,
    ctl, ctr, cbr, cbl, true );
}

// Nothing more to draw
if ( noOfRows < 2 )
  return;

var int32 leading = font.Leading;

// Overload the font metrics?
if ( pure RowDistance > 0 )
  leading = pure RowDistance - font.Ascent - font.Descent;

// Displaying multiline text. Process and display the text row by row
var int32 rowHeight = font.Ascent + font.Descent + leading;
var int32 y         = area.y1;
var int32 i         = 1;
var int32 c         = flowString[i];

// Fading is enabled when first/last row is almost invisible
var float fadingIndicator = 0.0;
var rect contentArea = GetContentArea();
var bool topFade = (int32)((float)rowHeight * fadingIndicator) < -contentArea.y1 + Bounds.origin.y;
var int32 fadableTextHeight = (contentArea.y2 - (int32)((float)rowHeight * fadingIndicator));
var bool bottomFade = Bounds.h + Bounds.origin.y < fadableTextHeight;

// Skip over rows lying outside the clipping area
while ((( y + rowHeight ) < aClip.y1 ) && ( c > 0 ))
{
  i = i + c;
  y = y + rowHeight;
  c = flowString[i];
}

// Now draw all following text rows which are enclosed within the clipping 
// area
while (( y < aClip.y2 ) && ( c > 0 ))
{
  var int32 minWidth = 0;
  var int32 cc   = c - 2;
  var point ofs2 = ofs;

  ofs2.y = ofs2.y + area.y1 - y;
          
  // If the text row was terminated with the <new line> sign -> Ignore it! Do 
  // not display <new line> signs!
  if ( flowString[ i + c - 1 ] == '\n' )
    cc = cc - 1;

  // Ignore empty rows (\n only) ...
  if ( cc <= 0 )
    ;

  // Should the text be stretched to fill the whole view's width?
  // In this case no text row width calculation is necessary.
  else if ( align.contains( Views::TextAlignment[ AlignHorzJustified ]))
  {
    // The text row was terminated with the <new line> sign, or it
    // is the last text row -> In this case do not stretch the text row!
    if (( cc < ( c - 2 )) || ( flowString[ i + c ] == '\0' ))
      {} //default way

    // This text row can be stretched ...
    else
      minWidth = area.w;
  }

  // Should the text be aligned to the right?
  else if ( align.contains( Views::TextAlignment[ AlignHorzRight ]))
  {
    // Using the text width, calculate the horizontal text drawing position.
    ofs2.x = ofs2.x - area.w + font.GetTextAdvance( flowString, i + 2, cc );
  }

  // Should the text be centered?
  else if ( align.contains( Views::TextAlignment[ AlignHorzCenter ]))
  {
    var int32 tw = font.GetTextAdvance( flowString, i + 2, cc );

    // Using the text width, calculate the horizontal text drawing position.
    ofs2.x = ofs2.x - (( area.w - tw ) / 2 );
  }

  // Prepare to draw the text
  var int32 topFadedHeight = (int32)(this.Bounds.h * FadePercentage / 100);
  var int32 bottomFadedHeight = (int32)(this.Bounds.h - ( this.Bounds.h * FadePercentage / 100 ));
  var int32 textY1 = y - rd.y1;
  var color ctf = ctl;
  ctf.alpha = 0;

  //fading top                     
  if ( textY1 < topFadedHeight && topFade )
  {
    var rect topRect         = rect(rd.x1, rd.y1, rd.x2, rd.y1+topFadedHeight);
    var rect bottomRect      = rect(rd.x1, rd.y1+topFadedHeight, rd.x2, rd.y2);

    //draw faded text 
    aCanvas.DrawText( aClip, font, flowString, i + 2, cc, topRect, ofs2, minWidth, 
      ctf, ctf, cbr, cbl, true );

    //draw remaining plain text part
    aCanvas.DrawText( aClip & bottomRect, font, flowString, i + 2, cc, rd, ofs2, minWidth,
      ctl, ctr, cbr, cbl, true );
  }
  
  //fading bottom
  else if ( textY1 + rowHeight > bottomFadedHeight && bottomFade )
  {
    var rect topRect         = rect(rd.x1, rd.y1, rd.x2, rd.y1+bottomFadedHeight);
    var rect bottomRect      = rect(rd.x1, rd.y1+bottomFadedHeight, rd.x2, rd.y2);
    var point offsetAdjustment  = point( ofs2.x, ofs2.y+bottomFadedHeight );

    //draw faded text 
    aCanvas.DrawText( aClip, font, flowString, i + 2, cc, bottomRect, 
      offsetAdjustment, minWidth, ctl, ctr, ctf, ctf, true );

    //draw remaining plain text part
    aCanvas.DrawText( aClip, font, flowString, i + 2, cc, topRect, ofs2, minWidth, 
      ctl, ctr, cbr, cbl, true );
  }

  //no fading in center area, just draw text
  else
    aCanvas.DrawText( aClip, font, flowString, i + 2, cc, rd, ofs2, minWidth,
      ctl, ctr, cbr, cbl, true );

  // ... and continue with the next row.
  i = i + c;
  y = y + rowHeight;
  c = flowString[i];
}               

 

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...