2012-03-27 1 views

Antwort

0

Bis Sie hier das Layout eingeben, könnte ich nur annehmen, dass Sie in Ihrem linearen Layout falsche horizontale/vertikale Parameter eingestellt haben.

9

Sie können scrollbare Ansichten in Android nicht verschachteln - z. B. ListView, GridView, ScrollView.

Sie konnten einen Blick auf den folgenden Code geben:

import android.content.Context; 
import android.util.AttributeSet; 
import android.view.ViewGroup; 
import android.widget.GridView; 

public class ScrollableGridView extends GridView { 
    boolean expanded = true; 

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

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

    public ScrollableGridView(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; 
    } 
} 

Es ist ein wenig bessere Version von Grid es fast arbeiten ermöglicht, wenn in Scroll verschachtelt. Ich sagte "fast arbeiten", da ich es manchmal 20-30 Pixel zu kurz oder zu lang fand. Sie sollten beachten, dass dies verhindern würde, dass die Ansichten wiederverwendet werden, also ist es viel schwerer als normale GridView.

In meinem Fall habe ich LinearLayout erweitert und damit seine Kinder in Spalten ausrichten. Es war nicht wirklich schwer - ich kann dir Beispiele geben, wenn du willst. :) Ich habe das GridView-Beispiel von this answer bekommen. Hier

ist ein Beispiel für eine Gridview basierend auf Linearlayout:

import java.util.List; 
import android.content.Context; 
import android.content.res.TypedArray; 
import android.util.AttributeSet; 
import android.util.TypedValue; 
import android.view.Gravity; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.LinearLayout; 

public class GridLikeLayout extends LinearLayout { 
    private static final int DEFAULT_ITEMS_PER_ROW = 1; 
    private final int DEFAULT_COLUMN_WIDTH = (int) TypedValue.applyDimension(
      TypedValue.COMPLEX_UNIT_DIP, 150, getContext().getResources() 
        .getDisplayMetrics()); 

    private int itemsPerRow = DEFAULT_ITEMS_PER_ROW; 
    private List<View> innerViews = null; 

    private int columnWidth; 

    public GridLikeLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     TypedArray a = context.obtainStyledAttributes(attrs, 
       R.styleable.GridLikeLayout); 

     // itemsPerRow = a.getInt(R.styleable.GridLikeLayout_columns, 
     // DEFAULT_ITEMS_PER_ROW); 

     try { 
      columnWidth = (int) a.getDimension(
        R.styleable.GridLikeLayout_column_width, DEFAULT_COLUMN_WIDTH); 
     } catch (UnsupportedOperationException uoe) { 
      columnWidth = (int) a.getInt(
        R.styleable.GridLikeLayout_column_width, DEFAULT_COLUMN_WIDTH); 
     } 

