175 votes

android ellipsize multiligne textview

Je dois ellipsiser une textview multi-lignes. Mon composant est suffisamment grand pour afficher au moins 4 lignes avec l'ellipse, mais seules 2 lignes sont affichées. J'ai essayé de modifier le nombre minimum et maximum de lignes du composant mais cela ne change rien.

143voto

Micah Hainline Points 6629

Voici une solution à ce problème. C'est une sous-classe de TextView qui fonctionne réellement pour ellipsizing. Le android-textview-multiligne-ellipse code répertorié dans une précédente réponse que j'ai trouvé pour être buggy dans certaines circonstances, comme étant sous licence GPL, ce qui ne fonctionne pas vraiment pour la plupart d'entre nous. N'hésitez pas à utiliser ce code librement et sans attribution, ou sous la licence Apache si vous préférez. Notez qu'il y a un port d'écoute pour vous informer quand le texte devient ellipsized, que j'ai trouvé très utile à moi-même.

import java.util.ArrayList;
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
    }
}

67voto

hooloovoo Points 87

Dans mon application, j'avais un problème similaire: 2 lignes de chaîne et, éventuellement, ajouter "..." si la chaîne était trop longue. J'ai utilisé ce code dans un fichier xml dans la balise textview:

 android:maxLines="2"
android:ellipsize="end"
android:singleLine="false"
 

18voto

Lysogen Points 237

Essayez ceci, ça marche pour moi, j’ai 4 lignes et il ajoute le «... » à la fin de la dernière et quatrième ligne. Son les mêmes que du moral répondre, mais j’ai singeLine = « false » là-dedans.

17voto

Robert Nekic Points 1186

J'ai rencontré ce problème aussi. Il y a un bug assez vieux à ce sujet qui reste sans réponse: Bug 2254

14voto

Percuss Points 91

J’ai eu ce problème et finalement, me construire une solution courte. Vous avez juste à ellipsize manuellement la ligne que vous voulez, votre attribut maxLine réduira votre texte.

Cet exemple coupe votre texte pour 3 lignes max

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X