Android: TextView: supprimer l'espacement et le rembourrage en haut et en bas

208

Quand j'ai un TextViewavec un \ndans le texte, à droite j'ai deux singleLine TextViews, l'un en dessous de l'autre sans aucun espacement entre les deux. J'ai défini ce qui suit pour les trois TextViews.

android:lineSpacingMultiplier="1" 
android:lineSpacingExtra="0pt" 
android:paddingTop="0pt" 
android:paddingBottom="0pt"

La première ligne de la gauche TextViews'aligne parfaitement avec le haut à droite TextView.

La deuxième ligne de gauche TextViewest un peu plus haute que la deuxième ligne en bas à droite TextView.

Il semble qu'il y ait une sorte de rembourrage caché en haut et en bas du TextViews. Comment puis-je supprimer cela?

Bryan Field
la source
essayez de régler la gravité de cette vue de texte sur center_vertical
Dawid Hyży
Salut, George Bailey, avez-vous une solution après si longtemps? Je rencontre aussi ce problème maintenant. Pouvez-vous me donner votre solution? Merci.
mmm2006
1
@ mmm2006, Cela fait si longtemps que je ne sais pas ce que j'ai fini par faire. Essayez les solutions dans les réponses. Si cela ne fonctionne pas, posez une nouvelle question.
Bryan Field
Cela n'a pas fonctionné pour moi
Marty Miller
l'une des réponses ci-dessous n'a pas fonctionné pour moi, pouvez-vous aider
Richa

Réponses:

521
setIncludeFontPadding (boolean includepad)

ou dans XMLce serait:

android:includeFontPadding="false"

Définissez si le TextViewrembourrage supérieur et inférieur supplémentaire comprend pour faire de la place aux accents qui dépassent la montée et la descente normales. La valeur par défaut est vraie.

