0

I feel like I'm missing something basic, and I'm actually kind of embarrassed asking this question. But that's what happens when you start learning a new platform...

I have a ListViewActivity that is populated via a CursorAdapter. When a list item is clicked, I start a new Activity to display the details for that item. What I want to do is enable flinging/swiping to iterate through the items from the detail activity. I don't want to fully populate a ViewFlipper, as there is no hard-coded limit to the number of items in the List, and it just seems wasteful. Is there some way to intercept the fling gesture/trackball movement, and reset the detail activity with the next/previous item detail?

My ListViewActivity just sets up a Cursor (via managedQuery) and the associated CursorAdapter, with an OnListItemClick that calls startActivity with the appropriate Intent.

public final class ModelList extends ListActivity {

    private Cursor m_models = null;
    private ModelAdapter m_adapter;

    @Override
    public void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(m_models == null) {
            m_models = managedQuery(Model.CONTENT_URI, Model.PROJECTION, null, null, Model.DEFAULT_SORT_ORDER);
        }
        m_adapter = new ModelAdapter(this, R.layout.modelitem, m_models);
        setContentView(R.layout.forcelist);
        setTitle(R.string.activity_list);
        setListAdapter(m_adapter);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        Log.d(getPackageName(), "Clicked item id:" + id);
        if(id < 0) {
            startActivity(new Intent(Intent.ACTION_EDIT, Model.CONTENT_URI));
        } else {
            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Model.CONTENT_URI + "/" + id)));
        }
    }
}

My detail Activity seems pretty straightforward; it's simply a RelativeLayout with a number of Views set up to display the details of the item based on the Intent's Uri.

public class ModelDetail extends Activity {

    private Uri mUri;
    private FactionHelper factionHelper;
    private static String mCostFormat;
    private static String mDescriptionFormat;
    private ModelAdapter.MarAdapter marAdapter;

    @Override
    public void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.modeldetail);
        setTitle(R.string.activity_detail);
        mCostFormat = getBaseContext().getResources().getString(R.string.modelCostFormat);
        mDescriptionFormat = getBaseContext().getResources().getString(R.string.modelDescriptionFormat);
        mUri = getIntent().getData();
        factionHelper = new FactionHelper(getBaseContext());
        populateData();
    }

    protected void populateData() {

        TextView name = (TextView) findViewById(R.id.modelName);
        TextView description = (TextView) findViewById(R.id.modelDescription);
        // ... More finding Views and populating data ...
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        populateData();
    }

}
Kenneth Cummins
  • 407
  • 1
  • 4
  • 13

1 Answers1

0

Just pass the ID of the current record to the details activity. This will then query the details for the ID given and get a Cursor for that record.

Then create a class which extends ViewSwitcher (the user will only be able to see one details at a time, so we only need 2 views at any one time). In your custom view switcher class add a method similar to:

class MySwitcher extends ViewSwitcher {
    ...

    long currentRowId;
    long nextRowId;
    long previousRowId;

    public void setItemDetails(long rowId) {
        final View nextView = this.getNextView();

        currentRowId = rowId;
        /* Get the next/previous record IDs with a query like
         * "SELECT row_id FROM table WHERE row_id < "+currentRowId+" ORDER BY row_id DESC LIMIT 1;" (Previous)
         * "SELECT row_id FROM table WHERE row_id > "+currentRowId+" ORDER BY row_id ASC LIMIT 1;" (Next)
         */        

        // Do something with nextView, like set some text or something
        // You could get a cursor based on the rowID with
        // "SELECT * FROM table WHERE row_id = "+currentRowId+" LIMIT 1;"
        ((TextView) nextView.findViewById(R.id.myTextView)).setText("Details for item #" + rowId);
        this.showNext();
    }
}

If you don't want an animation the first time setItemDetails is called then use setAnimateFirstView(false) on the ViewSwitcher.

Then you need to add an OnTouchListener to detect drags/swipes, and then call setItemDetails with the next/previous row ID when you detect a horizontal swipe -- you might want to set a different animation depending on whether you are moving to the next or previous item.

Joseph Earl
  • 23,351
  • 11
  • 76
  • 89
  • OK, I *think* I see what you're saying. My problem is that I want to maintain filters and ordering. It's not a straightforward select... I was also trying to be clever, and I think I got something terribly wrong. Anyway, how do I utilize the ViewSwitcher? Do I use that in the Activity.setContentView()? And for the OnTouchListener/GestureDetector, which classes extend those? I'm sorry, I feel like an idiot, but this is the first UI I've worked on other than web forms... :P – Kenneth Cummins Apr 05 '11 at 19:12
  • Sure, but your order is determined by an `ORDER BY` statement when you select all of the rows for the list isn't it? In that case use the same `ORDER BY` clause in the query for the next/previous records and ordering will be maintained (if the ordering can change you could pass the current order in the intent to the details activity). In the same way you can pass the current filter (where clause) and use the same where clause when retrieving the next/previous IDs. – Joseph Earl Apr 05 '11 at 19:26
  • Yes you can use it with setContentView. If you had a custom view class such as com.mycompany.myapp.CustomViewSwitcher, then you can just put it in XML the same as you would for a ViewSwitcher except use ` – Joseph Earl Apr 05 '11 at 19:29
  • For gesture detecting, override the `onTouch` method in a manner similar to that posted here: http://www.warriorpoint.com/blog/2009/05/29/android-switching-screens-by-dragging-over-the-touch-screen/. When you detect a drag, return `true` from your `onTouch` method (to indicate you consumed the touch event) and then call `setItemDetails(nextRowId)` if it's a drag the right, otherwise call it with `previousRowId`. – Joseph Earl Apr 05 '11 at 19:32
  • Got it working! Thanks! Now to research dealing with a ListView inside the ViewSwitcher... – Kenneth Cummins Apr 06 '11 at 00:09