0

I created custom "TextView" that text lines are drawn in the overridden OnDraw method by canvas.DrawText method. Everything was fine until I added ScrollView:

<LinearLayout
    android:background="#ffffff"
    android:layout_height="200dp"
    android:layout_width="match_parent"
    android:orientation="horizontal">
  <ScrollView
    android:id="@+id/scrollV"
    android:layout_height="match_parent"
        android:layout_width="match_parent">
    <myapp.TextViewJustifiable
        android:id="@+id/textViewJustifiableAlertMessage"
        android:layout_gravity="top"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:lineSpacingExtra="8dp"
        android:textSize="16sp"
        android:textColor="#333333" />
  </ScrollView>
</LinearLayout>

In general, ScrollView does not show nth text line of the custom TextView! For example, if TextView has 20 lines of text, only 19 lines are scrolled and line of 20 is not shown at all! When I delete OnDraw method everything is OK.

Where do you think the problem is?

  • Have you overrided the [onMeasure](https://stackoverflow.com/questions/12266899/onmeasure-custom-view-explanation) method? – Robbit Jun 06 '18 at 03:23
  • @Joe Lv - MSFT No I have not. – Mohammad Afrashteh Jun 06 '18 at 03:48
  • If you use `wrap_content` in your custom view, you need override it. – Robbit Jun 06 '18 at 05:20
  • It didn't work for me. I used SetHeight method in the end of overridden OnDraw method. – Mohammad Afrashteh Jun 06 '18 at 05:55
  • Could you please show your `TextViewJustifiable`? If you use `wrap_content`, and not override `onMeasure` method, the system don't know the specific size. And why do you use `SetHeight`? You need use `setMeasuredDimension` to define the width and height. – Robbit Jun 06 '18 at 05:57
  • I use wrap_content for height of TextViewJustifiable. Using overridden onMeasure method causes to disappear of TextViewJustifiable contents! I use SetHeight in OnDraw method to set actual height of control after text lines drawn to screen. It works fine. – Mohammad Afrashteh Jun 06 '18 at 06:20
  • Good luck, could you please post an answer for your question? So it will help others. – Robbit Jun 06 '18 at 06:29

1 Answers1

0

I used SetHeight method in the end of the overridden OnDraw method to solve the issue:

> protected override void OnDraw(Canvas canvas)
>         {
>             float floatCharSpaceSize;
>             float floatWordWidth;
>             float floatEmptySpace;
>             float floatJustifedSpaceSize;
>             float floatLineWidth;
>             float floatTextAreaWidth;
>             float floatWordPositionX;
>             float floatWordPositionY;
>             int intLineEnd;
>             int intLineStart;
>             int intSpaceCount;
>             int intTextHeight;
>             int intRemaindedSpaceSize;
>             Layout layoutTextView;
>             Paint.FontMetrics fontMetrics_Paint;
>             string stringLine;
>             string stringText;
>             string[] stringArrWord;
>             TextPaint textPaint = Paint;
> 
>             textPaint.Color = new Color(CurrentTextColor);
>             textPaint.DrawableState = GetDrawableState();
>             floatTextAreaWidth = MeasuredWidth - (PaddingLeft + PaddingRight);
>             floatCharSpaceSize = textPaint.MeasureText(" ");
>             stringText = Text;
>             floatWordPositionY = TextSize + PaddingTop;
>             layoutTextView = Layout;
> 
>             if (layoutTextView == null)
>             {
>                 return;
>             }
> 
>             fontMetrics_Paint = textPaint.GetFontMetrics();
>             intTextHeight = (int)(Math.Ceiling(fontMetrics_Paint.Bottom - fontMetrics_Paint.Top) *
> LineSpacingMultiplier + layoutTextView.SpacingAdd);
> 
>             for (int intIndexA = 0; intIndexA < layoutTextView.LineCount; intIndexA++)
>             {
>                 intLineStart = layoutTextView.GetLineStart(intIndexA);
>                 intLineEnd = layoutTextView.GetLineEnd(intIndexA);
>                 floatLineWidth = StaticLayout.GetDesiredWidth(Text, intLineStart, intLineEnd, textPaint);
>                 stringLine = Text.Substring(intLineStart, intLineEnd - intLineStart);
> 
>                 if (stringLine[stringLine.Length - 1] == ' ')
>                 {
>                     stringLine = stringLine.Substring(0, stringLine.Length - 1);
>                     floatLineWidth -= floatCharSpaceSize;
>                 }
> 
>                 if (BoolJustify == true && intIndexA < layoutTextView.LineCount - 1)
>                 {
>                     floatEmptySpace = floatTextAreaWidth - floatLineWidth;
>                     intSpaceCount = stringLine.Split(' ').Length - 1;
>                     floatJustifedSpaceSize = (int)(floatEmptySpace / intSpaceCount) + floatCharSpaceSize;
>                     intRemaindedSpaceSize = (int)(((floatEmptySpace / intSpaceCount) - (int)(floatEmptySpace / intSpaceCount)) *
> intSpaceCount);
>                     stringArrWord = stringLine.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
> 
>                     if (IntLangDirection == (int)ApplicationLSchool.LangDirection.LTR)
>                     {
>                         floatWordPositionX = 0;
> 
>                         for (int intIndexB = 0; intIndexB < stringArrWord.Length; intIndexB++)
>                         {
>                             floatWordWidth = StaticLayout.GetDesiredWidth(stringArrWord[intIndexB], textPaint);
> 
>                             canvas.DrawText(stringArrWord[intIndexB], floatWordPositionX, floatWordPositionY, textPaint);
> 
>                             if (intRemaindedSpaceSize > 0)
>                             {
>                                 floatWordPositionX += floatWordWidth + floatJustifedSpaceSize + 1;
> 
>                                 intRemaindedSpaceSize--;
>                             }
>                             else
>                             {
>                                 floatWordPositionX += floatWordWidth + floatJustifedSpaceSize;
>                             }
>                         }
>                     }
>                     else if (IntLangDirection == (int)ApplicationLSchool.LangDirection.RTL)
>                     {
>                         floatWordPositionX = floatTextAreaWidth;
> 
>                         for (int intIndexB = 0; intIndexB < stringArrWord.Length; intIndexB++)
>                         {
>                             floatWordWidth = StaticLayout.GetDesiredWidth(stringArrWord[intIndexB], textPaint);
> 
>                             canvas.DrawText(stringArrWord[intIndexB], floatWordPositionX - floatWordWidth, floatWordPositionY, textPaint);
> 
>                             if (intRemaindedSpaceSize > 0)
>                             {
>                                 floatWordPositionX -= floatWordWidth + floatJustifedSpaceSize + 1;
> 
>                                 intRemaindedSpaceSize--;
>                             }
>                             else
>                             {
>                                 floatWordPositionX -= floatWordWidth + floatJustifedSpaceSize;
>                             }
>                         }
>                     }
>                 }
>                 else
>                 {
>                     if (IntLangDirection == (int)ApplicationLSchool.LangDirection.LTR)
>                     {
>                         canvas.DrawText(stringLine, 0, floatWordPositionY, textPaint);
>                     }
>                     else if (IntLangDirection == (int)ApplicationLSchool.LangDirection.RTL)
>                     {
>                         canvas.DrawText(stringLine, floatTextAreaWidth - floatLineWidth, floatWordPositionY, textPaint);
>                     }
>                 }
> 
>                 floatWordPositionY += intTextHeight;
>             }
> 
>             **SetHeight((int)(floatWordPositionY - TextSize - layoutTextView.SpacingAdd) + PaddingBottom);**
>         }