Les vues ont un minHeight
mais il leur manque un maxHeight
:
Ce que je cherche à faire, c’est que certains éléments (vues) remplissent un ScrollView
. Quand il y a des articles 1..3, je veux les afficher directement. Ce qui signifie que ScrollView
a la hauteur de 1, 2 ou 3 éléments.
Quand il y a 4 éléments ou plus, je veux que le ScrollView
cesse de se développer (donc un maxHeight
) et commence à fournir le défilement.
Cependant, il n’existe malheureusement aucun moyen de définir un maxHeight
. Donc, je dois probablement définir ma hauteur ScrollView
par programme à WRAP_CONTENT
Lorsqu'il y a des éléments 1..3 et définir la hauteur à 3*sizeOf(View)
lorsqu'il y a 4 éléments ou plus .
Quelqu'un peut-il expliquer pourquoi il n'y a pas de maxHeight
fourni, alors qu'il y a déjà un minHeight
?
(BTW: certaines vues, comme ImageView
ont un maxHeight
implémenté.)
Aucune de ces solutions ne fonctionnait pour ce dont j'avais besoin, à savoir un ScrollView défini sur wrap_content, mais avec un maxHeight afin qu'il cesse de se développer après un certain point et commence à défiler. Je viens simplement de surcharger la méthode onMeasure dans ScrollView.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(300, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Cela peut ne pas fonctionner dans toutes les situations, mais cela me donne certainement les résultats nécessaires pour ma mise en page. Et cela répond aussi au commentaire de madhu.
Si une mise en page est présente sous le scrollview, cette astuce ne fonctionnera pas - madhu 5 mars à 4:36
Pour créer un ScrollView
ou ListView
avec un maxHeight, il vous suffit de créer un objet LinearLayout transparent avec une hauteur correspondant à ce que vous souhaitez que maxHeight soit. Vous définissez ensuite la hauteur de ScrollView sur wrap_content
. Cela crée un ScrollView qui semble grossir jusqu'à ce que sa hauteur soit égale à celle de LinearLayout parent.
Cela a fonctionné pour moi pour le rendre personnalisable en xml:
MaxHeightScrollView.Java:
public class MaxHeightScrollView extends ScrollView {
private int maxHeight;
private final int defaultHeight = 200;
public MaxHeightScrollView(Context context) {
super(context);
}
public MaxHeightScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
if (!isInEditMode()) {
init(context, attrs);
}
}
public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (!isInEditMode()) {
init(context, attrs);
}
}
@TargetApi(Build.VERSION_CODES.Lollipop)
public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
if (!isInEditMode()) {
init(context, attrs);
}
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView);
//200 is a defualt value
maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.MaxHeightScrollView_maxHeight, defaultHeight);
styledAttrs.recycle();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
attr.xml
<declare-styleable name="MaxHeightScrollView">
<attr name="maxHeight" format="dimension" />
</declare-styleable>
exemple de mise en page
<blah.blah.MaxHeightScrollView Android:layout_weight="1"
app:maxHeight="90dp"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content">
<EditText Android:id="@+id/commentField"
Android:hint="Say Something"
Android:background="#FFFFFF"
Android:paddingLeft="8dp"
Android:paddingRight="8dp"
Android:gravity="center_vertical"
Android:maxLines="500"
Android:minHeight="36dp"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content" />
</blah.blah.MaxHeightScrollView>
(Je sais que cela ne répond pas directement à la question, mais pourrait être utile aux autres personnes à la recherche de la fonctionnalité maxHeight)
ConstraintLayout offre une hauteur maximale à ses enfants via
app:layout_constraintHeight_max="300dp"
app:layout_constrainedHeight="true"
ou
app:layout_constraintWidth_max="300dp"
app:layout_constrainedWidth="true"
Exemple d'utilisation ici .
J'aurais commenté la réponse de Whizzle si je le pouvais, mais je pensais qu'il était utile de noter que pour que je puisse résoudre ce problème dans le contexte du mode multi-fenêtre dans Android N, je devais modifiez légèrement le code en ceci:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(MeasureSpec.getSize(heightMeasureSpec) > maxHeight) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Cela permet de redimensionner la mise en page pour qu'elle soit inférieure à la hauteur maximale, mais l'empêche également d'être plus grande que la hauteur maximale. J’ai utilisé c’est une classe de présentation qui remplace RelativeLayout
, ce qui m’a permis de créer une boîte de dialogue personnalisée avec un ScrollView
comme enfant de MaxHeightRelativeLayout
qui ne développe pas toute la hauteur de l'écran et réduit également pour tenir dans la plus petite taille de la veuve en multi-fenêtre pour Android N.
Il n'y a aucun moyen de définir maxHeight. Mais vous pouvez définir la hauteur.
Pour ce faire, vous devrez découvrir la hauteur de chaque élément de scrollView. Après cela, réglez simplement scrollView height sur numberOfItens * heightOfItem.
Pour découvrir la hauteur d'un article, procédez comme suit:
View item = adapter.getView(0, null, scrollView);
item.measure(0, 0);
int heightOfItem = item.getMeasuredHeight();
Pour définir la hauteur, procédez comme suit:
// if the scrollView already has a layoutParams:
scrollView.getLayoutParams().height = heightOfItem * numberOfItens;
// or
// if the layoutParams is null, then create a new one.
scrollView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, heightOfItem * numberOfItens));
Ma vue personnalisée MaxHeightScrollView
public class MaxHeightScrollView extends ScrollView {
private int maxHeight;
public MaxHeightScrollView(Context context) {
this(context, null);
}
public MaxHeightScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray styledAttrs =
context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView);
try {
maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.MaxHeightScrollView_mhs_maxHeight, 0);
} finally {
styledAttrs.recycle();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (maxHeight > 0) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
style.xml
<declare-styleable name="MaxHeightScrollView">
<attr name="mhs_maxHeight" format="dimension" />
</declare-styleable>
tilisation
<....MaxHeightScrollView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
app:mhs_maxHeight="100dp"
>
...
</....MaxHeightScrollView>
Avez-vous essayé d'utiliser le valeur layout_weight ? Si vous en définissez une sur une valeur supérieure à 0, la vue sera étendue à l'espace disponible restant.
Si vous aviez plusieurs vues à étirer, la valeur deviendra un poids entre elles.
Ainsi, si vous avez deux vues définies avec une valeur layout_weight de 1, elles s’étireront toutes les deux pour remplir l’espace mais elles s’étireront toutes deux à la même quantité d’espace. Si vous définissez l'une d'elles sur la valeur 2, le résultat sera deux fois plus étendu que celui de l'autre vue.
Quelques informations supplémentaires sont énumérées ici dans Linear Layout.
Enroulez votre ScrollView
autour de votre un simple LinearLayout
avec layout_height = "max_height", cela fera un travail parfait. En fait, j'ai ce code en production des 5 dernières années avec zéro numéro.
<LinearLayout
Android:id="@+id/subsParent"
Android:layout_width="match_parent"
Android:layout_height="150dp"
Android:gravity="bottom|center_horizontal"
Android:orientation="vertical">
<ScrollView
Android:id="@+id/subsScroll"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginBottom="10dp"
Android:layout_marginEnd="15dp"
Android:layout_marginStart="15dp">
<TextView
Android:id="@+id/subsTv"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="@string/longText"
Android:visibility="visible" />
</ScrollView>
</LinearLayout>
Si quelqu'un envisage d'utiliser la valeur exacte pour LayoutParams, par exemple.
setLayoutParams(new LayoutParams(Y, X );
N'oubliez pas de prendre en compte la densité de l'affichage de l'appareil, sinon vous pourriez avoir un comportement très étrange sur différents appareils. Par exemple:
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics d = new DisplayMetrics();
display.getMetrics(d);
setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, (int)(50*d.density) ));
Comme nous le savons, les appareils fonctionnant sous Android peuvent avoir différentes tailles d’écran. Comme nous le savons plus en détail, les vues doivent s’ajuster de manière dynamique et devenir l’espace approprié.
Si vous définissez une hauteur maximale, vous pouvez forcer la vue à ne pas disposer de suffisamment d'espace ou à moins d'espace. Je sais que parfois, il semble être pratiquement de définir une hauteur maximale. Mais si la résolution change radicalement et si!, La vue, qui a une hauteur maximale, n’apparaîtra pas appropriée.
je pense qu'il n'y a pas de moyen approprié de faire exactement la mise en page que vous voulez. Je vous recommanderais de réfléchir à votre mise en page en utilisant des gestionnaires de mise en page et des mécanismes relatifs. Je ne sais pas ce que vous essayez d'atteindre, mais cela me semble un peu étrange qu'une liste ne contienne que trois éléments, puis que l'utilisateur doit faire défiler l'écran.
btw. minHeight n'est pas garanti (et ne devrait peut-être pas exister non plus). il peut être avantageux de forcer la visibilité des éléments, tandis que les autres éléments relatifs deviennent plus petits.
D'abord obtenir la hauteur de l'élément en pixels
View rowItem = adapter.getView(0, null, scrollView);
rowItem.measure(0, 0);
int heightOfItem = rowItem.getMeasuredHeight();
alors simplement
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getMetrics(displayMetrics);
scrollView.getLayoutParams().height = (int)((heightOfItem * 3)*displayMetrics .density);
je pense que vous pouvez définir la hauteur au moment de l'exécution pour 1 élément seulement scrollView.setHeight(200px)
, pour 2 éléments scrollView.setheight(400px)
pendant 3 ou plus scrollView.setHeight(600px)
si vous voulez créer une liste déroulante ou une liste déroulante, cliquez sur RelativeLayout avec les options topview et bottomview pour le haut et le bas:
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_above="@+id/topview"
Android:layout_below="@+id/bottomview" >
J'ai une réponse ici:
https://stackoverflow.com/a/29178364/1148784
Créez simplement une nouvelle classe qui étend ScrollView et remplacez sa méthode onMeasure
.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (maxHeight > 0){
int hSize = MeasureSpec.getSize(heightMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
switch (hMode){
case MeasureSpec.AT_MOST:
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.min(hSize, maxHeight), MeasureSpec.AT_MOST);
break;
case MeasureSpec.UNSPECIFIED:
heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
break;
case MeasureSpec.EXACTLY:
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.min(hSize, maxHeight), MeasureSpec.EXACTLY);
break;
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}