1

I'm new to Android and I'm trying to do the following task on my school project:

I have a grid view of movies which the user can scroll endlessly. When the app starts I fetch the first 20 movies and each time the user scrolls to the bottom of the grid I execute an AsyncTask to fetch 20 more movies and add them to the Adapter.

When the user clicks on a movie he goes to a new child activity to see the movie details.

I'm having troubles maintaining the GridView's scroll position in the following cases:

  1. When the user goes to the details activity and returns to the main activity of the movies.
  2. When the user changes the device orientation.

And when dealing with theses 2 cases I also need to take in consideration that maybe the user scrolled a lot and had 100 movies in the adapter and when he goes back the activity start from the start with only the first 20 movies, so I would be able to scroll to his last position.

Can someone please tell me how can I give the best user experience in my project by not losing the user's scroll position at any case?

Liran Friedman
  • 4,027
  • 13
  • 53
  • 96

2 Answers2

1

I don't know if this is the best practice, but in my case it is. I decided to set my adapter as a global static variable, in this way I maintain the amount of data loaded via the API, and I don't need to perform a request for every time the user moves between activities. For maintaining the scroll position I used the onItemClickListener when moving to the details activity and the savedInstanceState when changing orientation.

Here is my code for that:

//Static variables
private static MoviesAdapter mMoviesAdapter;
private static int mGridViewPosition = 0;

//Call this method when user clicks the back button
public static void ClearStaticData(){
    mMoviesAdapter.clear();
    mMoviesAdapter = null;
}

@Override
public void onSaveInstanceState(Bundle outState) {
    int index = mGridView.getFirstVisiblePosition();
    outState.putInt(GRID_VIEW_POSITION, index);
    super.onSaveInstanceState(outState);
}

@Override
public View onCreateView(...) {
    if (mMoviesAdapter == null) {
        mMoviesAdapter = new MoviesAdapter(...);
    } else {
        RestoreGridPosition();
    }
}

private void RestoreGridPosition(){
    if(mGridViewPosition > 0 && mMoviesAdapter.getCount() >= mGridViewPosition)
        mGridView.setSelection(mGridViewPosition);
}

Since I fill my adapter via API call, I think this is probably the best solution to save the data and not to perform requests every time.

Ivar
  • 6,138
  • 12
  • 49
  • 61
Liran Friedman
  • 4,027
  • 13
  • 53
  • 96
0
  1. Try not finishing mainActivity once a gridItem is clicked so when user navigates back to mainActivity (from detailsActivity) he will have all the data that was there before.

  2. You can handle this situation with activity's lifecycle callbacks:

You can get currently visible GridView item's position like this:

int mCurrentPosition = gridview.getFirstVisiblePosition(); 

When an orientation change is occurring the activity is recreated and going through the following stages:

onSaveInstanceState
onRestoreInstanceState

You can then save the position before orientation change is happening and get it back when its being restored.

Save Your Activity State

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current scroll state
savedInstanceState.putInt(STATE_POSITION, mCurrentPosition);

// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}

Restore Your Activity State

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    mCurrentPosition = savedInstanceState.getInt(STATE_POSITION);
}

Here once you have the previous position you can move to the desired position in the gridView:

gridview.smoothScrollToPosition(int mCurrentPosition)

This is taken from android docs: Recreating an Activity
Scrolling gridView to position GridView scrolling stackoverflow

Community
  • 1
  • 1
  • Thank you for your answer. can you please tell me how do I 1. "not finishing mainActivity once a gridItem is clicked"? 2. The `gridview.getFirstVisiblePosition();` sometimes brings the position of a half scrolled item, and it doesn't work so well... – Liran Friedman Nov 03 '15 at 11:37
  • Since I'm using a fragment, I don't seem to have the `onRestoreInstanceState` event. – Liran Friedman Nov 04 '15 at 04:21
  • You're right. Check the following [stackoverflow question](http://stackoverflow.com/questions/5412746/android-fragment-onrestoreinstancestate) – Evgeny Maltsev Nov 04 '15 at 08:12
  • You're right. Check the following [stackoverflow question](http://stackoverflow.com/questions/5412746/android-fragment-onrestoreinstancestate). About not finishing the activity - if you start `DetailsActivity` without calling `MainActivity.finish()` than it should be in the back-stack and when user navigates back he should be returned to the previous state. – Evgeny Maltsev Nov 04 '15 at 08:25