GridView的行重叠:如何让行高度契合最高的项目吗?高度、最高、项目、GridView

由网友(爱那么短,遗忘那么长)分享简介:如这previous人,我的GridView项之间不必要的重叠:Like this previous person, I have unwanted overlap between GridView items:注意的文字,除了在最右边的每一列。Notice the text, in every column ex...

如这previous人,我的GridView项之间不必要的重叠:

Like this previous person, I have unwanted overlap between GridView items:

注意的文字,除了在最右边的每一列。

Notice the text, in every column except the rightmost one.

我在哪里从previous问题不同的是,我不想要一个恒定的行高。我想行高度改变为容纳的最高含量每一行中,为有效利用屏幕空间。

Where I differ from that previous question is that I don't want a constant row height. I want the row height to vary to accommodate the tallest content in each row, for efficient use of screen space.

纵观source为GridView控件(不是权威的副本,但kernel.org仍是下跌),我们可以在fillDown()和makeRow()看到,看到的最后一个视图是参考视图:该行的高度从设置该视图的高度,而不是从最高的之一。 这就解释了为什么最右边一列就可以了。不幸的是,GridView中没有得到很好的建立为我所继承的解​​决这个问题。所有相关的领域和方法都是私有的。

Looking at the source for GridView (not the authoritative copy, but kernel.org is still down), we can see in fillDown() and makeRow() that the last View seen is the "reference view": the row's height is set from the height of that View, not from the tallest one. This explains why the rightmost column is ok. Unfortunately, GridView is not well set-up for me to fix this by inheritance. All the relevant fields and methods are private.

所以,在我走的陈腐bloaty路径克隆自己,有一招,我在这里失踪?我可以用一个TableLayout,但这需要我实施为numColumns =auto_fit自己(因为我想如只是一长列在电话屏幕上),而且它也不会是一个AdapterView,它这种感觉就像它应该是。

So, before I take the well-worn bloaty path of "clone and own", is there a trick I'm missing here? I could use a TableLayout, but that would require me to implement numColumns="auto_fit" myself (since I want e.g. just one long column on a phone screen), and it also wouldn't be an AdapterView, which this feels like it ought to be.

编辑:其实,克隆和自己是不实际的在这里。 GridView控件取决于其父母和兄弟姐妹类人迹罕至的地区,并会导致进口至少6000行code(AbsListView,适配器视图,等等。)

in fact, clone and own is not practical here. GridView depends on inaccessible parts of its parent and sibling classes, and would result in importing at least 6000 lines of code (AbsListView, AdapterView, etc.)

推荐答案

我用一个静态数组来驱动的最大高度为行。这是不完美的,因为早先的列将不会被调整,直到该单元被重新显示。这里是code的膨胀可重复使用的内容视图。

I used a static array to drive max heights for the row. This is not perfect since the earlier columns will not be resized until the cell is redisplayed. Here is the code for the inflated reusable content view.

修改:我正确地得到这个工作,但我不得不pre-措施,所有的细胞呈​​现之前。我通过继承GridView和在onLayout方法增加了测量钩这样做。

Edit: I got this work correctly but I had pre-measure all cells before rendering. I did this by subclassing GridView and adding a measuring hook in the onLayout method.

/**
 * Custom view group that shares a common max height
 * @author Chase Colburn
 */
public class GridViewItemLayout extends LinearLayout {

    // Array of max cell heights for each row
    private static int[] mMaxRowHeight;

    // The number of columns in the grid view
    private static int mNumColumns;

    // The position of the view cell
    private int mPosition;

    // Public constructor
    public GridViewItemLayout(Context context) {
        super(context);
    }

    // Public constructor
    public GridViewItemLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * Set the position of the view cell
     * @param position
     */
    public void setPosition(int position) {
        mPosition = position;
    }

    /**
     * Set the number of columns and item count in order to accurately store the
     * max height for each row. This must be called whenever there is a change to the layout
     * or content data.
     * 
     * @param numColumns
     * @param itemCount
     */
    public static void initItemLayout(int numColumns, int itemCount) {
        mNumColumns = numColumns;
        mMaxRowHeight = new int[itemCount];
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // Do not calculate max height if column count is only one
        if(mNumColumns <= 1 || mMaxRowHeight == null) {
            return;
        }

        // Get the current view cell index for the grid row
        int rowIndex = mPosition / mNumColumns;
        // Get the measured height for this layout
        int measuredHeight = getMeasuredHeight();
        // If the current height is larger than previous measurements, update the array
        if(measuredHeight > mMaxRowHeight[rowIndex]) {
            mMaxRowHeight[rowIndex] = measuredHeight;
        }
        // Update the dimensions of the layout to reflect the max height
        setMeasuredDimension(getMeasuredWidth(), mMaxRowHeight[rowIndex]);
    }
}

下面是我的BaseAdapter子类的测量功能。请注意,我有一个方法 updateItemDisplay ,设置视图上的细胞中所有相应的文字和图片。

Here is the measuring function in my BaseAdapter subclass. Note that I have a method updateItemDisplay that sets all appropriate text and images on the view cell.

    /**
     * Run a pass through each item and force a measure to determine the max height for each row
     */
    public void measureItems(int columnWidth) {
        // Obtain system inflater
        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        // Inflate temp layout object for measuring
        GridViewItemLayout itemView = (GridViewItemLayout)inflater.inflate(R.layout.list_confirm_item, null);

        // Create measuring specs
        int widthMeasureSpec = MeasureSpec.makeMeasureSpec(columnWidth, MeasureSpec.EXACTLY);
        int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);

        // Loop through each data object
        for(int index = 0; index < mItems.size(); index++) {
            String[] item = mItems.get(index);

            // Set position and data
            itemView.setPosition(index);
            itemView.updateItemDisplay(item, mLanguage);

            // Force measuring
            itemView.requestLayout();
            itemView.measure(widthMeasureSpec, heightMeasureSpec);
        }
    }

最后,这里是GridView控件的子类设置测量视图细​​胞布局过程:

And finally, here is the GridView subclass set up to measure view cells during layout:

/**
 * Custom subclass of grid view to measure all view cells
 * in order to determine the max height of the row
 * 
 * @author Chase Colburn
 */
public class AutoMeasureGridView extends GridView {

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

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

    public AutoMeasureGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if(changed) {
            CustomAdapter adapter = (CustomAdapter)getAdapter();

            int numColumns = getContext().getResources().getInteger(R.integer.list_num_columns);
            GridViewItemLayout.initItemLayout(numColumns, adapter.getCount());

            if(numColumns > 1) {
                int columnWidth = getMeasuredWidth() / numColumns;
                adapter.measureItems(columnWidth);
            }
        }
        super.onLayout(changed, l, t, r, b);
    }
}

我之所以有列数作为一种资源,使基于方向等我可以有不同数量的

The reason I have the number of columns as a resource is so that I can have a different number based on orientation, etc.

阅读全文

相关推荐

最新文章