Ich möchte, dass meine Gegenstände GridView
quadratisch sind. Es gibt 2 Spalten und die Elementbreite ist fill_parent
(z. B. nehmen sie so viel horizontalen Platz wie möglich ein. Die Elemente sind benutzerdefinierte Ansichten.
Wie stelle ich die Höhe der Elemente so ein, dass sie ihrer variablen Breite entsprechen?
Oder wenn Sie eine Ansicht erweitern möchten, tun Sie einfach etwas ganz Einfaches wie:
public class SquareImageView extends ImageView { public SquareImageView(final Context context) { super(context); } public SquareImageView(final Context context, final AttributeSet attrs) { super(context, attrs); } public SquareImageView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final int width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec); setMeasuredDimension(width, width); } @Override protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { super.onSizeChanged(w, w, oldw, oldh); } }
Es ist erwähnenswert, dass dies
super.onMeasure()
nicht benötigt wird.onMeasured
Voraussetzung ist, dass Sie anrufen müssensetMeasuredDimension
.quelle
super.onMeasure()
anrufe, wird eine darin platzierte ImageView nicht gezeichnet. Es scheint also als erste Zeile deronMeasure
Methode erforderlich zu sein .Ich bin mir nicht sicher, ob dies mit den aktuellen Widgets möglich ist. Am besten fügen Sie Ihre benutzerdefinierte Ansicht in eine benutzerdefinierte "SquareView" ein. Diese Ansicht kann nur eine untergeordnete Ansicht enthalten und die Höhe so erzwingen, dass sie der Breite entspricht, wenn die onLayout-Methode aufgerufen wird.
Ich habe nie versucht, so etwas zu tun, aber ich denke, es sollte nicht zu schwierig sein. Eine alternative (und möglicherweise etwas einfachere) Lösung könnte darin bestehen, das Stammlayout Ihrer benutzerdefinierten Ansicht in Unterklassen zu unterteilen (z. B. wenn es sich um ein LinearLayout handelt, ein SquareLinearLayout zu erstellen) und dieses stattdessen als Container zu verwenden.
edit: Hier ist eine grundlegende Implementierung, die für mich zu funktionieren scheint:
package com.mantano.widget; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class SquareView extends ViewGroup { public SquareView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onLayout(boolean changed, int l, int u, int r, int d) { getChildAt(0).layout(0, 0, r-l, d-u); // Layout with max size } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { View child = getChildAt(0); child.measure(widthMeasureSpec, widthMeasureSpec); int width = resolveSize(child.getMeasuredWidth(), widthMeasureSpec); child.measure(width, width); // 2nd pass with the correct size setMeasuredDimension(width, width); } }
Es ist so konzipiert, dass es ein einzigartiges Kind hat, aber ich habe der Einfachheit halber alle Überprüfungen ignoriert. Die Grundidee besteht darin, das untergeordnete Element mit den von GridView festgelegten Breiten- / Höhenparametern zu messen (in meinem Fall wird numColumns = 4 zur Berechnung der Breite verwendet) und anschließend einen zweiten Durchgang mit den endgültigen Abmessungen mit height = width durchzuführen. .. Das Layout ist nur ein einfaches Layout, das das eindeutige untergeordnete Element bei (0, 0) mit den gewünschten Abmessungen (rechts-links, unten-oben) anordnet.
Und hier ist das XML, das für die GridView-Elemente verwendet wird:
<?xml version="1.0" encoding="utf-8"?> <com.mantano.widget.SquareView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/item" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" android:gravity="center"> <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello world" /> </LinearLayout> </com.mantano.widget.SquareView>
Ich habe ein LinearLayout in SquareView verwendet, damit es alle Schwerkraftmöglichkeiten, Ränder usw. verwaltet.
Ich bin nicht sicher, wie gut (oder schlecht) dieses Widget auf Orientierungs- und Dimensionsänderungen reagieren würde, aber es scheint richtig zu funktionieren.
quelle
Es ist ziemlich einfach, das Gitterelement quadratisch zu machen.
Führen Sie in Ihrer "GetView" -Methode Ihres Grid-Adapters einfach Folgendes aus:
@Override public View getView(int position, View convertView, ViewGroup parent) { GridView grid = (GridView)parent; int size = grid.getRequestedColumnWidth(); TextView text = new TextView(getContext()); text.setLayoutParams(new GridView.LayoutParams(size, size)); // Whatever else you need to set on your view return text; }
quelle
getRequestedColumnWidth
mitgetColumnWidth
und arbeitete für mich ... danke!Ich weiß nicht, ob dies der beste Weg ist, aber ich schaffe es, dass meine benutzerdefinierte Ansicht onSizeChanged auf diese Weise überschreibt:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (getLayoutParams() != null && w != h) { getLayoutParams().height = w; setLayoutParams(getLayoutParams()); } }
Ich verwende diese benutzerdefinierte Ansicht in einem LinearLayout und einer GridView und in beiden wird sie quadratisch angezeigt!
quelle
Das hat bei mir funktioniert!
Wenn Sie wie ich sind und getRequestedColumnWidth () nicht verwenden können, weil Ihr minSdk kleiner als 16 ist, empfehle ich diese Option.
in deinem Fragment:
DisplayMetrics dm = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); int size = dm.widthPixels / nbColumns; CustomAdapter adapter = new CustomAdapter(list, size, getActivity());
in Ihrem Adapter (in getView (int position, View convertView, ViewGroup parent))
v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, size));
fragment.xml:
<GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="match_parent" android:horizontalSpacing="3dp" android:verticalSpacing="3dp" android:numColumns="4" android:stretchMode="columnWidth" />
custom_item.xml: (zum Beispiel)
<ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/picture" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" />
Hoffe es wird jemandem helfen!
quelle
Wenn Sie eine statische Anzahl von Spalten in der XML festlegen, können Sie die Breite der Ansicht durch die Anzahl der Spalten dividieren.
Wenn Sie verwenden,
auto_fit
wird es etwas schwierig sein, die Spaltenanzahl zu ermitteln (es gibt keine Methode getColumnCount ()). Diese Frage sollte Ihnen übrigens irgendwie helfen.Dies ist der Code, den ich in der
getView(...)
Methode des Adapters mit einer festen Anzahl von Spalten verwende:item_side = mFragment.holder.grid.getWidth() / N_COL; v.getLayoutParams().height = item_side; v.getLayoutParams().width = item_side;
quelle
Versuchen
<GridView ... android:stretchMode="columnWidth" />
Sie können auch mit anderen Modi spielen
quelle
Dies ist, was ich tue, um quadratische Zellen in einer GridView anzuzeigen. Ich bin mir nicht sicher, ob Sie quadratische Zellen oder etwas anderes wollen.
GridView grid = new GridView( this ); grid.setColumnWidth( UIScheme.cellSize ); grid.setVerticalSpacing( UIScheme.gap ); grid.setStretchMode( GridView.STRETCH_COLUMN_WIDTH ); grid.setNumColumns( GridView.AUTO_FIT );
Und dann muss ich für die Ansicht, die ich für jede Zelle erstelle, Folgendes tun:
cell.setLayoutParams( new GridView.LayoutParams(iconSize, iconSize) );
quelle
Basierend auf SteveBorkmans Antwort , die API 16+ lautet:
@Override public View getView(int position, View convertView, ViewGroup parent) { GridView grid = (GridView)parent; int size = grid.getColumnWidth(); if (convertView == null){ convertView = LayoutInflater.from(context).inflate(R.layout.your_item, null); convertView.setLayoutParams(new GridView.LayoutParams(size, size)); } //Modify your convertView here return convertView; }
quelle
In Anlehnung an @ Gregorys Antwort musste ich mein Bild in ein LinearLayout einbinden, um zu verhindern, dass GridView seine Abmessungen vom Quadrat aus manipuliert. Beachten Sie, dass das äußere LinearLayout so eingestellt sein sollte, dass es die Dimension des Bildes aufweist, und dass die Breite der GridView-Spalte der Breite des Bildes und eines beliebigen Randes entspricht. Zum Beispiel:
<!-- LinearLayout wrapper necessary to wrap image button in order to keep square; otherwise, the grid view distorts it into rectangle. also, margin top and right allows the indicator overlay to extend top and right. NB: grid width is set in filter_icon_page.xml, and must correspond to size + margin --> <LinearLayout android:id="@+id/sport_icon_lay" android:layout_width="60dp" android:layout_height="60dp" android:orientation="vertical" android:layout_marginRight="6dp" android:layout_marginTop="6dp" > <ImageButton android:id="@+id/sport_icon" android:layout_width="60dp" android:layout_height="60dp" android:maxHeight="60dp" android:maxWidth="60dp" android:scaleType="fitCenter" /> </LinearLayout>
und das GridView wie:
<GridView android:id="@+id/grid" android:layout_width="fill_parent" android:layout_height="fill_parent" android:fillViewport="true" android:columnWidth="66dp" android:numColumns="auto_fit" android:verticalSpacing="25dp" android:horizontalSpacing="24dp" android:stretchMode="spacingWidth" />
quelle
In Ihrer Tätigkeit
DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); valX = displaymetrics.widthPixels/columns_number;
im CustomAdapter der GridView
v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, YourActivity.valX));
quelle