Как создать заголовок в стиле абзаца в Android?

Мне нужно достичь следующего результата с динамическими заголовками, поступающими с сервера:

введите здесь описание изображения

Я попытался достичь этого результата, используя ответ на следующий вопрос:

Как сделать первый символ намного больше, чем другие в TextView

Но результат, которого я достиг, не был достаточно хорош для команды разработчиков. К проекту предъявляется несколько требований:

  1. Большой первый последнийv (B).
  2. текст продолжается немного выше середины большой буквы (меньшие красные буквы).
  3. Второй ряд текста по-прежнему выравнивается по основанию большой буквы («и сниматься в кино»).
  4. наконец, если есть еще текст, он продолжается под большой буквой.

Каков наилучший способ достичь этого результата в Android?


person Emil Adz    schedule 19.06.2016    source источник
comment
Мне кажется, что вам нужен HTML-дизайн... Что может быть лучше, чем WebView, для отображения HTML-контента?   -  person    schedule 19.06.2016
comment
Я бы очень хотел избежать использования WebView для фиксации этой задачи, хотя это была первая идея, которая пришла мне в голову. Я предпочитаю найти собственный способ Android для выполнения этой задачи.   -  person Emil Adz    schedule 19.06.2016
comment
@LonnieZamora пользовательский TextView? Он ни разу не упомянул, что текст уже стилизован под html.   -  person Evgeniy Mishustin    schedule 19.06.2016
comment
@EvgeniyMishustin Имейте в виду, что HTML.fromHtml() устарело на уровне API 24.   -  person    schedule 19.06.2016
comment
@LonnieZamora нужно только анализировать текст из HTML и рисовать с использованием внутренней логики. HTML-теги не нужны.   -  person Evgeniy Mishustin    schedule 19.06.2016


Ответы (3)


Решение состоит в том, чтобы иметь 3 вида: один для первой буквы, другой для (максимум) двух строк и еще один для остального текста. При измерении представления вы можете определить, преодолели ли вы ограничение в 2 строки, которое вы хотите наложить, и если это так, разорвите текст и установите оставшуюся часть текста в 3-м представлении. Вам также нужно будет преодолеть внутреннее заполнение шрифта первой буквы, чтобы достичь желаемого результата, следовательно, представление 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;
    }
    }
person sahar    schedule 29.06.2016

Я предлагаю вам использовать библиотеку Letterine.

Добавьте следующую строку в свой gradle:

compile 'com.github.rpradal.lettrine:lettrine:1.0.0'

Вот пример того, как вы можете добавить LettrineTextView в свой проект:

  <com.github.rpradal.lettrine.LettrineTextView
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              app:lettrine_textColor="@android:color/holo_red_dark"
              app:lettrine_text="Lorem ipsum"
              app:lettrine_lettrineSize="3"
              app:lettrine_textSize="14sp" />

Затем вы можете найти вид, как я делаю ниже.

LettrineTextView letterineTextView = (LettrineTextView) findViewById(R.id.letterineTextView);
letterineTextView.setBodyText(getString(R.string.body));

Наслаждайтесь, удачного кодирования.

person Burak Cakir    schedule 19.06.2016

взгляните на http://uncodin.github.io/bypass/. https://github.com/Uncodin/bypass. например:

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);
person NIPHIN    schedule 19.06.2016