web-dev-qa-db-fra.com

Comment ajuster la hauteur de ligne dans TextView avec plusieurs tailles de caractères?

J'ai un TextView qui contient une chaîne Spannable. La chaîne contient un tas de texte, dont le premier mot est le double de la taille du texte comme le reste de la chaîne.

Le problème est que l’espacement des lignes entre les première et deuxième lignes est beaucoup plus grand que l’espacement entre les lignes suivantes en raison de la taille accrue du premier mot.

http://img.skitch.com/20100615-fwd2aehbsgaby8s2s9psx3wwii.png

La chaîne spannable a été créée à l'aide de l'extrait de code suivant:

    // Price
    CharSequence text = "$30 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
    final Pattern priceRegex = Pattern.compile("^(.[0-9]+)\\s.*");
    final Matcher m = priceRegex.matcher(text!=null ? text : "");
    if( m.matches() ) {
        text = new SpannableString(text);
        ((SpannableString)text).setSpan(new RelativeSizeSpan(2), 0, m.end(1), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

Comment puis-je réparer mon TextView afin que toutes les lignes aient le même espacement?

25
emmby

Vous pouvez essayer l’une de ces propriétés TextView:

Android:lineSpacingMultiplier
Android:lineSpacingExtra

au moins, essayez de faire en sorte que toutes les lignes aient la même hauteur (comme la première).

43
Rangel Reale

Après beaucoup d'essais et d'erreurs, j'ai eu une solution très compliquée à utiliser:

  1. J'ai ajouté des fichiers spannables avec la même taille de texte doublée que le mot souligné dans chaque espace du texte. De cette façon, tout le TextView a le même (grand) interligne. Sachez que vous ne pouvez pas réutiliser un spannable.

  2. Ensuite, j'ai donné à la TextView un négatif lineSpacingExtra afin que l'interligne soit redevenu agréable.

  3. Pour éviter des espaces anormalement larges en raison de la taille de texte accrue, j'ai ajouté un ScaleXSpan à chaque espace, en les redimensionnant à 50% de leur grande taille d'origine.

Cette méthode devrait fonctionner même pour les TextViews contenant des chaînes localisées (où vous ne savez jamais à quelle position le mot mis en évidence apparaît ni la longueur de votre ligne) tant que chaque ligne contient au moins un caractère d'espacement. 

2
miracula

J'ai écrit cette fonction:

CONTRIBUTION

  • LinearLayout ll: 

    la mise en page qui sera votre "TexView" (assurez-vous que son orientation est verticale)

  • Argent ficelle: 

    la chaîne que vous voulez être différent (dans votre cas, un plus gros textize)

  • Texte de chaîne: 

    le texte

  • Contexte mContext 

    le contexte

QUE FAIRE

J'ai commenté les parties que vous devez éditer


private void populateText(LinearLayout ll,
        String money, String text , Context mContext) { 
    String [] textArray = text.split(" ");
    Display display = getWindowManager().getDefaultDisplay();
    ll.removeAllViews();
    int maxWidth = display.getWidth() - 20;

    LinearLayout.LayoutParams params; // to be used over and over
    LinearLayout newLL = new LinearLayout(mContext);
    newLL.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
            LayoutParams.WRAP_CONTENT));
    newLL.setGravity(Gravity.LEFT);
    newLL.setOrientation(LinearLayout.HORIZONTAL);

    int widthSoFar = 0;

    ///FIRST INSERT THE MONEY TEXTVIEW
    LinearLayout LL = new LinearLayout(mContext);
    LL.setOrientation(LinearLayout.HORIZONTAL);
    LL.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM); //THIS IS IMPORTANT TO keep spacing up not down
    LL.setLayoutParams(new ListView.LayoutParams(
            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    TextView TV = new TextView(mContext);
    TV.setText(money);
    //TV.setTextSize(size);  <<<< SET TEXT SIZE
    TV.measure(0, 0);
    params = new LinearLayout.LayoutParams(TV.getMeasuredWidth(),
            LayoutParams.WRAP_CONTENT);
    //params.setMargins(5, 0, 5, 0);  // YOU CAN USE THIS
    LL.addView(TV, params);
    LL.measure(0, 0);
    widthSoFar += TV.getMeasuredWidth();// YOU MAY NEED TO ADD THE MARGINS
    newLL.addView(LL, params);

    for (int i = 0 ; i < textArray.length ; i++ ){
        LL = new LinearLayout(mContext);
        LL.setOrientation(LinearLayout.HORIZONTAL);
        LL.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM);
        LL.setLayoutParams(new ListView.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        TV = new TextView(mContext);
        TV.setText(textArray[i]);
        //TV.setTextSize(size);  <<<< SET TEXT SIZE
        TV.measure(0, 0);
        params = new LinearLayout.LayoutParams(TV.getMeasuredWidth(),
                LayoutParams.WRAP_CONTENT);
        //params.setMargins(5, 0, 5, 0);  // YOU CAN USE THIS
        LL.addView(TV, params);
        LL.measure(0, 0);
        widthSoFar += TV.getMeasuredWidth();// YOU MAY NEED TO ADD THE MARGINS
        if (widthSoFar >= maxWidth) {
            ll.addView(newLL);

            newLL = new LinearLayout(mContext);
            newLL.setLayoutParams(new LayoutParams(
                    LayoutParams.FILL_PARENT,
                    LayoutParams.WRAP_CONTENT));
            newLL.setOrientation(LinearLayout.HORIZONTAL);
            newLL.setGravity(Gravity.LEFT);
            params = new LinearLayout.LayoutParams(LL
                    .getMeasuredWidth(), LL.getMeasuredHeight());
            newLL.addView(LL, params);
            widthSoFar = LL.getMeasuredWidth();
        } else {
            newLL.addView(LL);
        }
    }
    ll.addView(newLL);
}

REMARQUE

Je ne l'ai pas testé ... je l'ai utilisé pour des choses plus complexes et cela fonctionnait ... Vous devrez peut-être un peu Tweak.

1
Sherif elKhatib

Je pense que vous ne pouvez pas: (. Android calculer les espaces entre les lignes en fonction de la taille de la police, de sorte que "30 $" augmente l’écart entre la ligne 1 et la ligne 2 et je ne sais pas. s'il est possible de contrôler cette taille d'espace.

Pour résoudre ce problème, vous pouvez facilement étendre LinearLayuot et mettre l'orientation verticale. Que mettre 2 textviews avec fillparent pour la largeur ....

et que la fonction de mise en œuvre, disons setNoGapText (String s); , et dans cette fonction, vous pouvez mesurer le texte qui peut être ajusté dans la vue de texte sur le dessus (cela peut être fait avec textutils), et que le le reste du texte sera ajusté sur textview2 ...

entre cette vue de texte, vous pouvez jouer avec les propriétés de remplissage et de marges afin que les espaces entre les lignes ressemblent à ceux que vous imaginez. 

0
Lukap