J'utilise un TextInputLayout pour afficher un indice, mais je ne parviens pas à le centrer verticalement. Je reçois toujours ceci:
Et je voudrais centrer l'indicateur verticalement lorsqu'il n'y a pas de texte dans EditText / TextInputEditText . J'ai essayé les idées de base (gravité, layout_gravity, etc.). Jusqu'ici, la seule façon de le faire serait d'ajouter un rembourrage "magique", mais j'aimerais le faire de manière plus propre. Je pensais mesurer la hauteur de l'étiquette de soupçon supérieure et l'ajouter comme marge inférieure lorsqu'elle n'est pas visible, et supprimer la même marge lorsqu'elle est visible, mais je ne comprends pas très bien le TextInputLayout code source . Est-ce que quelqu'un sait comment le faire?
Modifier:
J'ai essayé cette réponse suggérée:
<Android.support.design.widget.TextInputLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginTop="20dp"
Android:background="@color/grey_strong">
<Android.support.design.widget.TextInputEditText
Android:layout_width="match_parent"
Android:layout_height="90dp"
Android:background="@color/red_light"
Android:gravity="center_vertical"
Android:hint="Test"/>
</Android.support.design.widget.TextInputLayout>
Et je reçois ceci:
Le "gros" indice n'est toujours pas centré verticalement. Il est un peu en dessous du centre car le "petit" indice (sur fond gris, en haut, visible uniquement lorsque le champ est mis au point) prend un peu de place en haut et pousse le EditText .
Cela ne semble pas être possible avec l'implémentation actuelle de TextInputLayout
. Mais vous pouvez obtenir ce que vous voulez en jouant avec le rembourrage de la variable TextInputEditText
.
Disons que vous avez une TextInputLayout
et une TextInputEditText
comme ceci:
<Android.support.design.widget.TextInputLayout
Android:id="@+id/text_input_layout"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="#FAA"
Android:hint="Text hint">
<Android.support.design.widget.TextInputEditText
Android:id="@+id/text_input_edit_text"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="#AAF" />
</Android.support.design.widget.TextInputLayout>
Comme vous pouvez le constater, la variable TextInputLayout
se compose d’une zone supérieure pour contenir l’indice dans la version réduite et d’une zone inférieure pour contenir l’indicateur dans la version complète (et le contenu en entrée). Lorsque la vue perd le focus et que le texte de montage est vide, l'indicateur se déplace dans l'espace bleu. En revanche, lorsque la vue est mise en évidence ou que le texte modifié contient du texte, l’indice se déplace vers l’espace rouge.
Donc, ce que nous voulons faire, c'est:
TextInputEditText
lorsqu'elle ne contient pas de texte ni de focus, ce remplissage est égal à la hauteur de la zone rouge;TextInputEditText
a le focus ou du texte à l'intérieur.En conséquence, la vue ressemblera à ceci avec le gros indice centré verticalement:
Disons que vous récupérez vos points de vue comme suit:
private lateinit var textInputLayout: TextInputLayout
private lateinit var textInputEditText: TextInputEditText
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
...
textInputLayout = view.findViewById(R.id.text_input_layout)
textInputEditText = view.findViewById(R.id.text_input_edit_text)
...
}
Voici un exemple d'implémentation que vous pouvez utiliser pour calculer l'espace rouge supérieur en pixels.
private fun getTextInputLayoutTopSpace(): Int {
var currentView: View = textInputEditText
var space = 0
do {
space += currentView.top
currentView = currentView.parent as View
} while (currentView.id != textInputLayout.id)
return space
}
Ensuite, vous pouvez mettre à jour le remplissage comme ceci:
private fun updateHintPosition(hasFocus: Boolean, hasText: Boolean) {
if (hasFocus || hasText) {
textInputEditText.setPadding(0, 0, 0, 0)
} else {
textInputEditText.setPadding(0, 0, 0, getTextInputLayoutTopSpace())
}
}
Vous devez maintenant appeler cette méthode à deux endroits: lorsque la vue est créée (en fait, nous devons attendre que la vue soit entièrement mesurée) et lorsque la mise au point change.
textInputLayout.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
if (textInputLayout.height > 0) {
textInputLayout.viewTreeObserver.removeOnPreDrawListener(this)
updateHintPosition(textInputEditText.hasFocus(), !textInputEditText.text.isNullOrEmpty())
return false
}
return true
}
})
textInputEditText.setOnFocusChangeListener { _, hasFocus ->
updateHintPosition(hasFocus, !textInputEditText.text.isNullOrEmpty())
}
Un problème est que la hauteur de la TextInputLayout
est en train de changer, de sorte que toute la vue bouge et ne semble pas vraiment centrée. Vous pouvez résoudre ce problème en plaçant la TextInputLayout
dans une FrameLayout
avec une hauteur fixe et en la centrant verticalement.
Enfin, vous pouvez animer tout. Vous devez simplement utiliser la TransitionManager
de la bibliothèque de support lorsque vous modifiez le remplissage.
Vous pouvez voir le résultat final dans ce lien: https://streamable.com/la9uk
Le code complet ressemblera à ceci:
La disposition:
<FrameLayout
Android:layout_width="match_parent"
Android:layout_height="60dp"> <-- Adapt the height for your needs -->
<Android.support.design.widget.TextInputLayout
Android:id="@+id/text_input_layout"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_gravity="center_vertical"
Android:background="#FAA"
Android:hint="Text hint">
<Android.support.design.widget.TextInputEditText
Android:id="@+id/text_input_edit_text"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="#AAF" />
</Android.support.design.widget.TextInputLayout>
</FrameLayout>
Le code:
private lateinit var textInputLayout: TextInputLayout
private lateinit var textInputEditText: TextInputEditText
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
val view = inflater.inflate(R.layout.your_layout, container, false)
textInputLayout = view.findViewById(R.id.text_input_layout)
textInputEditText = view.findViewById(R.id.text_input_edit_text)
textInputLayout.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
// Wait for the first draw to be sure the view is completely measured
if (textInputLayout.height > 0) {
textInputLayout.viewTreeObserver.removeOnPreDrawListener(this)
updateHintPosition(textInputEditText.hasFocus(), !textInputEditText.text.isNullOrEmpty(), false)
return false
}
return true
}
})
textInputEditText.setOnFocusChangeListener { _, hasFocus ->
updateHintPosition(hasFocus, !textInputEditText.text.isNullOrEmpty(), true)
}
return view
}
private fun updateHintPosition(hasFocus: Boolean, hasText: Boolean, animate: Boolean) {
if (animate) {
TransitionManager.beginDelayedTransition(textInputLayout)
}
if (hasFocus || hasText) {
textInputEditText.setPadding(0, 0, 0, 0)
} else {
textInputEditText.setPadding(0, 0, 0, getTextInputLayoutTopSpace())
}
}
private fun getTextInputLayoutTopSpace(): Int {
var currentView: View = textInputEditText
var space = 0
do {
space += currentView.top
currentView = currentView.parent as View
} while (currentView.id != textInputLayout.id)
return space
}
J'espère que cela résoudra votre problème.
Veuillez utiliser ce code Si vous souhaitez afficher un indice EditText dans le centre
<Android.support.design.widget.TextInputLayout Android:layout_width="match_parent"
Android:layout_height="wrap_content"
xmlns:Android="http://schemas.Android.com/apk/res/Android">
<Android.support.design.widget.TextInputEditText
Android:layout_width="match_parent"
Android:layout_height="90dp"
Android:hint="Test"
Android:gravity="center" />
Si vous souhaitez afficher l’indice EditText au centre verticalement ainsi qu’à gauche
<Android.support.design.widget.TextInputLayout Android:layout_width="match_parent"
Android:layout_height="wrap_content"
xmlns:Android="http://schemas.Android.com/apk/res/Android">
<Android.support.design.widget.TextInputEditText
Android:layout_width="match_parent"
Android:layout_height="90dp"
Android:hint="Test"
Android:gravity="center_vertical" />
Ou
<Android.support.design.widget.TextInputLayout Android:layout_width="match_parent"
Android:layout_height="wrap_content"
xmlns:Android="http://schemas.Android.com/apk/res/Android">
<Android.support.design.widget.TextInputEditText
Android:layout_width="match_parent"
Android:layout_height="90dp"
Android:hint="Test"
Android:gravity="center|left" />
Trouvé une solution:
<Android.support.design.widget.TextInputLayout
Android:layout_width="wrap_content"
Android:layout_height="wrap_content">
<Android.support.design.widget.TextInputEditText
Android:layout_width="200dp"
Android:layout_height="90dp"
Android:hint="Test"
Android:gravity="center_vertical" />
90dp comme hauteur était juste à titre d'exemple. Si vous pouviez fournir votre code XML, je pourrais l'adapter à votre cas. Vous devez juste définir Android:gravity="center_vertical"
et la TextInputLayout
devrait avoir wrap_content
comme hauteur
J'espère que ça aide :)