четверг, 28 июля 2011 г.

Прикручиваем функцию setMaxHeight к классу ScrollTextView.

Постановка задачи:  Есть текст со скролингом, его размер динамически меняется. Нужно чтобы высота контрола, определялась содержимым, пока текста меньше чем 4 строки, а если его больше, то высота не увеличивалась, а появлялся скролинг.
Проблема:  Метод getLineCount класса TextView возвращает 0.
Версия Android-а: 1.6



 Ниже приведу код примера класса, предназаначенного для отображения текста со скролингом:

public class ScrollTextView extends ScrollView {

  private
 TextView _textView;

  public ScrollTextView(
Context
 context, String text) {
    this(context);
    _textView.setText(text);
  }

  public ScrollTextView(
Context context) {
    super(context);
    _textView = new 
TextView
(context);
    this.addView(_textView);
  }
}


Для того чтобы задать максимальную высоту  ScrollTextView нужно: 1) определится какая эта будет высота, для этого введем констану:
private final int MAX_HEIGHT_LINES = 4;

2) при изменении текста анализировать превышает ли высота TextView нашу константу, и если превышает, то задавать константу в качестве высоты, таким образом:


    if (heightTextLines > MAX_HEIGHT_LINES) {
      ScrollTextView.this.setLayoutParams(new LinearLayout.LayoutParams
(LayoutParams.FILL_PARENT, MAX_HEIGHT_LINES * _textView.getLineHeight()));
    } else {
      ScrollTextView.this.setLayoutParams(new 
LinearLayout.LayoutParams(LayoutParams..FILL_PARENT,
         
LayoutParams.WRAP_CONTENT));
    }



Этот анализ можно вставить сразу в конструктор или создать для него метод.
Ничего сложного как бы нету, но тут неожиданно возникает проблема: метод класса
TextView  getLineCount() возвращает 0, вместо количества строк. И чтобы решить эту проблему я использовал следующий костыль в конструкторе:


LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 1);
    this.setLayoutParams(layoutParams);
    _textView = new TextView(context);
    _textView.setText(" ");



после чего метод getLineCount() заработал нормально. Дальше я привожу полный код:


import com.evos.guice.GuiceFactory;
import com.evos.model.ISettings;
import android.content.Context;
import android.graphics.Typeface;
import android.text.Spanned;
import android.widget.LinearLayout;
import android.widget.ScrollView;


public class ScrollTextView extends ScrollView {

  private final int MAX_HEIGHT_LINES = 4;
  private TextView _textView;

  public ScrollTextView(Context context, String text) {
    this(context);
    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
    this.setLayoutParams(layoutParams);
    _textView.setText(text);
  }

  public ScrollTextView(Context context) {
    super(context);
    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 1);
    this.setLayoutParams(layoutParams);
    _textView = new TextView(context);
    ISettings settings = GuiceFactory.getInstance(ISettings.class);
    _textView.setTextSize(settings.getTextSize());
    if (settings.getTextBold()) _textView.setTypeface(Typeface.DEFAULT_BOLD);
    _textView.setText(" ");
    this.addView(_textView);
  }

  public void update(String text) {
    _textView.setText(text);
    int heightText = _textView.getLineCount() * _textView.getLineHeight();
    if (heightText > MAX_HEIGHT_LINES) {
      ScrollTextView.this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, MAX_HEIGHT_LINES));
    } else {
      ScrollTextView.this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
        LayoutParams.WRAP_CONTENT));
    }
  }

  public void update(Spanned textHtml) {
    _textView.setText(textHtml);
    int heightTextLines = _textView.getLineCount();
    if (heightTextLines > MAX_HEIGHT_LINES) {
      ScrollTextView.this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, MAX_HEIGHT_LINES * _textView.getLineHeight()));
    } else {
      ScrollTextView.this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
        LayoutParams.WRAP_CONTENT));
    }
  }

}



В документации к методу getLineCount написано Return the number of lines of text, or 0 if the internal Layout has not been built. То есть метод возвращает 0 если Layout не был собран. К сожалению мне не удалось понять как же определить когда именно он собирается. Возможно есть метод который его принудительно собирает. В любом случае костыль работает, кому нужно - пользуйтесь :)
  



Комментариев нет:

Отправить комментарий