     setOrientation(LinearLayout.VERTICAL); 
    } 

    public GridLikeLayout(Context context) { 
     super(context); 
     setOrientation(LinearLayout.VERTICAL); 
    } 

    public void setInnerViews(List<View> innerViews) { 
     this.innerViews = innerViews; 
     processViews(); 
    } 

    public List<View> getInnerViews() { 
     return innerViews; 
    } 

    protected void processViews() { 
     if (null != innerViews) { 
      LinearLayout innerContainer = null; 
      innerContainer = generateInnerContainer(); 
      int childrenCount = innerViews.size(); 
      for (int index = 0; index < childrenCount; ++index) { 
       if (isFull(innerContainer)) { 
        addInnerContainer(innerContainer); 
        innerContainer = generateInnerContainer(); 
       } 
       View child = innerViews.get(index); 
       if (null != child.getParent()) { 
        ((ViewGroup) child.getParent()).removeView(child); 
       } 
       addInnerView(innerContainer, child); 
      } 

      addInnerContainer(innerContainer); 
     } 
    } 

    protected boolean isFull(LinearLayout innerContainer) { 
     return 0 == (innerContainer.getChildCount() % itemsPerRow) 
       && 0 < innerContainer.getChildCount(); 
    } 

    protected void addInnerView(LinearLayout innerContainer, View child) { 
     int width = LayoutParams.WRAP_CONTENT; 
     int height = LayoutParams.WRAP_CONTENT; 
     LayoutParams innerParams = new LayoutParams(width, height); 
     innerParams.weight = 1; 
     innerParams.gravity = Gravity.CENTER; 
     innerContainer.addView(child, innerParams); 
    } 

    protected void addInnerContainer(LinearLayout innerContainer) { 
     LayoutParams params = generateDefaultLayoutParams(); 
     params.width = LayoutParams.MATCH_PARENT; 
     addView(innerContainer, params); 
    } 

    protected LinearLayout generateInnerContainer() { 
     LinearLayout innerContainer; 
     innerContainer = new LinearLayout(getContext()); 
     innerContainer.setGravity(Gravity.CENTER); 
     return innerContainer; 
    } 

    public void setOnInnerViewClickListener(OnClickListener listener) { 
     for (View innerView : innerViews) { 
      innerView.setOnClickListener(listener); 
     } 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     // Sets up mListPadding 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

     int widthMode = MeasureSpec.getMode(widthMeasureSpec); 
     int widthSize = MeasureSpec.getSize(widthMeasureSpec); 

     if (widthMode == MeasureSpec.UNSPECIFIED) { 
      if (columnWidth > 0) { 
       widthSize = columnWidth + getPaddingLeft() + getPaddingRight(); 
      } else { 
       widthSize = getPaddingLeft() + getPaddingRight(); 
      } 
      widthSize += getVerticalScrollbarWidth(); 
     } 

     int childWidth = widthSize - getPaddingLeft() - getPaddingRight(); 
     int columnsNumber = determineColumns(childWidth); 
     if (columnsNumber > 0 && columnsNumber != itemsPerRow) { 
      itemsPerRow = columnsNumber; 
      removeAllViews(); 
      processViews(); 
     } 
    } 

    protected int determineColumns(int availableSpace) { 
     int columnsNumber = itemsPerRow; 
     if (0 < columnWidth) { 
      columnsNumber = availableSpace/columnWidth; 
     } 
     return columnsNumber; 
    } 

} 

Hier ist meine Ressourcendatei für die benutzerdefinierte Attribute:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 

    <attr name="column_width" format="dimension|integer"> 
     <enum name="single_column" value="-1" /> 
    </attr> 
    <declare-styleable name="GridLikeLayout"> 
     <attr name="column_width" /> 
    </declare-styleable> 

</resources> 

Hier ist ein Beispiel für die Verwendung:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/layoutContainer" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 

    <ScrollView 
     android:id="@+id/itemsScroller" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" > 

     <LinearLayout 
      android:id="@+id/itemsLayout" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:orientation="vertical" > 

      <your_package.view.GridLikeLayout 
       xmlns:my="YOUR APPLICATION PACKAGE" 
       android:id="@+id/MyGrid" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
       my:column_width="260dp" 
       android:focusable="true" 
       android:gravity="center_horizontal" 
       android:padding="5dp" > 
      </your_package.GridLikeLayout> 

      <View 
       android:id="@+id/viewSeparator" 
       android:layout_width="fill_parent" 
       android:layout_height="2dp" /> 

      <your_package.GridLikeLayout 
       xmlns:my="YOUR APPLICATION PACKAGE" 
       android:id="@+id/list" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       my:column_width="single_column" > 
      </your_package.GridLikeLayout> 

     </LinearLayout> 
    </ScrollView> 

</FrameLayout> 

Bitte sagen Sie mir, wenn Sie Probleme haben, das Beispiel zu laufen - ich kann es nicht im Mome versuchen nt. Also, wenn Sie Probleme haben, werde ich es später überprüfen. Vergessen Sie nicht, die Paketnamen zu ändern - "your_package" sollte das Paket sein, in dem Sie das GridLikeLayout speichern, und "YOUR APPLICATION PACKAGE" ist das Paket Ihrer App, das im Anwendungsmanifest angegeben ist. :)

+0

PLZ geben Sie mir Beispiel ... – Venkat

+0

@venkat, ich habe ein Beispiel zu meinem Beitrag hinzugefügt. Probieren Sie es aus und sagen Sie mir, wenn Sie Hilfe brauchen. :) –

0

Ihre erste Lösung funktioniert, berücksichtigt aber nicht, dass GridViews oft Image-Caching implizieren, wie in meinem Fall. Hier führt Ihre erste Lösung jedes Mal zu OutOfMemoryError, wenn ich mit dem Scrollen anfange. Hat schon jemand eine Beispiellösung, die Image-Caching berücksichtigt?

Verwandte Themen