PinnedHeader Google plus GridView?

前端 未结 1 1216
一整个雨季
一整个雨季 2021-01-26 11:30

Background

Google plus (google+) app has a nice viewing of images on the \"highlights\" category.

For each section on this screen, they made a header that cont

相关标签:
1条回答
  • 2021-01-26 12:21

    since i can't find any other solution, i've decided to make my own solution (code based on another code i've made, here)

    it's used on a ListView instead, but it works quite well. you just set the adapter on the listView and you are good to go. you can set exactly how the headers look like and how each cell look like.

    it works by having 2 types of rows: header-rows and cells-rows .

    it's not the best solution, since it creates extra views instead of having the ListView/GridView (or whatever you use) put the cells correctly, but it works fine and it doesn't crash

    it also doesn't have items clicking (since it's for listView), but it shouldn't be hard to add for whoever uses this code.

    sadly it also doesn't have the header as a pinned header, but maybe it's possible to be used with this library (PinnedHeaderListView) .

    here's the code :

    public abstract class HeaderGridedListViewAdapter<SectionData, ItemType> extends BaseAdapter {
        private static final int TYPE_HEADER_ROW = 0;
        private static final int TYPE_CELLS_ROW = 1;
        private final int mNumColumns;
        private final List<Row<SectionData, ItemType>> mRows = new ArrayList<Row<SectionData, ItemType>>();
        private final int mCellsRowHeight;
        private final Context mContext;
    
        public HeaderGridedListViewAdapter(final Context context, final List<Section<SectionData, ItemType>> sections,
                final int numColumns, final int cellsRowHeight) {
            this.mContext = context;
            this.mNumColumns = numColumns;
            this.mCellsRowHeight = cellsRowHeight;
            for (final Section<SectionData, ItemType> section : sections) {
                // add header
                Row<SectionData, ItemType> row = new Row<SectionData, ItemType>();
                row.section = section;
                row.type = TYPE_HEADER_ROW;
                mRows.add(row);
                int startIndex = 0;
                // add section rows
                for (int cellsLeft = section.getItemsCount(); cellsLeft > 0;) {
                    row = new Row<SectionData, ItemType>();
                    row.section = section;
                    row.startIndex = startIndex;
                    row.type = TYPE_CELLS_ROW;
                    cellsLeft -= Math.min(mNumColumns, cellsLeft);
                    startIndex += mNumColumns;
                    mRows.add(row);
                }
            }
        }
    
        @Override
        public int getViewTypeCount() {
            return 2;
        }
    
        @Override
        public int getItemViewType(final int position) {
            return getItem(position).type;
        }
    
        @Override
        public int getCount() {
            return mRows.size();
        }
    
        @Override
        public Row<SectionData, ItemType> getItem(final int position) {
            return mRows.get(position);
        }
    
        @Override
        public long getItemId(final int position) {
            return position;
        }
    
        @Override
        public View getView(final int position, final View convertView, final ViewGroup parent) {
            final Row<SectionData, ItemType> item = getItem(position);
            switch (item.type) {
            case TYPE_CELLS_ROW:
                LinearLayout rowLayout = (LinearLayout) convertView;
                if (rowLayout == null) {
                    rowLayout = new LinearLayout(mContext);
                    rowLayout.setOrientation(LinearLayout.HORIZONTAL);
                    rowLayout.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, mCellsRowHeight));
                    rowLayout.setWeightSum(mNumColumns);
                }
                final int childCount = rowLayout.getChildCount();
                // reuse previous views of the row if possible
                for (int i = 0; i < mNumColumns; ++i) {
                    // reuse old views if possible
                    final View cellConvertView = i < childCount ? rowLayout.getChildAt(i) : null;
                    // fill cell with data
                    final View cellView = getCellView(item.section, item.startIndex + i, cellConvertView, rowLayout);
    
                    LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) cellView.getLayoutParams();
                    if (layoutParams == null) {
                        layoutParams = new LinearLayout.LayoutParams(0, mCellsRowHeight, 1);
                        cellView.setLayoutParams(layoutParams);
                    } else {
                        final boolean needSetting = layoutParams.weight != 1 || layoutParams.width != 0
                                || layoutParams.height != mCellsRowHeight;
                        if (needSetting) {
                            layoutParams.width = 0;
                            layoutParams.height = mCellsRowHeight;
                            layoutParams.weight = 1;
                            cellView.setLayoutParams(layoutParams);
                        }
                    }
                    if (cellConvertView == null)
                        rowLayout.addView(cellView);
                }
                return rowLayout;
            case TYPE_HEADER_ROW:
                return getHeaderView(item.section, convertView, parent);
            }
            throw new UnsupportedOperationException("cannot create this type of row view");
        }
    
        @Override
        public boolean areAllItemsEnabled() {
            return false;
        }
    
        @Override
        public boolean isEnabled(final int position) {
            return false;
        }
    
        /** should handle getting a single header view */
        public abstract View getHeaderView(Section<SectionData, ItemType> section, View convertView, ViewGroup parent);
    
        /**
         * should handle getting a single cell view. <br/>
         * NOTE:read the parameters description carefully !
         * 
         * @param section
         *            the section that this cell belongs to
         * @param positionWithinSection
         *            the position within the section that we need to fill the data with. note that if it's larger than what
         *            the section can give you, it means we need an empty cell (same the the others, but shouldn't show
         *            anything, can be invisible if you wish)
         * @param convertView
         *            a recycled row cell. you must use it when it's not null, and fill it with data
         * @param parent
         *            the parent of the view. you should use it for inflating the view (but don't attach the view to the
         *            parent)
         */
        public abstract View getCellView(Section<SectionData, ItemType> section, int positionWithinSection,
                View convertView, ViewGroup parent);
    
        // ////////////////////////////////////
        // Section//
        // /////////
        public static class Section<SectionData, ItemType> {
            private final List<ItemType> mItems;
            private final SectionData mSectionData;
    
            public Section(final SectionData sectionData, final List<ItemType> items) {
                this.mSectionData = sectionData;
                this.mItems = items;
            }
    
            public SectionData getSectionData() {
                return mSectionData;
            }
    
            public int getItemsCount() {
                return mItems.size();
            }
    
            public ItemType getItem(final int posInSection) {
                return mItems.get(posInSection);
            }
    
            @Override
            public String toString() {
                return mSectionData;
            }
        }
    
        // ////////////////////////////////////
        // Row//
        // /////
        private static class Row<SectionData, ItemType> {
            int type, startIndex;
            Section<SectionData, ItemType> section;
        }
    }
    
    0 讨论(0)
提交回复
热议问题