-1

I want to save a user's ScrollView position after they've left the View.

I'm doing this by trying to capture to position of getScrollY inside onPause and save it to a database, then retrieve it when the user returns.

I can successfully add and retrieve the position (Log.i("scrolly", Integer.toString(scrollY)) returns as expected), but the ScrollView isn't jumping to the right position.

Part of StoryBodyActivity:

public class StoryBodyActivity extends AppCompatActivity {

    private TextView storyBodyTextView;
    private ScrollView storyBodyScrollView;
    public int storyID;
    Parcelable state;
    int scrollY;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_story_body, menu);
        return true;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_story_body);

        Bundle extras = getIntent().getExtras();

        String story = extras.getString("story");
        storyID = extras.getInt("story_id");
        Log.i("stories", Integer.toString(storyID));

        storyBodyTextView = (TextView) findViewById(R.id.story_body_text_view);
        storyBodyScrollView = (ScrollView) findViewById(R.id.story_body_scroll_view);

        DatabaseHelper db = new DatabaseHelper(this);
        scrollY = db.getScrollPosition(storyID);
        Log.i("scrolly", Integer.toString(scrollY));

        storyBodyScrollView.scrollTo(0, scrollY);

        String storyBody = db.getStoryBody(storyID);

        storyBodyTextView.setText(Html.fromHtml(storyBody));

        if(state != null) {
            Log.d("pause", "trying to restore textview state..");
            storyBodyTextView.onRestoreInstanceState(state);
        }

        int scroll = storyBodyScrollView.getScrollY();
        Log.i("scroll", Integer.toString(scroll));

    }

    @Override
    public void onPause() {

        scrollY = storyBodyScrollView.getScrollY();
        Log.i("scroll", Integer.toString(scrollY));
        Log.i("insert", Integer.toString(storyID));
        DatabaseHelper db = new DatabaseHelper(this);
        db.setScrollPosition(scrollY, storyID);
        super.onPause();
    }

}

Part of my DatabaseHelper:

public class DatabaseHelper extends SQLiteAssetHelper {

    private static final int DATABASE_VERSION = 1;

    private static final String DATABASE_NAME = "database9.db";
    private static final String BOOKS = "books";
    private static final String AUTHORS = "authors";

    public DatabaseHelper (Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        setForcedUpgrade();
    }

    public int setScrollPosition(int scrollY, int storyID) {

        String insertQuery = "UPDATE " + BOOKS + " SET scroll_position = '" + scrollY + "' WHERE id = '" + storyID + "'";
        Log.i("insert", insertQuery);
        SQLiteDatabase db = this.getWritableDatabase();
        db.execSQL(insertQuery);

        return 0;

    }

    public int getScrollPosition(int storyID) {

        int scrollPosition = 0;

        String selectQuery = "SELECT scroll_position FROM " + BOOKS + " WHERE id = '" + storyID + "'";

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                scrollPosition = cursor.getInt(0);
            } while (cursor.moveToNext());
        }

        return scrollPosition;

       }
}

UPDATE:

My schema:

    CREATE TABLE "books" (
`id` INTEGER NOT NULL,
`title` TEXT,
`author_id` INTEGER,
`collection` TEXT,
`body` TEXT,
`scroll_position` INTEGER,
PRIMARY KEY(`id`) )
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Sebastian
  • 3,548
  • 18
  • 60
  • 95

1 Answers1

0

In your INSERT command, you are passing a string as the id, whereas it expects an integer.

String insertQuery = "UPDATE " + BOOKS + " SET scroll_position = '" + scrollY + "' WHERE id = '" + storyID + "'";

You see? storyID is passed as a string ("' WHERE id = '" + storyID + "'")!!
Single quotes mark the id as a string.

If you create an integer column, it will never match a string.

CREATE TABLE "books" (
`id` INTEGER NOT NULL,
`title` TEXT,
`author_id` INTEGER,
`collection` TEXT,
`body` TEXT,
`scroll_position` INTEGER,
PRIMARY KEY(`id`) )

The id field is created as an integer (which is good).
But you can't then pass it a string in your commands (nor in your queries).

EDIT

You are also passing a string to the scroll_position field.
Which is an integer. And this also won't work.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • Thanks - I've removed the single quotes, but I'm having the same issue – Sebastian Nov 10 '17 at 22:33
  • So, there is no match with the passed id. Make sure that the passed id exists in the table. Be mindful that a ListView selected index doesn't necessarily match your table row ids. – Phantômaxx Nov 10 '17 at 22:34
  • The passed `id` does, but when I view the table in a database browser, there are no values for `scroll_position` despite my code successfully logging the output of `scrollY` – Sebastian Nov 10 '17 at 22:37
  • If you remove the WHERE condition, all the rows will be updated. Try - just for testing. This means that there is no match on the id field. – Phantômaxx Nov 10 '17 at 22:39
  • Nope, afraid the problem persists – Sebastian Nov 10 '17 at 22:42
  • You are also passing a **string** to the `scroll_position` field. Which is an **integer**. And this also won't work. – Phantômaxx Nov 10 '17 at 22:47
  • I fixed the `scroll_position` single quotes too. Same problem - not seeing the field update in my database browser. Could it be to do with the fact that I'm shipping with a preloaded database? – Sebastian Nov 10 '17 at 22:48
  • If you use a preloaded database, everything changes. You have to first copy the database to the default app database location - And the CREATE TABLE has no meaning anymore, because it won't be executed, being replaced by the "copy database" method you will use. – Phantômaxx Nov 10 '17 at 22:50
  • But I don't see the copy database method in your code. Aren't you mixing between regular and prefilled database? The methods are mutually exclusive. I suspect you're writing to a regular database, but looking into another one (so, not seeing the updates written to the regular one). and writing. I mean, you have a prefilled database in your `assets` folder. But you are creating and writing another database in the regular app database path (`/data/data/yourpackage/your.db`). Then you check the database in the `assets` folder (which is read-only at run time). And see no updates. – Phantômaxx Nov 10 '17 at 23:00
  • Yes, I have a prefilled database in my `assets` folder, but that's the one I'm hoping to write to, too. I can see two databases - one in `assets` and the other in `debug`. – Sebastian Nov 10 '17 at 23:04
  • The one in `assets` **can't be written** by any means. It must be copied to the regular app database path first. The CREATE TABLE command becomes then useless (the table is already in the database). – Phantômaxx Nov 10 '17 at 23:05
  • Right, so do I need to do that in `onCreate()`? Which folder do I copy it to? – Sebastian Nov 10 '17 at 23:06
  • Please refer to [this](https://stackoverflow.com/questions/21101515/getting-a-prepopulated-database-located-in-the-assets-folder-into-the-data-data). – Phantômaxx Nov 10 '17 at 23:11