天天看點

仿淘寶京東商品規格屬性選擇的最簡單實作仿淘寶京東商品規格屬性選擇的最簡單實作

仿淘寶京東商品規格屬性選擇的最簡單實作

商城裡面的規格選擇,網上大部分是自定義控件實作的,顯得很是麻煩,而我的實作方式是大家最常用的控件RecyclerView,特點是性能好,簡單。廢話不多說,先看實作的效果圖:

仿淘寶京東商品規格屬性選擇的最簡單實作仿淘寶京東商品規格屬性選擇的最簡單實作

上圖效果的實作主要是 RecyclerView和flowlayout(流式布局).

RecyclerView設定最大高度

如圖規格多的時候,RecyclerView要有個最大高度,我們設定

android:maxHeight="300dp"

是沒有效果的,因為RecyclerView沒有maxHigh這個屬性,那怎麼實作這個效果呢?通過檢視源碼,

@Override
protected void onMeasure(int widthSpec, int heightSpec) {
...
if (mLayout.mAutoMeasure) {
    ...
    // now we can get the width and height from the children.
    mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);
    if (mLayout.shouldMeasureTwice()) {
        ...        
        // now we can get the width and height from the children.
        mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);
    }
} else {
  ...
}
}
           

當RecyclerView的LayoutManager#isAutoMeasureEnabled()傳回true時,RecyclerView高度取決于children view的布局高度,并非取決于RecyclerView自身的測量高度。

下面是setMeasuredDimensionFromChildren(int widthSpec, int heightSpec)源碼
void setMeasuredDimensionFromChildren(int widthSpec, int heightSpec) {
final int count = getChildCount();
if (count == 0) {
    mRecyclerView.defaultOnMeasure(widthSpec, heightSpec);
    return;
}
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for (int i = 0; i < count; i++) {
    View child = getChildAt(i);
    final Rect bounds = mRecyclerView.mTempRect;
    getDecoratedBoundsWithMargins(child, bounds);
    if (bounds.left < minX) {
        minX = bounds.left;
    }
    if (bounds.right > maxX) {
        maxX = bounds.right;
    }
    if (bounds.top < minY) {
        minY = bounds.top;
    }
    if (bounds.bottom > maxY) {
        maxY = bounds.bottom;
    }
}
mRecyclerView.mTempRect.set(minX, minY, maxX, maxY);
setMeasuredDimension(mRecyclerView.mTempRect, widthSpec, heightSpec);
}
           

該方法計算了RecyclerView目前所有Child View的布局範圍mRecyclerView.mTempRect,最後調用了public void setMeasuredDimension(Rect childrenBounds, int wSpec, int hSpec),并将得出的布局範圍mRecyclerView.mTempRect、RecyclerView的測量參數widthSpec、heightSpec作為參數傳入,以此來決定RecyclerView最終寬高值。

最終解決方法

是以,我們隻需要重寫LayoutManager的public void setMeasuredDimension(Rect childrenBounds, int wSpec, int hSpec)方法即可為RecyclerView設定最大寬高。

` @Override
public void setMeasuredDimension(Rect childrenBounds, int wSpec, int hSpec) {
    super.setMeasuredDimension(childrenBounds, wSpec, View.MeasureSpec.makeMeasureSpec(DeviceUtil.dp2px(mContext,246), AT_MOST));
}`
           
屬性的标簽實作

标簽的實作用的是flowlayout,用法很簡單,這裡就不在描述了。

至此,如圖的效果就實作了,還有不懂的可看demo代碼。

檢視源碼

繼續閱讀