Custom Grid View with Row span and Column span

2019-02-17 16:21发布

问题:

i am trying to implement a grid view which has the Graphical view as follows. I have gone through various blogs and S.O questions, and unfortunately i am not able to provide a row and column span to one particular grid item and grid view also does not support this feature. And i don't want to create Dynamic Scroll View with other views in between as the there is a lot of data and it causes performance issues. So if any one have any suggestions. Please reply . Thanks in advance.

回答1:

Do you intend to repeat the pattern for your scrollable view? To be more clear, does your Grid item with large span repeat at regular intervals?

One option would be to use a list view and implement your large span view with two normal views as one row of the list view with a tag such as "special_row" and implement regular views as another row with tag like "normal row". Based on the requirement you can recycle the rows by accessing the row tags.

EDIT:

I found a library that implements pinterest like UI for android. This has a symmetric views in it. Checkout PinterestLisView.

EDIT:

Here is another interesting technique by specifying coulmn span and row spans for the grid items. I took from this question. I guess you can do away with the static xml declaration of grid items by programmatically specifying column and row spans.



回答2:

Here's the solution to all your problems: https://github.com/felipecsl/AsymmetricGridView Yeah, I got tired of Android not having a class like this and wrote it myself. Hope it is useful for you.



回答3:

This is a particular solution for 3 column grids with featured items that span 2x2 grids.

public class GridAdapter extends ArrayAdapter<GridAdapter.GridItem> {
    public GridAdapter(Context context, int itemViewResId, List<String> things) {
        super(context, itemViewResId, buildGridItems(things));
    }

    /**
     * Assumes 3 column layout. A list of indices that shows a large
     * item on the right of 1st row, then alternating on every 3rd row 
     * to the left and then right. The large item should occupy a 2x2 grid.
     *
     *   X O O
     *   X O O
     *   X X X
     *   X X X
     *   O O X
     *   O O X
     *   X X X
     *   X X X
     *   X O O
     *   X O O
     *   X X X
     *
     * The indices where the large featured items are in item list is 
     * 1, 9, 19, 27, 37, 45, 55, ...         
     */
    protected static List<Integer> getFeaturedIndex(int total) {
        int pos = 1;
        ArrayList<Integer> index = new ArrayList<Integer>();
        if (pos + 1 < total) {
            index.add(pos);
        }
        for (int i = 0; pos < total; i++) {
            int inc = i % 2 == 0 ? 8 : 10;
            pos += inc;
            if (pos + 1 < total) {
                index.add(pos);
            }
        }
        return index;
    }

    protected static List<GridItem> buildGridItems(List<String> things) {
        ArrayList<GridItem> items = new ArrayList<GridItem>();
        List<Integer> featuredIndex = getFeaturedIndex(things.size());
        ArrayList<GridItem> featured = new ArrayList<GridItem>();
        for (int i = 0, k = things.size(); i < k; i++) {
            GridItem item = new GridItem(things.get(i));
            if (featuredIndex.contains(i)) {
                item.feature = true;
                featured.add(item);
            }
            items.add(item);
        }
        for (GridItem feature : featured) {
            int index = items.indexOf(feature);
            GridItem shim = new GridItem(feature.getModel());
            shim.shim = true;
            items.add(index + 1, shim);
            items.add(index + 3, shim);
            items.add(index + 4, shim);
        }
        return items;
    }

    @Override
    public int getItemViewType(int position) {
        return getItem(position).shim ? 0 : 1;
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = new View(getContext());
        }
        GridItem item = getItem(position);
        if (item.feature) {
            convertView.setLayoutParams(new LayoutParams(400,300));
        } else {
            convertView.setLayoutParams(new LayoutParams(200,150));
        }
        if (item.shim) {
            convertView.setVisibility(View.GONE);
        }
        return convertView;
    }

    public static class GridItem {
        private String mItem;
        private boolean shim = false;
        private boolean feature = false;

        public GridItem(String item) {
            mItem = item;
        }
    }
}

The idea is to wrap the item list with GridItem with a feature and shim flags that determine how the views should behave.

The method getFeaturedIndex() calculates which items in the original list should be featured. Then in the buildGridItems() we take 2 steps. First, flag all the items that are featured (and keep a list of these items). Afterwards, for each of these featured items, add 3 shims (+1, +3 and +4) relative to the featured item.

In the getView() for featured items, we set the appropriate dimensions as 2x2 of the normal items. For shim items, set the visibility to GONE.