wake-up-neo.net

Raster von Bildern in ScrollView

Ich versuche, einen Bildschirm mit Text und Bildern zu erstellen. Ich möchte, dass die Bilder wie in einem Raster angeordnet sind, wie unten gezeigt, aber ich möchte, dass sie keine andere Scrollfunktion als die von der umgebenden ScrollView bereitgestellte haben. 

Ein Bild veranschaulicht meine Frage am besten:

alt text

<ScrollView>
    <LinearLayout>
        <ImageView />
        <TextView />
        <GridView />
        <TextView />
    </LinearLayout>
</ScrollView>

Was ist der beste Weg, um ein Raster mit einer unterschiedlichen Anzahl von Bildern anzeigen zu lassen, wenn das Raster keine Bildlauffunktion hat?

Bitte beachten Sie, dass das Deaktivieren der Bildlauffunktion für GridView nicht funktioniert, da dies nur die Bildlaufleisten deaktiviert, aber nicht alle Elemente anzeigt.

Update: Das Bild unten zeigt, wie es aussieht, wenn Bildlaufleisten in der GridView deaktiviert sind.

alt text

63
hanspeide

Oh Junge, ja, du wirst Probleme damit haben. Es macht mich verrückt, dass ListViews und GridViews nicht so erweitert werden können, dass sie ihre Kinder einwickeln können, da wir alle wissen, dass sie neben dem Scrollen und dem Recycling ihrer Kinder auch weitere nützliche Funktionen haben.

Trotzdem können Sie dieses Problem umgehen oder ein eigenes Layout erstellen, das Ihren Anforderungen entspricht, und dies ohne große Schwierigkeiten. Mir fallen zwei Möglichkeiten ein:

In meiner eigenen App habe ich eine ListView in eine ScrollView eingebettet. Ich habe dies getan, indem ich der ListView explizit gesagt habe, genau so hoch zu sein wie ihr Inhalt. Ich mache es, indem ich die Layout-Parameter direkt in der ListView.onMeasure()-Methode wie folgt ändere:

public class ExpandableListView extends ListView {

    boolean expanded = false;

    public ExpandableListView(Context context, AttributeSet attrs, int defaultStyle) {
        super(context, attrs, defaultStyle);
    }

    public boolean isExpanded() {
        return expanded;
    }

    public void setExpanded(boolean expanded) {
        this.expanded = expanded;
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // HACK!  TAKE THAT Android!
        if (isExpanded()) {         
            // Calculate entire height by providing a very large height hint.
            // View.MEASURED_SIZE_MASK represents the largest height possible.
            int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
                        MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);

            LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

Dies funktioniert, weil, wenn Sie der ListView einen Modus von AT_MOST geben, alle untergeordneten Elemente für Sie erstellt und gemessen werden, und zwar direkt in der onMeasure-Methode (ich habe dies beim Durchsuchen des Quellcodes entdeckt). Hoffentlich verhält sich GridView gleich, aber wenn nicht, können Sie den gesamten Inhalt der GridView selbst messen. Es wäre jedoch einfacher, wenn Sie die GridView dazu bringen könnten, es für Sie zu tun.

Beachten Sie, dass durch diese Lösung die Ansichtsrecyclingfunktion vollständig deaktiviert wird, wodurch GridView so effizient ist. Alle ImageViews sind dann im Speicher, auch wenn sie nicht sichtbar sind. Gleiches gilt für meine nächste Lösung.

Die andere Möglichkeit besteht darin, die GridView aufzuheben und ein eigenes Layout zu erstellen. Sie können entweder AbsoluteLayout oder RelativeLayout erweitern. Wenn Sie beispielsweise RelativeLayout erweitern, können Sie jedes Bild LEFT_OF des vorherigen Bildes platzieren, die Breite jedes Bildes verfolgen, bis Sie in dieser Zeile keinen Platz mehr haben, und dann die nächste Zeile mit dem ersten Bild des neuen beginnen row BELOW das höchste Bild der letzten Zeile. Um die Bilder horizontal zentriert oder in gleich großen Spalten zu platzieren, müssen Sie noch mehr Schmerzen durchmachen. Vielleicht ist AbsoluteLayout besser. So oder so, irgendwie schmerzhaft.

Viel Glück.

186
Neil Traft

Eine GridView mit Kopf- und Fußzeile kann verwendet werden, anstatt zu versuchen, GridView in ScrollView einzubetten. Kopf- und Fußzeile können alles sein - Texte, Bilder, Listen usw. Es gibt ein Beispiel für GridView mit Kopf- und Fußzeile: https://github.com/SergeyBurish/HFGridView

4
Sergey Burish

Sie haben 2 Lösungen für diese eine:

  1. Schreiben Sie Ihr eigenes Layout. Dies wäre die schwierigere Lösung (kann jedoch als die richtige betrachtet werden).

  2. Stellen Sie die tatsächliche Höhe Ihrer GridView im Code ein. Zum Beispiel:

 RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) myGridView.getLayoutParams (); 
 // lp.setMargins (0, 0, 10, 10); // Wenn Sie Layoutränder haben, müssen Sie auch diese einstellen 
 lp.height = measureRealHeight (...); 
 myGridView.setLayoutParams (lp); 

Die measureRealHeight()-Methode sollte ungefähr so ​​aussehen (hoffentlich habe ich es richtig verstanden):

private int measureRealHeight(...)
{
  final int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
  final double screenDensity = getResources().getDisplayMetrics().density;
  final int paddingLeft = (int) (X * screenDensity + 0.5f); // where X is your desired padding
  final int paddingRight = ...;
  final int horizontalSpacing = (int) (X * screenDensity + 0.5f); // the spacing between your columns
  final int verticalSpacing = ...; // the spacing between your rows
  final int columnWidth = (int) (X * screenDensity + 0.5f);             
  final int columnsCount = (screenWidth - paddingLeft - paddingRight + horizontalSpacing - myGridView.getVerticalScrollbarWidth()) / (columnWidth + horizontalSpacing);
  final int rowsCount = picsCount / columnsCount + (picsCount % columnsCount == 0 ? 0 : 1);

  return columnWidth * rowsCount + verticalSpacing * (rowsCount - 1);
}

Der obige Code sollte in Android 1.5 und höher funktionieren.

3
Edi

Erstellen Sie eine nicht scrollbare Listenansicht wie folgt:

public class ExpandableListView extends ListView{

public ExpandableListView(Context context) {
    super(context);
}

public ExpandableListView(Context context, AttributeSet attrs, int defaultStyle) {
    super(context, attrs, defaultStyle);
}

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

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
            Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
    ViewGroup.LayoutParams params = getLayoutParams();
    params.height = getMeasuredHeight();
  }
}

