This is what ended-up working. It uses the pattern found in screen-slide example from developer.android.com/training, with one difference: in ThingSlideActivity.getItem()
, instead of running ThingSlideFragment.onCreate(pos)
, I used ThingSlideFragment.newInstance(pos)
. Also, I added static Cursor getCursor()
which made available the original Cursor
that populated the ListActivity
in the first place. This allowed me to translate from the position within the list to the database key. If there are any faults with this pattern, please advise.
The initial activity This activity has a list from the database and a cursor left open until the list is destroyed :
public class ThingListActivity extends ListActivity {
private SQLiteDatabase db;
private static Cursor cursor;
static Cursor getCursor() {
return cursor;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView listThings = getListView();
int position = getIntent().getIntExtra("POSITION", 0);
try {
SQLiteOpenHelper tableDatabaseHelper = new TableDatabaseHelper(this);
db = tableDatabaseHelper.getReadableDatabase();
cursor = db.query("TABLE", pullFields, selectionFields, selectionArgs, null, null, null); // you define your own query
if (cursor.moveToFirst()) {
listThings.setAdapter(new ResourceCursorAdapter(this, R.layout.my_simple_expandable_list_item_2, cursor) { //built-in layout
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tvFirst = (TextView)view.findViewById(android.R.id.text1);
TextView tvSecond = (TextView)view.findViewById(android.R.id.text2);
tvFirst.setText(cursor.getString(1) + " - " + getPctString(cursor.getString(2)));
tvSecond.setText(cursor.getString(3));
}
});
} else {
Toast toast = Toast.makeText(this, "The list was empty.", Toast.LENGTH_SHORT);
toast.show();
}
} catch (SQLiteException e) {
Toast toast = Toast.makeText(this, "Database Unavailable", Toast.LENGTH_SHORT);
toast.show();
} finally {
//Not closing cursor. Will do in onDestroy()
}
}
@Override
public void onDestroy(){
super.onDestroy();
if (cursor != null) cursor.close();
if (db != null) db.close();
}
@Override
protected void onListItemClick(ListView listView, View view, int position, long id) {
Intent intent = new Intent(ThingListActivity.this, ThingSlideActivity.class);
intent.putExtra(ThingSlideActivity.EXTRA_POSITION, (int) position);
startActivity(intent);
}
}
The follow-on FragmentActivity
. This activity has an inner class ThingSlidePageAdapter
. Notice setCurrentItem
, which places you in the right spot within the list. :
public class ThingSlideActivity extends FragmentActivity{
public static final String EXTRA_POSITION = "extra_position";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_slide);
ViewPager mPager = (ViewPager)findViewById(R.id.pager);
PagerAdapter mPagerAdapter = new ThingSlidePageAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem((Integer)getIntent().getExtras().get(EXTRA_POSITION));
}
private static class ThingSlidePageAdapter extends FragmentStatePagerAdapter {
int count;
public ThingSlidePageAdapter(FragmentManager fm){
super(fm);
this.count = ThingListActivity.getCursor().getCount();
}
@Override
public int getCount() {
return this.count;
}
@Override
public Fragment getItem(int position) {
return ThingSlideFragment.newInstance(position); // onCreate() doesn't work well.
}
}
}
**The Fragment
we are paging through. This is where we use the Cursor
from the original ListView
in order to get the database key (_id
). Then a fresh query is executed, pulling details for only for one item. But under the covers, the previous and next items are also pulled.
public class ThingSlideFragment extends Fragment {
private static final String ARG_POSITION = "position";
public static ThingSlideFragment create(int position) {
ThingSlideFragment fragment = new ThingSlideFragment();
Bundle args = new Bundle();
args.putInt(ARG_POSITION, position);
fragment.setArguments(args);
return fragment;
}
public static ThingSlideFragment newInstance(int position) {
ThingSlideFragment fragment = new ThingSlideFragment();
Bundle args = new Bundle();
args.putInt(ARG_POSITION, position);
fragment.setArguments(args);
return fragment;
}
public ThingSlideFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.activity_thing, container, false);
TextView tv = (TextView)rootView.findViewById(R.id.thingname);
Cursor mCursor = ThingListActivity.getCursor();
if (mCursor != null) {
mCursor.moveToPosition(getArguments().getInt(ARG_POSITION));
int id = Integer.parseInt(mCursor.getString(0));
populateView(id, rootView);
}
return rootView;
}
private void populateView(int id, View rootView) {
Cursor cursor = null;
SQLiteDatabase db = null;
try {
SQLiteOpenHelper tableDatabaseHelper = new TableDatabaseHelper(this.getContext()) ;
db = tableDatabaseHelper.getReadableDatabase();
cursor = db.query("TABLE", new String[] {"NAME", "DESCRIPTION", "DETAIL1", "DETAIL2", "DETAIL3", "DETAIL4"}, "_id = ?", new String[] {Integer.toString(id)}, null, null, null);
//Move to first record in the cursor (should be just one since our query used database key "CREATE TABLE TABLE (_id INTEGER PRIMARY KEY AUTOINCREMENT, ...."
if (cursor.moveToFirst()) {
// Get thing details from the cursor
String nameText = cursor.getString(0);
String descriptionText = cursor.getString(1);
// ........ continue with other fields
// Populate TextView items
((TextView)rootView.findViewById(R.id.thingname)).setText(nameText);
((TextView)rootView.findViewById(R.id.description)).setText(descriptionText);
// ........ continue with other fields
}
} catch (SQLiteException e) {
Toast toast = Toast.makeText(this.getContext(), "Database unavailable. "+ e.getMessage(), Toast.LENGTH_LONG) ;
} finally {
try {cursor.close();} catch (Throwable t) {}
try {db.close();} catch (Throwable t) {}
}
}
}
And, left out of many of the examples here, the contents of the supporting xml files!
<!-- R.layout.activity_screen_slide.xml containing R.id.pager -->
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- R.layout.activity_thing.xml containing R.id.thingname and R.id.description -->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:id="@+id/thingRelativeLayout"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.someones.package.ThingActivity"
tools:showIn="@layout/activity_thing">
<TextView
android:id="@+id/thingname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:paddingTop="40dp"
android:textSize="40dp"
android:gravity="center"
tools:text="Name Of Thing"
/>
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textSize="20dp"
android:layout_below="@id/thingname"
android:paddingTop="10dp"
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et magna ut erat elementum cursus in quis ipsum. Nam faucibus ultrices eros, vel tempor leo semper sit amet."
/>
</RelativeLayout>
</ScrollView>
I hope this works for you and hope a lot of people are able to find it and benefit from it, because I spent a couple of days fiddling around with this until I got it working to my satisfaction. Possibly an easy one for the more highly experienced here, but helpful for those at a certain level of experience.