Book reading widget for Android
I am working on a eBook reading app for my company; we use a library that does dynamic reflowing layout of screens to a custom View I provide.
I want a display that lets the user move from one screen to the next by finger swipes. I'm using my own subclass of android.widget.Gallery backed by a custom adapter; the adapter's getView() is responsible for talking to the library and generating a View for each requested page.
My problem is that the Gallery expects to know the total count of Views, and to have an index 开发者_如何学编程for its current position in the View array, but the library we use makes it impossible to know that. Because it does dynamic reflow, the total number of 'screens' that comprise the book depends on the screen size of the device, the current font size, screen orientation, etc.--there's no way to know it in advance. We can also jump to ay location in the book; when it does so, there is no way to know how many 'screens' from the start we are (short of returning to the start and advancing a page at a time to the same place), and thus no way to get a position index into the Gallery view.
My current solution is to handle the 'ends' of the Gallery as special conditions in my adapter's getView() call: if it hits the start of the Gallery but I know more pages are available, I force the Gallery to change its current position. Here's an example of PageAdapter.getView():
public View getView(int position, View convertView, ViewGroup parent)
{
...
if( 0 == position ) {
// The adapter thinks we're at screen 0; verify that we really are
int i = 0;
// previousScreen() returns true as long as it could move
// to another screen; after this loop, i will equal the
// number of additional screens before our current position
while( m_book.previousScreen() ) {
i++;
}
PageFlipper pf = (PageFlipper) parent;
// Remember the last REAL position we dealt with.
// The +1 to mActualPosition is a hack--for some reason,
// PageFlipper.leftResync() needs it to work correctly.
m_lastRequestedPosition = i;
pf.mActualPosition = i + 1;
pf.mNeedsLeftResync = true;
// Do a fixup so we're on the right screen
while( i-- > 0 ) {
m_book.nextScreen();
}
}
...
m_view = new PageView(m_book);
return m_view;
}
And here's how it's used in my Gallery subclass:
public class PageFlipper extends Gallery {
...
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// Triggers a call to PageAdapter.getView()
super.onScroll(e1, e2, distanceX, distanceY);
// Adapter getView() may have marked us out of sync
this.checkLeftResync();
return true;
}
...
private void checkLeftResync() {
if( mNeedsLeftResync ) {
setSelection(mActualPosition, false);
mActualPosition = 0;
mNeedsLeftResync = false;
}
}
}
However, my solution is unreliable, and feels intuitively wrong. What I really want is something that looks and feels like a Gallery widget, but never tracks any position; instead, it would always ask the Adapter if a new view is available and behave appropriately. Has anyone seen a solution to a problem like this?
BTW, the closest thing I've seen is this project on Google apps, but it appears to expect a static, preallocated set of views.
Thanks in advance for any suggestions!
精彩评论