Erstellen Sie in Ihrer Layoutdatei ein Element wie folgt:

<com.example.ExpandableListView
           Android:layout_width="match_parent"
           Android:layout_height="wrap_content"/>

Das sollte funktionieren.

2
user3282666

Ich habe einen Weg gefunden, GridView in ScrollView eine feste Größe zu geben und das Scrollen zu aktivieren.

Dazu müssen Sie eine neue Klasse implementieren, die GridView erweitert und onTouchEvent () überschreibt, um requestDisallowInterceptTouchEvent (true) ..__ aufzurufen. Dadurch verlässt die übergeordnete Ansicht die Berührungsereignisse für die Interaktion mit dem Grid.

GridViewScrollable.Java:

package com.example;
import Android.content.Context;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.widget.GridView;

public class GridViewScrollable extends GridView {

    public GridViewAdjuntos(Context context) {
        super(context);
    }

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

    public GridViewAdjuntos(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev){
        // Called when a child does not want this parent and its ancestors to intercept touch events.
        requestDisallowInterceptTouchEvent(true);
        return super.onTouchEvent(ev);
    }
}

Fügen Sie es in Ihrem Layout mit den gewünschten Merkmalen hinzu:

<ScrollView 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"
Android:isScrollContainer="true" >

    <com.example.GridViewScrollable
    Android:id="@+id/myGVS"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:clickable="true"
    Android:numColumns="auto_fit"
    Android:columnWidth="100dp"
    Android:stretchMode="columnWidth" />

</ScrollView>

Holen Sie es sich einfach in Ihre Aktivität und stellen Sie den Adapter ein, zum Beispiel einen ArrayAdapter <> :

GridViewScrollable mGridView = (GridViewScrollable) findViewById(R.id.myGVS);
mGridView.setAdapter(new ArrayAdapter<>(this, Android.R.layout.simple_list_item_1, new String[]{"one", "two", "three", "four", "five"}));

Ich hoffe es hilft =)

1
Lionel T.

Versuche dies

 public static void setGridViewHeightBasedOnChildren(GridView gridView, int columns) {
        ListAdapter listAdapter = gridView.getAdapter();
        if (listAdapter == null)
            return;
        int desiredWidth = View.MeasureSpec.makeMeasureSpec(gridView.getWidth(), View.MeasureSpec.UNSPECIFIED);
        int totalHeight = 0;
        View view = null;
        int rows = listAdapter.getCount() / columns;
        if(listAdapter.getCount() % columns> 0){
            rows++;
        }
        for (int i = 0; i < rows; i++) {
            view = listAdapter.getView(i, view, gridView);
            if (i == 0)
                view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, LinearLayout.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = gridView.getLayoutParams();
        params.height = totalHeight + (gridView.getHorizontalSpacing() * rows);
        gridView.setLayoutParams(params);
        gridView.requestLayout();
    }
0
Roman Mosiienko

Um GridView mit einer anderen Ansicht in der Save ScrollView zu erhalten, klicken Sie auf diesen Link: http://www.londatiga.net/it/programming/Android/make-Android-listview-gridview-expandable-inside -scrollview/# comment-3967742 . Es ist hilfreich und habe meine Zeit gespart, die ich gerade 5 Minuten damit verbringe, wenn ich noch nie davon erfahren habe.

Aktualisieren:

Über den Link habe ich eine ExpandedGridView angepasst:

public class ExpandedGridView extends GridView {
    boolean expanded = false;

    public ExpandedGridView(Context context) {
        super(context);
    }

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

    public ExpandedGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public boolean isExpanded() {
        return expanded;
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // HACK! TAKE THAT Android!
        if (isExpanded()) {
            // Calculate entire height by providing a very large height hint.
            // But do not use the highest 2 bits of this integer; those are
            // reserved for the MeasureSpec mode.
            int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);
            ViewGroup.LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    public void setExpanded(boolean expanded) {
        this.expanded = expanded;
    }
}

Für Ihre XML-Datei wechseln Sie von GridView zu ExpandedGridView, die angepasst wurden.

<com.your.package.ExpandedGridView
    Android:id="@+id/home_screen_list_goals"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:numColumns="2" />

Verwendungszweck:

Nenne es in deiner Aktivität. Wenn es sich um ein Fragment handelt, verwenden Sie contentView.findViewById(...). Welche contentView ist Ihr gesamtes Layout?.

ExpandedGridView gridView = (ExpandedGridView) findViewById(R.id.home_screen_list_goals);
//set data into grid view
gridView.setAdapter(YOUR_ADAPTER_OBJECT);
gridView.setExpanded(true);

0
Sarith NOB