1

I need to reach the following result, with dynamic titles that are coming from the server:

enter image description here

I tried to reach this result using the answer from the following question:

How to make the first character much larger than other in a TextView

But the result I reached was not good enough for the design team. There are several requirements that are requested by the design:

  1. Big first latterv (B).
  2. the text continues a little bit above the middle of the big letter (the smaller red letters).
  3. The second row of text continue aligned with the base of the big letter ("and star in film").
  4. finally if there is more text it continue under the big letter.

What would be the best way to reach this result in Android?

halfer
  • 19,824
  • 17
  • 99
  • 186
Emil Adz
  • 40,709
  • 36
  • 140
  • 187
  • 1
    It seems to me that you want some HTML design... What's better than a WebView, to display HTML content? –  Jun 19 '16 at 09:36
  • I would really wanted to avoid using a WebView to commit this task, although this was the first idea that came to my head. I prefer to find a natively android way to commit this task. – Emil Adz Jun 19 '16 at 09:42
  • @LonnieZamora a custom TextView? He never mentioned, that text is html-styled already – Evgeniy Mishustin Jun 19 '16 at 09:42
  • @EvgeniyMishustin Keep in mind that `HTML.fromHtml()` has been deprecated in API Level 24. –  Jun 19 '16 at 09:43
  • @LonnieZamora need to only parse text from HTML and draw using inner logic. No html tags needed. – Evgeniy Mishustin Jun 19 '16 at 09:48

2 Answers2

2

The solution would be to have 3 views, one for the first letter, another for the (maximum) two lines, and another for the remainder of the text. When measuring the view, you can determine if you've passed the 2 lines limit you wish to impose, and if so break the text and set the remainder of the text in the 3rd view. You would also need to overcome the internal font padding of the first letter in order to achieve your desired result, hence the BottomAlignedTextView view.

Here is the code:

BottomAlignedTextView.java

public class BottomAlignedTextView extends TextView {

 public BottomAlignedTextView(Context context) {
     super(context);
 }

 @Override
 protected void onDraw(Canvas canvas) {
     float offset = getTextSize() - getLineHeight();
     canvas.translate(0, -offset);
     super.onDraw(canvas);
 }

}

view_reader_title.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.shellanoo.newsbot.ui.views.BottomAlignedTextView
            android:id="@+id/first_letter_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:fontFamily="serif"
            android:background="@null"
            android:gravity="bottom"
            android:includeFontPadding="false"
            android:textSize="92dp"
            tools:text="B"/>

        <TextView
            android:id="@+id/two_lines_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/first_letter_tv"
            android:layout_toEndOf="@+id/first_letter_tv"
            android:layout_toRightOf="@+id/first_letter_tv"
            android:gravity="bottom"
            android:includeFontPadding="false"
            android:lineSpacingMultiplier="0.9"
            android:textColor="@color/black"
            android:textSize="30dp"
            tools:text="eyonce to write and star in a film"/>
    </RelativeLayout>

    <TextView
        android:id="@+id/remainder_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="2dp"
        android:layout_marginStart="2dp"
        android:includeFontPadding="false"
        android:textColor="@color/black"
        android:textSize="30dp"
        tools:text="about Saartjie Baartman"/>
</LinearLayout>

ReaderTitleView.java

public class ReaderTitleView extends FrameLayout {

    @BindView(R.id.first_letter_tv)
    TextView firstLetterTv;

    @BindView(R.id.two_lines_tv)
    TextView twoLinesTv;

    @BindView(R.id.remainder_tv)
    TextView remainderTv;

    @ColorInt
    private int mFirstWordColor;
    private String mText;

    public ReaderTitleView(Context context) {
        this(context, null);
    }

    public ReaderTitleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ReaderTitleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        View view = inflate(getContext(), R.layout.view_reader_title, this);
        ButterKnife.bind(this, view);
        TypedArray a = getContext().getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.ReaderTitleView,
                0, 0);
        mText = a.getString(R.styleable.ReaderTitleView_rtv_text);
        if (mText == null) {
            mText = "";
        }
        mFirstWordColor = a.getColor(R.styleable.ReaderTitleView_rtv_first_word_color, -1);

        updateTextViews();
    }

    private void updateTextViews() {
        if (!TextUtils.isEmpty(mText)) {
            String firstLetter = mText.substring(0, 1);
            firstLetter = firstLetter.toUpperCase();
            String restText = mText.substring(1, mText.length());

            firstLetterTv.setText(firstLetter);
            twoLinesTv.setText(restText);
            colorifyFirstWord();
        } else {
            firstLetterTv.setText("");
            twoLinesTv.setText("");
            remainderTv.setText("");
        }
    }

    private void colorifyFirstWord() {
        if (mFirstWordColor != -1) {
            CharSequence text = twoLinesTv.getText();
            Spannable s;
            if (text instanceof Spannable) {
                s = (Spannable) text;
            } else {
                s = new SpannableString(text);
            }
            String[] split = s.toString().split(" ", 2);
            int start = 0;
            int end = start + split[0].length();
            s.setSpan(new ForegroundColorSpan(mFirstWordColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            twoLinesTv.setText(s, TextView.BufferType.SPANNABLE);
            firstLetterTv.setTextColor(mFirstWordColor);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (twoLinesTv.getLineCount() > 2) {
            String text = twoLinesTv.getText().toString();

            int secondLineEnd = twoLinesTv.getLayout().getLineEnd(1);
            String twoLines = text.substring(0, secondLineEnd);
            String remainder = text.substring(secondLineEnd, text.length());

            twoLinesTv.setText(twoLines);
            remainderTv.setText(remainder);
            colorifyFirstWord();
        }
    }

    public void setText(String text) {
        mText = text;
        updateTextViews();
    }

    public String getText() {
        return mText;
    }
    }
sahar
  • 350
  • 2
  • 15
0

have a look at http://uncodin.github.io/bypass/. https://github.com/Uncodin/bypass. eg:

Bypass markdown = new Bypass(context, new Bypass.Options());

                    CharSequence about0 = markdown.markdownToSpannable(parent.getResources()
                            .getString(R.string.string_0), yourTextView, null);
                    SpannableString about1 = new SpannableString(
                            parent.getResources().getString(R.string.string_1));
                    about1.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
                            0, about1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    SpannableString about2 = new SpannableString(markdown.markdownToSpannable
                            (parent.getResources().getString(R.string.string2),
                                    plaidDescription, null));
                    about2.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
                            0, about2.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    SpannableString about3 = new SpannableString(markdown.markdownToSpannable
                            (parent.getResources().getString(R.string.string_3),
                                    yourTextView, null));
                    about3.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
                            0, about3.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    CharSequence desc = TextUtils.concat(about0, "\n\n", about1, "\n", about2,
                            "\n\n", about3);
                    HtmlUtils.setTextWithNiceLinks(yourTextView, desc);
NIPHIN
  • 1,071
  • 1
  • 8
  • 16