今天偶然发现android:maxLines和android:ellipsize这两个属性同时使用在某些设备上时不能正常工作,网上搜索了大半天最后终于还是在Stack-Overflow这个神奇的网上找到了一个满意的答案,原文地址如下:
http://stackoverflow.com/questions/2160619/android-ellipsize-multiline-textview
用法是将需要用到的TextView换成下面的EllipsizingTextView,然后在Java代码中使用setMaxLines(int maxLines)方法,直接传入一个所需要的最大行数即可,不需要再指定android:ellipsize参数或着使用setEllipsize这个方法(该方法在此类中被重写成了一个空方法,即不推荐使用的)
用这个方法基本上能在所有的设备上正常工作
需要注意的是,某情况使用如下的这三个属性可能也能实现
android:maxLines="4"
android:ellipsize="marquee"
android:singleLine="false"
但是这种方法只能在部分设备上正常显示,并不能保证所有设备都正常(本人亲测过),所以最好还是用下面的EllipsizingTextView来实现
另外这个类还提供了一个监听器EllipsizeListener,这个监听器原文作者说的是开始在Ellipsize(这个单词不知道怎么读,网上也查不到,估计是Google自创的)的时候调用的,大概意思应该就是说在开始省略(也就是开始 ”...“ )的时候调用,这个暂时还没有试过,等以后需要的时候再去试一试
EllipsizingTextView.java
- import java.util.List;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.text.Layout;
- import android.text.Layout.Alignment;
- import android.text.StaticLayout;
- import android.text.TextUtils.TruncateAt;
- import android.util.AttributeSet;
- import android.widget.TextView;
- public class EllipsizingTextView extends TextView {
- private static final String ELLIPSIS = "...";
- public interface EllipsizeListener {
- void ellipsizeStateChanged(boolean ellipsized);
- }
- private final List<EllipsizeListener> ellipsizeListeners = new ArrayList<EllipsizeListener>();
- private boolean isEllipsized;
- private boolean isStale;
- private boolean programmaticChange;
- private String fullText;
- private int maxLines = -1;
- private float lineSpacingMultiplier = 1.0f;
- private float lineAdditionalVerticalPadding = 0.0f;
- public EllipsizingTextView(Context context) {
- super(context);
- }
- public EllipsizingTextView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public EllipsizingTextView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
- public void addEllipsizeListener(EllipsizeListener listener) {
- if (listener == null) {
- throw new NullPointerException();
- }
- ellipsizeListeners.add(listener);
- }
- public void removeEllipsizeListener(EllipsizeListener listener) {
- ellipsizeListeners.remove(listener);
- }
- public boolean isEllipsized() {
- return isEllipsized;
- }
- @Override
- public void setMaxLines(int maxLines) {
- super.setMaxLines(maxLines);
- this.maxLines = maxLines;
- isStale = true;
- }
- public int getMaxLines() {
- return maxLines;
- }
- @Override
- public void setLineSpacing(float add, float mult) {
- this.lineAdditionalVerticalPadding = add;
- this.lineSpacingMultiplier = mult;
- super.setLineSpacing(add, mult);
- }
- @Override
- protected void onTextChanged(CharSequence text, int start, int before, int after) {
- super.onTextChanged(text, start, before, after);
- if (!programmaticChange) {
- fullText = text.toString();
- isStale = true;
- }
- }
- @Override
- protected void onDraw(Canvas canvas) {
- if (isStale) {
- super.setEllipsize(null);
- resetText();
- }
- super.onDraw(canvas);
- }
- private void resetText() {
- int maxLines = getMaxLines();
- String workingText = fullText;
- boolean ellipsized = false;
- if (maxLines != -1) {
- Layout layout = createWorkingLayout(workingText);
- if (layout.getLineCount() > maxLines) {
- workingText = fullText.substring(0, layout.getLineEnd(maxLines - 1)).trim();
- while (createWorkingLayout(workingText + ELLIPSIS).getLineCount() > maxLines) {
- int lastSpace = workingText.lastIndexOf(' ');
- if (lastSpace == -1) {
- break;
- }
- workingText = workingText.substring(0, lastSpace);
- }
- workingText = workingText + ELLIPSIS;
- ellipsized = true;
- }
- }
- if (!workingText.equals(getText())) {
- programmaticChange = true;
- try {
- setText(workingText);
- } finally {
- programmaticChange = false;
- }
- }
- isStale = false;
- if (ellipsized != isEllipsized) {
- isEllipsized = ellipsized;
- for (EllipsizeListener listener : ellipsizeListeners) {
- listener.ellipsizeStateChanged(ellipsized);
- }
- }
- }
- private Layout createWorkingLayout(String workingText) {
- return new StaticLayout(workingText, getPaint(), getWidth() - getPaddingLeft() - getPaddingRight(),
- Alignment.ALIGN_NORMAL, lineSpacingMultiplier, lineAdditionalVerticalPadding, false);
- }
- @Override
- public void setEllipsize(TruncateAt where) {
- // Ellipsize settings are not respected
- }
- }