Mon problème est très similaire à Comment obtenir une mise en page dans laquelle un texte peut croître et ellipser, sans engloutir les autres éléments de la mise en page , mais lisez ci-dessous pourquoi je ne peux pas utiliser TableLayouts tel que proposé ici.
J'essaie de créer une ligne listview qui ressemble en gros à ceci:
| TextView | Voir 1 | Voir 2 |
Toutes les vues contiennent des éléments de largeur variable. Le TextView a ellipsize = "end" set. La vue 1 doit être alignée à gauche de la vue TextView, tandis que la vue 2 doit être alignée à la droite de l'écran. Ainsi, normalement, il y aurait des espaces entre View 1 et View 2. À mesure que le texte dans TextView s'allongera, TextView devrait s'agrandir, poussant View 1 vers la droite jusqu'à ce qu'il ne reste plus d'espaces. Ensuite, ellipsize devrait se déclencher, en coupant le texte dans TextView et en ajoutant un Ellipsis ("...") à la fin.
Donc, le résultat devrait ressembler à ceci:
+----------------------------------------+
| short text [view1] [view2] |
+----------------------------------------+
| long text with ell ... [view1] [view2] |
+----------------------------------------+
J'ai essayé:
Voici le GridLayout que j'ai essayé:
<GridLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content" >
<TextView
Android:layout_gravity="left|fill_horizontal"
Android:ellipsize="end"
Android:singleLine="true"
Android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite Ellipsis" />
<TextView
Android:layout_gravity="left"
Android:text="(view1)" />
<TextView
Android:layout_gravity="right"
Android:text="(view2)" />
</GridLayout>
View 1 et View 2 ne sont pas vraiment TextViews, je les ai simplement utilisées dans l'exemple pour simplifier les choses.
Existe-t-il un moyen d'y parvenir sans utiliser TableLayouts?
EDIT: Comme demandé, voici ma tentative de résoudre ceci avec un RelativeLayout. Dans ce cas, TextView occupe toute la largeur de l'écran. Ni view1 ni view2 ne sont visibles.
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content" >
<TextView
Android:id="@+id/rl0"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentLeft="true"
Android:ellipsize="end"
Android:singleLine="true"
Android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite Ellipsis" />
<TextView
Android:id="@+id/rl1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_toRightOf="@id/rl0"
Android:layout_marginLeft="10dp"
Android:text="(view1)" />
<TextView
Android:id="@+id/rl2"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_toRightOf="@id/rl1"
Android:layout_alignParentRight="true"
Android:layout_marginLeft="10dp"
Android:text="(view2)" />
</RelativeLayout>
Il semble que j'ai trouvé une solution potentielle pour empêcher un TextView dans GridLayout de se développer de manière illimitée et de pousser d'autres vues. Je ne sais pas si cela a déjà été documenté.
Vous devez utiliser fill layout_gravity et définir un layout_width ou une largeur arbitraire sur le long TextView nécessitant une ellipsisation.
Android:layout_gravity="fill"
Android:layout_width="1dp"
Fonctionne à la fois pour GridLayout et Android.support.v7.widget.GridLayout
Je suis un grand fan de LinearLayouts, alors voici ma suggestion en utilisant ceux-ci:
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal" >
<LinearLayout
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:layout_weight="1" >
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_weight="1"
Android:ellipsize="end"
Android:singleLine="true"
Android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite Ellipsis" />
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="(view1)" />
</LinearLayout>
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="right"
Android:text="(view2)" />
</LinearLayout>
Je pense que vous devriez créer une mise en page personnalisée pour votre but. Je ne sais pas comment faire cela en utilisant uniquement les dispositions/vues par défaut et en le faisant fonctionner pour tous les cas.
Je vais vous suggérer de jouer avec layout_weight propriété de votre widget
Exemple:
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
tools:context=".MainActivity" >
<LinearLayout
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:weightSum="10">
<LinearLayout
Android:id="@+id/ll_twoViewContainer"
Android:layout_weight="8"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:orientation="horizontal">
<TextView
Android:id="@+id/rl0"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentLeft="true"
Android:layout_weight="1"
Android:ellipsize="end"
Android:singleLine="true"
Android:text="Long text" />
<TextView
Android:id="@+id/rl1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginLeft="10dp"
Android:layout_toRightOf="@id/rl0"
Android:layout_weight="1"
Android:minWidth="120dp"
Android:text="(view1)" />
</LinearLayout>
<TextView
Android:id="@+id/rl2"
Android:layout_weight="2"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_toRightOf="@id/rl1"
Android:layout_alignParentRight="true"
Android:layout_marginLeft="10dp"
Android:text="(view2)" />
</LinearLayout>
</LinearLayout>
enfin, votre mise en page se présentera comme suit:
+----------------------------------------+
| short text [view1] [view2] |
+----------------------------------------+
| long text with ell ... [view1] [view2] |
+----------------------------------------+
L'astuce qui a fonctionné pour moi était d'utiliser maxWidth pour limiter la largeur de la première vue. Vous devez le faire avec Java, voici la logique de base:
firstView.setMaxWidth(parentView.getWidth() - view2.getWidth() - view1.getWidth() - padding * 2);
Pas joli, mais ça marche.
Je pense qu'il y a juste un petit problème sur la disposition qui pourrait être résolu, ancrant la vue3 à droite et partant de là pour forcer la vue à avoir une zone délimitée (donc être capable de définir correctement l'ellipse):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content">
<TextView
Android:id="@+id/rl3"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentRight="true"
Android:text="(view2)" />
<TextView
Android:id="@+id/rl2"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_toLeftOf="@id/rl3"
Android:text="(view1)" />
<TextView
Android:id="@+id/rl1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:ellipsize="end"
Android:singleLine="true"
Android:layout_alignParentLeft="true"
Android:layout_toLeftOf="@id/rl2"
Android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite Ellipsis" />
</RelativeLayout>
J'espère que cela t'aides...
Cordialement!
Essayez d'utiliser Poids de disposition
<TableRow
Android:id="@+id/tableRow3"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_alignBottom="@+id/tableRow2"
Android:layout_alignParentBottom="true"
Android:gravity="center"
Android:weightSum="10"
Android:background="@Android:color/black" >
<TextView
Android:id="@+id/txtInningsTotal"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="2"
Android:gravity="center"
Android:text="0"
Android:textColor="@Android:color/white" />
<TextView
Android:id="@+id/txtTeamOneTotal"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="2.5"
Android:gravity="center"
Android:text="0"
Android:textColor="@Android:color/white" />
<View
Android:layout_width="0dp"
Android:layout_height="match_parent"
Android:layout_weight="0.2" />
<TextView
Android:id="@+id/txtTeamTwoTotal"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="2.5"
Android:gravity="center"
Android:text="0"
Android:textColor="@Android:color/white" />
<View
Android:layout_width="0dp"
Android:layout_height="match_parent"
Android:layout_weight="0.2" />
<TextView
Android:id="@+id/txtGrandTotal"
Android:layout_width="0dp"
Android:layout_height="match_parent"
Android:layout_weight="3"
Android:gravity="center"
Android:text="0"
Android:textColor="@Android:color/white" />
</TableRow>
Ici, j'ai pris la ligne de table dans laquelle il y a une somme de poids de montage qui est de 10 signifie qu'il est 100% largeur de son parent. et dans toutes ses vues enfants, j'ai défini la largeur à 0Dp et le poids à 1 ou 2. afin qu'il prenne ce pourcentage sur 10. Le format sera ajusté en conséquence .
Si je vous ai bien compris, c’est la réponse que vous vouliez.
J'espère que ça aide!
Tout d'abord, vous devez mettre en page [vue 2] pour le parent droit;
Encore une fois, vous faites référence à la référence aux deux dernières mises en page!
<Relativelayout Android:layout_width="match_parent"
Android:layout_height="wrap_content"
<TextView
Android:id="@+id/view2"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentRight="true"
/>
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_toLeft="@id/view2"
Android:gravity="left">
<TextView
Android:id="@+id/shortORlongtTextView"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_toRightOf="@id/view1"
Android:ellipsize="end"
Android:maxLines="1"
Android:textSize="18dp"/>
<TextView
Android:id="@+id/view1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentRight="true"
/>
</RelativeLayout>
TableLayout donnera le comportement attendu. Peut poser un problème de performance comme le mentionne l'auteur, mais fonctionne parfaitement avec une présentation simple. Si la ligne est répétable et que vous pouvez la faire défiler, utilisez plutôt gridview.
<TableLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:stretchColumns="1"
Android:shrinkColumns="0"
>
<TableRow>
<TextView/>
<View1/>
<View2/>
</TableRow>
</TableLayout>
J'ai eu le même problème avec la disposition de la grille. Ce que j'ai fait est donné une largeur fixe pour la vue texte et également donné la propriété layout_columnWeight
pour chaque vue texte, puis le problème a été corrigé, espérons que cela aide ...
<TextView
Android:id="@+id/txtName"
style="@style/MyDetailTitle"
Android:layout_width="@dimen/detail_length"
Android:layout_height="wrap_content"
Android:text="@string/app_name"
app:layout_column="3"
app:layout_columnWeight="1"
app:layout_gravity="start"
app:layout_row="1" />
Si les vues de droite sont repoussées par le texte, vous pouvez également utiliser un objet ListView au lieu d'un objet GridView.
Il vous suffirait de transformer la base de la disposition des éléments de la liste en RelativeLayout et de définir des règles comme celles-ci:
Vous pouvez définir les deux vues à droite sur alignParentRight (avec Android: layout_alignParentLeft = "true"), mais assurez-vous que la première vue reste à gauche de la seconde et se pousse à gauche à mesure que les vues s'étendent.
Vous pouvez aligner le TextView de gauche sur la gauche tout en restant à gauche de la première vue (avec Android: layout_toLeftOf = "@ + id/viewId") afin de ne pas chevaucher les vues.
Je trouve ma solution pour le cas numéro 2 (celui avec un texte long):
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:weightSum="3" >
<TextView
Android:id="@+id/rl0"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_weight="3"
Android:ellipsize="end"
Android:singleLine="true"
Android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite Ellipsis" />
<TextView
Android:id="@+id/rl1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginLeft="10dp"
Android:layout_weight="1"
Android:text="(view1)" />
<TextView
Android:id="@+id/rl2"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginLeft="10dp"
Android:layout_weight="1"
Android:text="(view2)" />
</LinearLayout>
Le vrai problème est le cas un, et je n’ai pas essayé beaucoup de choses pour cela. J'espère que cela aidera (et si j'ai plus de temps libre, j'essaierai de réaliser le premier!).
Essaye ça
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:baselineAligned="false"
Android:orientation="horizontal">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_weight="1"
Android:gravity="center">
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:ellipsize="end"
Android:singleLine="true"
Android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite Ellipsis"/>
</LinearLayout>
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_weight="1"
Android:gravity="center">
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="left"
Android:text="(view1)"/>
</LinearLayout>
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_weight="1"
Android:gravity="center">
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="right"
Android:text="(view2)"/>
</LinearLayout>
</LinearLayout>
Actuellement, toutes les vues sont centrées. Vous pouvez modifier la propriété Android:gravity
pour répondre à vos besoins. Par exemple, vous pouvez aligner view1
right et view2
à gauche, auquel cas les deux derniers LinearLayout
ressemblent à quelque chose comme (avec une marge de 5dp respectivement):
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_weight="1"
Android:gravity="center|right">
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="left"
Android:layout_marginRight="5dp"
Android:text="(view1)"/>
</LinearLayout>
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_weight="1"
Android:gravity="center|left">
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="right"
Android:layout_marginLeft="5dp"
Android:text="(view2)"/>
</LinearLayout>
GridLayout est comme les autres choses sur Android: imparfait par la conception.
Vous aurez besoin d'une mise en page personnalisée. L'exemple suivant vous permettra de mettre en page des éléments tels que:
[ label | short text | very long label | short text ]
[ long label | very very very | label | very long text ]
[ | long text | | ]
import Android.content.Context;
import Android.view.View;
import Android.view.ViewGroup;
import Java.util.ArrayList;
import Java.util.List;
public class TwoColumsGridLayout extends ViewGroup {
private final List<List<View>> rows;
private int rowCount = 0;
private int firstColumWidth;
private int secondColumWidth;
private int thirdColumWidth;
private int fourthColumnWidth;
private final List<Integer> rowHeights = new ArrayList<>();
private final List<List<Integer>> cellHeights = new ArrayList<>();
private final List<Integer> firstCellsWidths = new ArrayList<>(4);
private final List<Integer> thirdCellsWidths = new ArrayList<>(4);
public TwoColumsGridLayout(Context context, int rowCount) {
super(context);
rows = new ArrayList<>(rowCount);
}
public void add(Context ctx, TextView l1, View t1, TextView l2, View t2) {
final List<View> row = new ArrayList<>(4);
row.add(l1);
row.add(t1);
row.add(l2);
row.add(t2);
rows.add(row);
this.addView(l1);
this.addView(t1);
if (l2 != null)
this.addView(l2);
if (t2 != null)
this.addView(t2);
this.rowCount++;
}
public int getRowCount() {
return rowCount;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int curLeft = 0;
int curBottom;
int curRight;
int curTop = 0;
int i = 0;
for (List<View> row : rows) {
final int rowHeight = this.rowHeights.get(i);
final List<Integer> rowCellHeights = this.cellHeights.get(i);
final View v0 = row.get(0);
curLeft = 0;
curRight = curLeft + this.firstColumWidth;
if (v0 != null) {
curBottom = curTop + rowCellHeights.get(0);
// Right align
v0.layout(curLeft + this.firstColumWidth - this.firstCellsWidths.get(i), curTop + 7, curRight, curBottom + 7);
}
//
final View v1 = row.get(1);
curLeft += this.firstColumWidth;
curRight = curLeft + this.secondColumWidth;
if (v1 != null) {
curBottom = curTop + rowCellHeights.get(1);
v1.layout(curLeft, curTop, curRight, curBottom);
}
//
final View v2 = row.get(2);
curLeft += this.secondColumWidth;
curRight = curLeft + this.thirdColumWidth;
if (v2 != null) {
curBottom = curTop + rowCellHeights.get(2);
// Right align
v2.layout(curLeft + this.thirdColumWidth - this.thirdCellsWidths.get(i), curTop + 7, curRight, curBottom + 7);
}
//
final View v3 = row.get(3);
curLeft += this.thirdColumWidth;
curRight = curLeft + this.fourthColumnWidth;
if (v3 != null) {
curBottom = curTop + rowCellHeights.get(3);
v3.layout(curLeft, curTop, curRight, curBottom);
}
curTop += rowHeight;
i++;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
// Compute first column width
firstColumWidth = 0;
for (List<View> row : rows) {
final View v = row.get(0);
if (v != null) {
v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
measureChild(v, widthMeasureSpec, heightMeasureSpec);
final int w = v.getMeasuredWidth();
if (firstColumWidth < w) {
firstColumWidth = w;
}
}
}
// Compute third column width
thirdColumWidth = 0;
for (List<View> row : rows) {
final View v = row.get(2);
if (v != null) {
v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
measureChild(v, widthMeasureSpec, heightMeasureSpec);
final int w = v.getMeasuredWidth();
if (thirdColumWidth < w) {
thirdColumWidth = w;
}
}
}
secondColumWidth = (parentWidth - firstColumWidth - thirdColumWidth) / 2;
fourthColumnWidth = parentWidth - firstColumWidth - secondColumWidth - thirdColumWidth;
// Clear
this.rowHeights.clear();
this.cellHeights.clear();
this.firstCellsWidths.clear();
this.thirdCellsWidths.clear();
// Compute heights
int height = 0;
for (List<View> row : rows) {
final ArrayList<Integer> rowCellHeights = new ArrayList<>(4);
cellHeights.add(rowCellHeights);
int rowHeight = 0;
// First column
final View v0 = row.get(0);
if (v0 != null) {
int h = v0.getMeasuredHeight();
this.firstCellsWidths.add(v0.getMeasuredWidth());
rowCellHeights.add(h);
if (rowHeight < h) {
rowHeight = h;
}
} else {
this.firstCellsWidths.add(0);
}
// Second column
final View v1 = row.get(1);
if (v1 != null) {
v1.setLayoutParams(new ViewGroup.LayoutParams(secondColumWidth, LayoutParams.WRAP_CONTENT));
measureChild(v1, widthMeasureSpec, heightMeasureSpec);
int h = v1.getMeasuredHeight();
rowCellHeights.add(h);
if (rowHeight < h) {
rowHeight = h;
}
}
// Third column
final View v2 = row.get(2);
if (v2 != null) {
int h = v2.getMeasuredHeight();
this.thirdCellsWidths.add(v2.getMeasuredWidth());
rowCellHeights.add(h);
if (rowHeight < h) {
rowHeight = h;
}
} else {
this.thirdCellsWidths.add(0);
}
// Fourth column
final View v3 = row.get(3);
if (v3 != null) {
v3.setLayoutParams(new ViewGroup.LayoutParams(fourthColumnWidth, LayoutParams.WRAP_CONTENT));
measureChild(v3, widthMeasureSpec, heightMeasureSpec);
int h = v3.getMeasuredHeight();
rowCellHeights.add(h);
if (rowHeight < h) {
rowHeight = h;
}
}
height += rowHeight;
this.rowHeights.add(rowHeight);
}
setMeasuredDimension(parentWidth, height);
}
}
S'amuser.