user634545
la source
3
Mais il semble toujours avoir un 1dprembourrage haut / bas, je me trompe? (J'utilise Developer options -> Show layout bounds)
Autobots
94
includeFontPadding="false"ne supprime pas une partie de l'espace, mais pas tout. très étrange.
theblang
7
Cela peut être une épée à double tranchant. includeFontPaddingest idéal pour supprimer tout remplissage supplémentaire de la police elle-même, mais cela peut provoquer des problèmes dans les langues qui ont des ascendants et des descendants. Je m'assurerais que si vous faites cela, vous testez des langues comme l'espagnol et le thaï si vous les supportez.
Elliott
3
Après avoir défini le runtime, il ne prend pas le rembourrage supérieur mais le rembourrage inférieur toujours là, même le rembourrage gauche et droit? toute suggestion?
CoDe
5
Ça n'a pas marché pour moi. Je ne comprends pas ce qui me manque. J'ai encore de l'espace indésirable au bas de mon TextView
Marty Miller
41

Je ressens ta douleur. J'ai essayé toutes les réponses ci-dessus, y compris le setIncludeFontPaddingfaux, ce qui n'a rien fait pour moi.

Ma solution? layout_marginBottom="-3dp"sur le TextViewvous donne une solution pour le fond, BAM!

Bien que -3dp sur layout_marginTopéchoue .... ugh.

Hunterp
la source
6
Cela peut entraîner la coupure du bas du texte
Jason Robinson
2
Vraiment mauvaise idée d'utiliser une marge négative. Mieux vaut envisager une vue personnalisée et dessiner le texte exactement comme vous le souhaitez.
Flynn81
Si un patch comme celui-ci, vous devez également calculer le rapport de la taille de la police.
phnghue
37

J'ai beaucoup cherché la bonne réponse, mais je n'ai trouvé aucune réponse qui pourrait exactement supprimer tout le rembourrage du TextView, mais finalement après avoir parcouru le document officiel, j'ai trouvé un moyen de contourner les textes sur une seule ligne.

android:includeFontPadding="false"
android:lineSpacingExtra="0dp"

L'ajout de ces deux lignes à TextViewxml fera le travail.
Le premier attribut supprime le remplissage réservé aux accents et le deuxième attribut supprime l'espacement réservé pour maintenir un espace approprié entre deux lignes de texte.

Assurez-vous de ne pas ajouter lineSpacingExtra="0dp"de TextView multiligne car cela pourrait rendre l'apparence maladroite

Mohammed Atif
la source
11
l'ajout de ces deux lignes ne fonctionne pas pour moi et il n'y a pas non plus de changement dans le rembourrage
sunil kushwah
@sunilkushwah, cela fonctionnera certainement si vous le faites correctement. Serait heureux de vous aider si vous pouvez fournir plus de détails sur votre problème.
Mohammed Atif
@sunilkushwah Vous pouvez probablement le pousser sur github et partager le lien
Mohammed Atif
@sunilkushwah je vois que vous utilisez la police Brandon (police personnalisée). Pouvez-vous essayer une fois en supprimant l' fontPathattribut?
Mohammed Atif
j'ai essayé mais cela ne fonctionne pas, Remarque: je ne veux pas de rembourrage par défaut dans TextView
sunil kushwah
14

Si vous utilisez AppCompatTextView(ou à API 28partir de maintenant), vous pouvez utiliser la combinaison de ces 2 attributs pour supprimer l'espacement sur la première ligne:

XML

android:firstBaselineToTopHeight="0dp"
android:includeFontPadding="false"

Kotlin

text.firstBaselineToTopHeight = 0
text.includeFontPadding = false
Mario Lenci
la source
11

Cela m'a énervé aussi, et la réponse que j'ai trouvée était qu'il y a en fait de l'espace supplémentaire dans la police elle-même, pas dans TextView. C'est assez irritant, venant d'un arrière-plan de publication de documents, le peu de contrôle que vous avez avec Android sur les éléments typographiques. Je recommanderais d'utiliser une police de caractères personnalisée (telle que Bitstream Vera Sans, qui est autorisée pour la redistribution) qui peut ne pas avoir ce problème. Je ne sais pas exactement si oui ou non, cependant.

Kevin Coppock
la source
avez-vous des polices gratuites à me montrer? Je n'ai pas besoin de marge sur le dessus sans affecter de marges négatives! Je vous remercie!
saut
11

Vous pouvez essayer d'utiliser cet attribut (ConstraintLayout):layout_constraintBaseline_toBaselineOf

Comme ça:

application: layout_constraintBaseline_toBaselineOf = "@ + id / textView"

entrez la description de l'image ici

entrez la description de l'image ici

windplume
la source
10

Je supprime l'espacement dans ma vue personnalisée - NoPaddingTextView.

https://github.com/SenhLinsh/NoPaddingTextView

entrez la description de l'image ici

package com.linsh.nopaddingtextview;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.TextView;

/**
 * Created by Senh Linsh on 17/3/27.
 */

public class NoPaddingTextView extends TextView {

    private int mAdditionalPadding;

    public NoPaddingTextView(Context context) {
        super(context);
        init();
    }


    public NoPaddingTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        setIncludeFontPadding(false);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int yOff = -mAdditionalPadding / 6;
        canvas.translate(0, yOff);
        super.onDraw(canvas);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        getAdditionalPadding();

        int mode = MeasureSpec.getMode(heightMeasureSpec);
        if (mode != MeasureSpec.EXACTLY) {
            int measureHeight = measureHeight(getText().toString(), widthMeasureSpec);

            int height = measureHeight - mAdditionalPadding;
            height += getPaddingTop() + getPaddingBottom();
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private int measureHeight(String text, int widthMeasureSpec) {
        float textSize = getTextSize();

        TextView textView = new TextView(getContext());
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        textView.setText(text);
        textView.measure(widthMeasureSpec, 0);
        return textView.getMeasuredHeight();
    }

    private int getAdditionalPadding() {
        float textSize = getTextSize();

        TextView textView = new TextView(getContext());
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        textView.setLines(1);
        textView.measure(0, 0);
        int measuredHeight = textView.getMeasuredHeight();
        if (measuredHeight - textSize > 0) {
            mAdditionalPadding = (int) (measuredHeight - textSize);
            Log.v("NoPaddingTextView", "onMeasure: height=" + measuredHeight + " textSize=" + textSize + " mAdditionalPadding=" + mAdditionalPadding);
        }
        return mAdditionalPadding;
    }
}
Linsh
la source
Est-ce une question ou une réponse?
Tushar
@Tushar C'est une réponse.
Linsh
D'accord. Pouvez-vous s'il vous plaît ajouter quelques explications avec le code ici.
Tushar
@Tushar Bien sûr, mais c'est un peu plus.
Linsh
3
Bien que ce code puisse résoudre la question, y compris une explication de comment et pourquoi cela résout le problème aiderait vraiment à améliorer la qualité de votre message (et à obtenir des votes positifs). N'oubliez pas que vous répondrez à la question des lecteurs à l'avenir, pas seulement à la personne qui pose la question maintenant! Veuillez modifier votre réponse pour ajouter des explications et donner une indication des limitations et hypothèses applicables.
Makyen
3
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/baselineImage"
        android:includeFontPadding="false" />

    <ImageView
        android:id="@+id/baselineImage"
        android:layout_width="1dp"
        android:layout_height="1dp"
        android:baselineAlignBottom="true"
        android:layout_alignParentBottom="true" />

    <!-- This view will be exactly 10dp below the baseline of textView -->
    <View
        android:id="@+id/view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_below="@+id/baselineImage" />

</RelativeLayout>

Avec une ImageView supplémentaire, nous pouvons définir TextView pour qu'il soit aligné sur la ligne de base avec ImageView et définir la valeur android:baselineAlignBottomde ImageView sur true, ce qui rendra la ligne de base d'ImageView au fond. D'autres vues peuvent s'aligner en utilisant le bas de l'ImageView qui lui-même est identique à la ligne de base de TextView.

Cela ne fixe cependant que le bas du rembourrage et non le haut.

Viven
la source
parfait pour ma situation, bien mieux que de supprimer le remplissage de police. +1
Bawa
3

Je pense que ce problème peut être résolu de cette façon:

 <TextView
        android:id="@+id/leftText"
        android:includeFontPadding="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30dp"
        android:text="Hello World!\nhello world" />

 <TextView
        android:id="@+id/rightUpperText"
        android:includeFontPadding="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/leftText"
        android:layout_alignTop="@+id/leftText"
        android:textSize="30dp"
        android:text="Hello World!" />

 <TextView
        android:id="@+id/rightLowerText"
        android:includeFontPadding="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/leftText"
        android:layout_below="@+id/rightUpperText"
        android:textSize="30dp"
        android:text="hello world" />

Voilà les résultats:

ScreenShot-1

ScreenShot-3

Bien que la ligne de caractères spéciaux dans rightLowerText semble un peu plus élevée que la deuxième ligne de leftText, leurs lignes de base sont toujours alignées.

Wei Wei
la source
includeFontPadding = "false" était exactement ce dont j'avais besoin! Merci.
hman
3

Étant donné que mon exigence est de remplacer le textView existant findViewById(getResources().getIdentifier("xxx", "id", "android"));, je ne peux donc pas simplement essayer une onDraw()autre réponse.

Mais je viens de comprendre les étapes correctes pour résoudre mon problème, voici le résultat final de Layout Inspector:

entrez la description de l'image ici

Puisque ce que je voulais, c'est simplement supprimer les espaces supérieurs, donc je n'ai pas à choisir une autre police pour supprimer les espaces inférieurs.

Voici le code critique pour le corriger:

Typeface mfont = Typeface.createFromAsset(getResources().getAssets(), "fonts/myCustomFont.otf");
myTextView.setTypeface(mfont);

myTextView.setPadding(0, 0, 0, 0);

myTextView.setIncludeFontPadding(false);

La première clé est la police personnalisée "fonts / myCustomFont.otf" qui a l'espace en bas mais pas en haut, vous pouvez facilement le comprendre en ouvrant le fichier otf et en cliquant sur n'importe quelle police dans Android Studio:

entrez la description de l'image ici

Comme vous pouvez le voir, le curseur en bas a un espacement supplémentaire mais pas en haut, donc cela a résolu mon problème.

La deuxième clé est que vous ne pouvez pas simplement ignorer le code , sinon cela pourrait ne pas fonctionner. C'est la raison pour laquelle vous pouvez trouver certaines personnes commenter qu'une réponse fonctionne et d'autres personnes commentent que cela ne fonctionne pas.

Illustrons ce qui se passera si j'en supprime un.

Sans setTypeface(mfont);:

entrez la description de l'image ici

Sans setPadding(0, 0, 0, 0);:

entrez la description de l'image ici

Sans setIncludeFontPadding(false);:

entrez la description de l'image ici

Sans 3 d'entre eux (c'est-à-dire l'original):

entrez la description de l'image ici

Fruit
la source
3

La seule chose qui a fonctionné est

android:lineSpacingExtra="-8dp"
Antonis Radz
la source
3

XML mis à jour

android:fontFamily="monospace"
android:includeFontPadding="false"
SJJ
la source
Salut, bienvenue dans Stack Overflow! Lorsque vous répondez à une question, vous devez inclure une sorte d'explication, comme ce que l'auteur a fait de mal et ce que vous avez fait pour y remédier. Je vous le dis car votre réponse a été signalée comme de mauvaise qualité et est en cours de révision. Vous pouvez modifier votre réponse en cliquant sur le bouton "Modifier".
Federico Grandi
Changer réellement Android: fontFamily n'est pas nécessaire si vous avez déjà la bonne police. Fondamentalement Android: includeFontPadding est la seule chose nécessaire et il a été mentionné dans les réponses précédentes du fil.
Darek Deoniziak
@DarekDeoniziak Certaines polices ont des espaces
SJJ
2

Une méthode simple a fonctionné:

setSingleLine();
setIncludeFontPadding(false);

Si cela n'a pas fonctionné, essayez d'ajouter ceci au-dessus de ce code:

setLineSpacing(0f,0f);
// and set padding and margin to 0

Si vous avez besoin de plusieurs lignes, vous devrez peut-être calculer exactement la hauteur du rembourrage en haut et en bas via TextView ligne unique temporaire (avant et après la suppression du rembourrage), puis appliquez le résultat de la diminution de la hauteur avec un rembourrage négatif ou une disposition fantôme avec la traduction Y. Lol

phnghue
la source
0

Vous voudrez peut-être essayer d'aligner le bas de la vue de texte gauche avec le bas de la 2e vue de texte droite.

Jems
la source
Mais alors la ligne supérieure ne s'alignerait pas. Et en fait, je ne me soucie pas qu'ils s'alignent autant que je voudrais vraiment supprimer l'espacement.
Bryan Field
0

À ma connaissance, cela est inhérent à la plupart des widgets et la quantité de "rembourrage" diffère selon les fabricants de téléphones. Ce remplissage est vraiment un espace blanc entre la bordure de l'image et l'image dans le fichier d'image de 9 patchs.

Par exemple sur mon Droid X, les widgets de spinner obtiennent un espace blanc supplémentaire par rapport aux boutons, ce qui le rend gênant lorsque vous avez un spinner en ligne avec un bouton, mais sur le téléphone de ma femme, la même application n'a pas le même problème et a fière allure!

La seule suggestion que j'aurais est de créer vos propres 9 fichiers de patch et de les utiliser dans votre application.

Ahhh les douleurs qui sont Android.

Modifié: clarifier le rembourrage par rapport à l'espace blanc.

user432209
la source
0

Cette astuce a fonctionné pour moi (pour min-sdk> = 18 ).

J'ai utilisé android:includeFontPadding="false"et une marge négative comme android:layout_marginTop="-11dp"et mis mon à l' TextViewintérieur d'un FrameLayout( ou tout ViewGroup ... )

entrez la description de l'image ici

et enfin des exemples de codes:

<LinearLayout
    android:layout_width="60dp"
    android:layout_height="wrap_content"
    >

    <TextView
        style="@style/MyTextViews.Bold"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/yellow"
        android:textSize="48sp"
        android:layout_marginTop="-11dp"
        android:includeFontPadding="false"
        tools:text="1"/>
</LinearLayout>
Richi
la source
1
Cette astuce peut ne pas fonctionner pour différentes polices, tailles ou mises en page.
Adil Soomro
-1

Regarde ça:

Aligner ImageView avec EditText horizontalement

Il semble que l'image d'arrière-plan de EditText comporte des pixels transparents qui ajoutent également un remplissage.

Une solution consiste à remplacer l'arrière-plan par défaut de EditText par autre chose (ou rien, mais aucun arrière-plan pour un EditText n'est probablement pas acceptable). Cela peut être fait en définissant l'attribut XML android: background.

android:background="@drawable/myEditBackground"
Ixx
la source
-2

Utilisez simplement

android:padding="0dp"
Juan Bernal
la source
-5

Utilisez-le dans votre xml ImageView

android: adjustViewBounds = "true"

Anshul Rawat
la source
Veuillez ajouter quelques explications à ce sujet
Nico Haase
je pensais que cela devait être compris. Je ne peux être utilisé qu'en xml.
Anshul Rawat