2012-03-27 56 views

回答

0

直到你把這裏的佈局,我可以假設只有你在你的線性佈局中設置了錯誤的水平/垂直參數。

9

您不能在Android中嵌套可滾動視圖 - 即ListView,GridView,ScrollView。

你可以給看看下面的代碼:

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; 
    } 
} 

這是一個好一點的版本的GridView的允許它幾乎工作嵌套,滾動型的時候。我說「幾乎可以工作」,因爲我發現它有時候太短或太長,20-30像素。 你應該注意到這會阻止視圖被重用,所以它比正常的GridView更重。

在我的情況下,我最終擴展了LinearLayout並使用它來對齊列中的子項。這不是很難 - 如果你願意,我可以給你舉例。 :)

我從this answer得到GridView示例。

下面是基於的LinearLayout一個GridView的例子:

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; 
    } 

} 

這是自定義我的資源文件屬性:

<?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> 

下面是一個例子用法:

<?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> 

請告訴我,如果你有任何麻煩運行的例子 - 我無法嘗試在mome NT。所以如果你有問題,我會在稍後檢查。不要忘記更改軟件包名稱 - 「your_package」應該是存儲GridLikeLayout的軟件包,「您的應用軟件包」是您應用的軟件包 - 應用軟件清單中指定的軟件包。 :)

+0

PLZ給我的例子... – Venkat 2012-09-11 05:08:09

+0

@venkat,我已經添加了一個例子到我的文章。試一試,告訴我你是否需要任何幫助。 :) – 2012-09-17 08:26:35

0

你的第一個解決方案確實有效,但沒有考慮到GridView通常暗示圖像緩存,就像我的情況。這裏你的第一個解決方案每次開始滾動時都會導致OutOfMemoryError。 有沒有人已經有一個示例解決方案,它考慮了圖像緩存?

相關問題