2016-03-05 81 views
1

我正在嘗試創建一個佈局管理器,它將水平放置它的子級,直到遇到回收器視圖的寬度。如果到達邊緣,它應該佈置下一行的孩子。

例如假設有在回收站視圖4項 - item1item2item3item4。 將item1item2的視圖排列在彼此的旁邊。還剩下一些空間。但item3's視圖不能適應該寬度。所以item3去下一行。但剩下的差距現在應該在item1item2之間平分。爲RecyclerView創建可變列大小布局管理器

| <item1><item2><--gap-->| 
|<-----item3---->  | 

這應該成爲

| <--item1--> <--item2-->| 
|<-----item3---->  | 

如果item4's視圖item3後的空間內配合,應該有佈局。

| <--item1--> <--item2--> | 
|<-----item3----><-item4->| 


這無法通過GridLayoutManagerStaggeredGridLayoutManager來實現,因爲他們沒有考慮到不同的個人物品的寬度。

要編寫自定義佈局管理器,我有一種感覺,我應該重寫onLayoutChildren佈局管理器的方法。但是我現在有點卡住了。我不知道如何去做這件事。任何幫助,將不勝感激。 謝謝。

回答

0

我有類似的問題,但解決了這個使用GridLayout。所有的意見應該從一開始就創建的優缺點:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
       xmlns:app="http://schemas.android.com/apk/res-auto" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content"> 

     <android.support.v7.widget.GridLayout 
      android:id="@+id/bubble_grid" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:scrollbars="vertical" 
      android:scrollbarStyle="outsideOverlay" 
      android:layout_gravity="top|left" 
      app:orientation="vertical" 
      app:columnCount="@integer/grid_cells"> 
     </android.support.v7.widget.GridLayout> 

    </ScrollView> 

這裏是一個適配器:

public class GridAdapter { 
    /** 
    * Indicates maximum filled row in current column, column is the index of arr, row is the value 
    * [224444555550000000] 
    * It equals to: 
    * [***********-------] 
    * [***********-------] 
    * [--*********-------] 
    * [--*********-------] 
    * [------*****-------] 
    * [------------------] 
    */ 
    private final int[] mRowMatrix; 

    public GridAdapter(GridLayout gridLayout) { 
     mGridLayout = gridLayout; 
     mPlacedList = new ArrayList<>(10); 
     mUnplacedList = new LinkedList<>(); 

     mNumColumns = ResHelper.getInteger(R.integer.grid_cells); 
     mMinCells = ResHelper.getInteger(R.integer.min_cells); 
     mMaxCells = ResHelper.getInteger(R.integer.max_cells); 
     mRowMatrix = new int[mNumColumns]; 
    } 

    public void notifyDataSetChanged() { 

     while (mUnplacedList.size() > 0) { 
      final int toCol = findColWithMinRow(); 
      final int gapSize = findGapSizeForCol(toCol); 
      final CustomView view = findAppropriate(gapSize); 
      if (view == null) { 
       final int filledRow = toCol > 0 
         ? (toCol + gapSize < mRowMatrix.length ? Math.min(mRowMatrix[toCol - 1], mRowMatrix[toCol + gapSize]) : mRowMatrix[toCol - 1]) 
         : mRowMatrix[gapSize]; 
       for (int j = toCol, jCount = toCol + gapSize; j < jCount; j++) { 
        mRowMatrix[j] = filledRow; 
       } 
      } else { 
       placeView(view, toCol, mRowMatrix[toCol]); 
      } 
     } 
    } 

    /** 
    * Put view in certain column and row in the gridlayout 
    */ 
    private void placeView(CustomView view, int toCol, int toRow) { 
     final int gridSize = view.getGridSize(); 
     final GridLayout.LayoutParams params = new GridLayout.LayoutParams(); 
     params.width = params.height = gridSize * mCellSize; 
     params.columnSpec = GridLayout.spec(toCol, gridSize); 
     params.rowSpec = GridLayout.spec(toRow, gridSize); 

     mPlacedList.add(view); 
     mUnplacedList.remove(view); 
     mGridLayout.addView(view, params); 

     final int filledRow = toRow + gridSize; 
     for (int j = toCol, count = toCol + gridSize; j < count; j++) { 
      mRowMap[j] = filledRow; 
     } 
    } 

    /** 
    * Find empty gap which starts from toCol 
    * [*********************] 
    * [******------*****----] here col = 6, size = 3 
    * [******------*****----] 
    * [******------*****----] 
    * [*****************----] 
    * @param toCol 
    * @return 
    */ 
    private int findGapSizeForCol(int toCol) { 
     final int fromRow = mRowMatrix[toCol]; 
     int i = toCol; 
     for (; i < mNumColumns; i++) { 
      if (fromRow != mRowMatrix[i]) { 
       break; 
      } 
     } 
     return i - toCol; 
    } 

    /** 
    * Find column with minimum filled row 
    * [*********************] 
    * [*****************----] here col = 17 
    * [******------*****----] 
    * [******------*****----] 
    * @return 
    */ 
    private int findColWithMinRow() { 
     int minRow = Integer.MAX_VALUE, minCol = 0; 
     for (int i = 0, count = mRowMatrix.length; i < count; i++) { 
      if (minRow > mRowMatrix[i]) { 
       minRow = mRowMatrix[i]; 
       minCol = i; 
      } 
     } 
     return minCol; 
    } 

    /** 
    * Find customView with appropriate size for the empty gap 
    */ 
    private CustomView findAppropriate(int size) { 
     for (int j = mUnplacedList.size() - 1; j >= 0; j--) { 
      if (mUnplacedList.get(j).getGridSize() <= size) { 
       return mUnplacedList.get(j); 
      } 
     } 
     return null; 
    } 

}