How do I implement background scrolling with a gridview? If it sounds vague, I mean like implementing a bookshelf using a gridview where the shelf image is attached to an item in the gridview.
Asked
Active
Viewed 2.2k times
3 Answers
4
It took me forever to figure this out, so for everybody trying to do this, here's the code from my e-book reader.
It's based on Shelves by Romain Guy so he deserves the credit for the original code.
package net.nightwhistler.pageturner.view;
import net.nightwhistler.pageturner.R;
import net.nightwhistler.pageturner.library.LibraryBook;
import net.nightwhistler.pageturner.library.QueryResult;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.GridView;
public class BookCaseView extends GridView {
private Bitmap background;
private int mShelfWidth;
private int mShelfHeight;
private QueryResult<LibraryBook> result;
private LibraryBook selectedBook;
public BookCaseView(Context context, AttributeSet attributes) {
super(context, attributes);
this.setFocusableInTouchMode(true);
this.setClickable(false);
final Bitmap shelfBackground = BitmapFactory.decodeResource(context.getResources(),
R.drawable.shelf_single);
setBackground(shelfBackground);
this.setFocusable(true);
}
public void setBackground(Bitmap background) {
this.background = background;
mShelfWidth = background.getWidth();
mShelfHeight = background.getHeight();
}
protected void onClick( int bookIndex ) {
LibraryBook book = this.result.getItemAt(bookIndex);
this.selectedBook = book;
invalidate();
}
@Override
protected void dispatchDraw(Canvas canvas) {
final int count = getChildCount();
final int top = count > 0 ? getChildAt(0).getTop() : 0;
final int shelfWidth = mShelfWidth;
final int shelfHeight = mShelfHeight;
final int width = getWidth();
final int height = getHeight();
final Bitmap background = this.background;
for (int x = 0; x < width; x += shelfWidth) {
for (int y = top; y < height; y += shelfHeight) {
canvas.drawBitmap(background, x, y, null);
}
//This draws the top pixels of the shelf above the current one
Rect source = new Rect(0, mShelfHeight - top, mShelfWidth, mShelfHeight);
Rect dest = new Rect(x, 0, x + mShelfWidth, top );
canvas.drawBitmap(background, source, dest, null);
}
super.dispatchDraw(canvas);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ( keyCode == KeyEvent.KEYCODE_BACK && this.selectedBook != null ) {
this.selectedBook = null;
invalidate();
return true;
}
return false;
}
}

NightWhistler
- 326
- 2
- 7
-
In this solution, it think that the shelf is attached to a single item. May this cause some issues when trying to paint a shelf below all the items without any spacing? Or perhaps when having a single item on a shelf? – AlikElzin-kilaka Oct 29 '12 at 13:15
-
No, it paints the shelf independant of how many items you draw in front of it. All it does is paint the background in such a way that it scrolls properly. – NightWhistler Jan 24 '13 at 10:00
-
Please tell me what is the use of the following code: //This draws the top pixels of the shelf above the current one Rect source = new Rect(0, mShelfHeight - top, mShelfWidth, mShelfHeight); Rect dest = new Rect(x, 0, x + mShelfWidth, top ); canvas.drawBitmap(background, source, dest, null); coz even if i remove it the view isn't getting affected.. – Snehal Poyrekar Mar 11 '13 at 06:25
-
Without that code, when you scroll you'll sometimes have a small strip of empty space at the top of the screen, since the top row starts a few pixels under the top of the view, but the row before it isn't shown yet. – NightWhistler Mar 27 '13 at 14:48
1
What I did was to split my background image in n gridview columns and in my gridview getView method add the view background according to the position in the grid. It worked perfectly.
If you want the code just ask.

Moisés Olmedo
- 919
- 1
- 17
- 15
-
layout.setBackground(context.getResources().getDrawable(R.drawable.shelf_panel)); for item you are telling or gridview.setBackground(getResources().getDrawable(R.drawable.bookshelf_empty)); is that possible to share the code?? – LOG_TAG Mar 14 '13 at 11:27
-1
My previous answer only adds the background but doesn't let it scroll with the items. what you wan is NightWhistler's answer :) Sorry for misinterpreting the question.

DallaRosa
- 5,737
- 2
- 35
- 53
-
I was thinking of using that, but the problem will be the number of items that will be displayed. If I only have 4 books and the number of columns per row is only three, there will be 2 items in the second row that will not have the background, making it look weird. – louieansonng Jul 18 '11 at 18:05
-
3I don't think it works, the background doesn't scroll with the images – louieansonng Jul 19 '11 at 07:28
-
I also tried above solution & I'm able to draw to separator between rows in GridView, however when I scroll the gridView, only item items get scrolled not the separator.How to scroll items with separator like listView.? – sachin003 Apr 03 '13 at 12:24