/* * MIT License * * Copyright (c) 2018 Alibaba Group * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.tmall.wireless.vaf.virtualview.layout; import android.util.Log; import android.view.View; import android.view.View.MeasureSpec; import com.libra.Utils; import com.libra.virtualview.common.StringBase; import com.tmall.wireless.vaf.framework.VafContext; import com.tmall.wireless.vaf.virtualview.Helper.RtlHelper; import com.tmall.wireless.vaf.virtualview.core.Layout; import com.tmall.wireless.vaf.virtualview.core.ViewBase; import com.tmall.wireless.vaf.virtualview.core.ViewCache; import com.tmall.wireless.vaf.virtualview.core.ViewCache.Item; import com.tmall.wireless.vaf.virtualview.layout.RatioLayout.Params; import static com.libra.virtualview.common.ViewBaseCommon.AUTO_DIM_DIR_X; import static com.libra.virtualview.common.ViewBaseCommon.AUTO_DIM_DIR_Y; /** * Created by gujicheng on 16/8/16. */ public class GridLayout extends Layout { final static private String TAG = "GridLayout_TMTEST"; protected int mColCount; protected int mItemWidth; protected int mItemHeight; protected int mItemHorizontalMargin = 0; protected int mItemVerticalMargin = 0; public GridLayout(VafContext context, ViewCache vc) { super(context, vc); mColCount = 1; mItemHeight = -1; } @Override public void onComMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mAutoDimDirection > 0) { switch (mAutoDimDirection) { case AUTO_DIM_DIR_X: if (View.MeasureSpec.EXACTLY == View.MeasureSpec.getMode(widthMeasureSpec)) { heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((int)((View.MeasureSpec.getSize(widthMeasureSpec) * mAutoDimY) / mAutoDimX), View.MeasureSpec.EXACTLY); } break; case AUTO_DIM_DIR_Y: if (View.MeasureSpec.EXACTLY == View.MeasureSpec.getMode(heightMeasureSpec)) { widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((int)((View.MeasureSpec.getSize(heightMeasureSpec) * mAutoDimX) / mAutoDimY), View.MeasureSpec.EXACTLY); } break; } } int width = View.MeasureSpec.getSize(widthMeasureSpec); int height = View.MeasureSpec.getSize(heightMeasureSpec); int widthMode = View.MeasureSpec.getMode(widthMeasureSpec); int heightMode = View.MeasureSpec.getMode(heightMeasureSpec); int space = mPaddingLeft + mPaddingRight + mItemHorizontalMargin * (mColCount - 1); mItemWidth = (width - space) / mColCount; for (int i = 0, size = mSubViews.size(); i < size; i++) { ViewBase child = mSubViews.get(i); if (child.isGone()) { continue; } if (mItemHeight > 0) { child.measureComponent(View.MeasureSpec.makeMeasureSpec(mItemWidth, MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(mItemHeight, MeasureSpec.EXACTLY)); } else { GridLayout.Params childParam = child.getComLayoutParams(); child.measureComponent(View.MeasureSpec.makeMeasureSpec(mItemWidth, MeasureSpec.EXACTLY), Layout.getChildMeasureSpec(heightMeasureSpec, mPaddingLeft + mPaddingRight + (mBorderWidth << 1) + childParam.mLayoutMarginLeft + childParam.mLayoutMarginRight, childParam.mLayoutHeight)); } } setComMeasuredDimension(getRealWidth(widthMode, width), getRealHeight(heightMode, height)); } private int getRealWidth(int mode, int size) { int ret = size; if (View.MeasureSpec.AT_MOST == mode) { int childrenWidth = 0; Params p = (Params) mParams; childrenWidth = mPaddingLeft + mPaddingRight; int count = 0; for (int i = 0, length = mSubViews.size(); i < length; i++) { ViewBase child = mSubViews.get(i); childrenWidth += child.getComMeasuredWidthWithMargin(); if (++count >= mColCount) { break; } else { childrenWidth += mItemHorizontalMargin; } } ret = Math.min(size, childrenWidth); } else if (View.MeasureSpec.EXACTLY == mode) { ret = size; } else { Log.e(TAG, "getRealWidth error mode:" + mode); } return ret; } private int getRealHeight(int mode, int size) { int ret = size; switch (mode) { case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: { int h = 0; if (mSubViews.size() > 0) { int count = mSubViews.size(); int row = count / mColCount + ((count % mColCount) > 0 ? 1 : 0); if (mItemHeight > 0) { h = row * mItemHeight + mPaddingTop + mPaddingBottom + (row - 1) * mItemVerticalMargin; } else { h = row * (mSubViews.get(0).getComMeasuredHeight()) + mPaddingTop + mPaddingBottom + (row - 1) * mItemVerticalMargin; } } if (View.MeasureSpec.AT_MOST == mode) { ret = Math.min(size, h); } else { ret = h; } break; } } return ret; } @Override public void onComLayout(boolean changed, int l, int t, int r, int b) { if (mSubViews.size() > 0) { Params p = (Params) mParams; int left = l + mPaddingLeft; int top = t + mPaddingTop; int count = mSubViews.size(); ViewBase c = mSubViews.get(0); int totalWidth = this.getComMeasuredWidth(); int itemWidth = c.getComMeasuredWidth(); int itemHeight = c.getComMeasuredHeight(); int rowCount = count / mColCount + ((count % mColCount) > 0 ? 1 : 0); int index = 0; //int padding = (totalWidth - itemWidth * mColCount) / (mColCount + 1); for (int row = 0; row < rowCount; ++row) { int ll = left; for (int col = 0; (col < mColCount) && (index < count); ++col) { ViewBase child = mSubViews.get(index++); if (child.isGone()) { continue; } int realLeft = RtlHelper.getRealLeft(isRtl(), l, getWidth(), ll, itemWidth); child.comLayout(realLeft, top, realLeft + itemWidth, top + itemHeight); ll += itemWidth + mItemHorizontalMargin; } if (mItemHeight > 0) { top += mItemHeight + mItemVerticalMargin; } else { top += itemHeight + mItemVerticalMargin; } } } } @Override protected boolean setAttribute(int key, float value) { boolean ret = super.setAttribute(key, value); if (!ret) { ret = true; switch (key) { case StringBase.STR_ID_itemHeight: mItemHeight = Utils.dp2px(Math.round(value)); break; case StringBase.STR_ID_itemHorizontalMargin: mItemHorizontalMargin = Utils.dp2px(value); break; case StringBase.STR_ID_itemVerticalMargin: mItemVerticalMargin = Utils.dp2px(value); break; default: ret = false; break; } } return ret; } @Override protected boolean setAttribute(int key, int value) { boolean ret = super.setAttribute(key, value); if (!ret) { ret = true; switch (key) { case StringBase.STR_ID_colCount: mColCount = value; break; case StringBase.STR_ID_itemHeight: mItemHeight = Utils.dp2px(value); break; case StringBase.STR_ID_itemHorizontalMargin: mItemHorizontalMargin = Utils.dp2px(value); break; case StringBase.STR_ID_itemVerticalMargin: mItemVerticalMargin = Utils.dp2px(value); break; default: ret = false; break; } } return ret; } @Override protected boolean setAttribute(int key, String value) { boolean ret = true; switch (key) { case StringBase.STR_ID_itemHorizontalMargin: mViewCache.put(this, StringBase.STR_ID_itemHorizontalMargin, value, Item.TYPE_FLOAT); break; case StringBase.STR_ID_itemVerticalMargin: mViewCache.put(this, StringBase.STR_ID_itemVerticalMargin, value, Item.TYPE_FLOAT); break; default: ret = super.setAttribute(key, value); break; } return ret; } @Override protected boolean setRPAttribute(int key, float value) { boolean ret = super.setRPAttribute(key, value); if (!ret) { ret = true; switch (key) { case StringBase.STR_ID_itemHeight: mItemHeight = Utils.rp2px(value); break; case StringBase.STR_ID_itemHorizontalMargin: mItemHorizontalMargin = Utils.rp2px(value); break; case StringBase.STR_ID_itemVerticalMargin: mItemVerticalMargin = Utils.rp2px(value); break; default: ret = false; break; } } return ret; } @Override protected boolean setRPAttribute(int key, int value) { boolean ret = super.setRPAttribute(key, value); if (!ret) { ret = true; switch (key) { case StringBase.STR_ID_itemHeight: mItemHeight = Utils.rp2px(value); break; case StringBase.STR_ID_itemHorizontalMargin: mItemHorizontalMargin = Utils.rp2px(value); break; case StringBase.STR_ID_itemVerticalMargin: mItemVerticalMargin = Utils.rp2px(value); break; default: ret = false; break; } } return ret; } public static class Builder implements ViewBase.IBuilder { @Override public ViewBase build(VafContext context, ViewCache vc) { return new GridLayout(context, vc); } } }