Android: more scrolling woes
Alright, so because of this question which I asked previously, I found out that you cannot know the scroll position of a WebView. I followed advice to put my content in a ListView instead. There's now a new problem.
All I am trying to do is tell when a certain part of the view scrolls past the bottom edge and the top edge of the screen. When the image appears at the bottom of the screen or disappears above the top of the screen, i want to play a sound effect.
Here's my code using a ListView. The problem is that onScroll is not consistently called. It seems like it's called only if I lift my finger and wait, then start scrolling again.
At the same time, onScrollStateChanged isn't always called either---it seems to only be called on the first frame of the scroll.
Isn't there some way to just continuously get scrolling information on every single frame of the scroll, regardless of whether I'm touching the screen? I just want to know whether the scroll animation has been activated, even if it's one pixel, so that I can look at the position of the image element and see whether it's on screen or not.
public class Scroll extends ListActivity implements ListView.OnScrollListener {
public ListView listview;
public int firstItemOnScreen;
public int lastItemOnScreen;
public int previousFirstItemOnScreen;
public int previousLastItemOnScreen;
private TextView mStatus;
private boolean mBusy = false;
//
// Will not bind views while the list is scrolling
//
//
private class SlowAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public SlowAdapter(Context context) {
mContext = context;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
//
// The number of items in the list is determined by the number of speeches
// in our array.
//
// @see android.widget.ListAdapter#getCount()
//
public int getCount() {
return 0;//mStrings.length;
}
//
// Since the data comes from an array, just returning the index is
// sufficent to get at the data. If we were using a more complex data
// structure, we would return whatever object represents one row in the
// list.
//
// @see android.widget.ListAdapter#getItem(int)
//
public Object getItem(int position) {
return position;
}
//
// Use the array index as a unique id.
//
// @see android.widget.ListAdapter#getItemId(int)
//
public long getItemId(int position) {
return position;
}
//
// Make a view to hold each row.
//
// @see android.widget.ListAdapter#getView(int, android.view.View,
// android.view.ViewGroup)
//
public View getView(int position, View convertView, ViewGroup parent) {
TextView text;
if (convertView == null) {
text = (TextView)mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
} else {
text = (TextView)convertView;
}
if (!mBusy) {
//text.setText(mStrings[position]);
// Null tag means the view has the correct data
text.setTag(null);
} else {
text.setText("Loading...");
// Non-null tag means the view still needs to load its data
text.setTag(this);
}
return text;
}
//
//Remember our context so we can use it when constructing views.
//
private Context mContext;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ImageListAdapter ila = new ImageListAdapter(this);
// Add four items
ila.addItem(new ImageList(
"", getResources().getDrawable(R.drawable.header)));
ila.addItem(new ImageList(
"Test text", null));
ila.addItem(new ImageList(
"", getResources().getDrawable(R.drawable.interstitial1)));
ila.addItem(new ImageList(
"Test text", null));
// Display it
setListAdapter(ila);
getListView().setOnScrollListener(this);
}
public void onScroll(AbsLi开发者_Python百科stView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount){
firstItemOnScreen = getListView().getFirstVisiblePosition();
lastItemOnScreen = getListView().getLastVisiblePosition();
Log.v("List", "first:" + firstItemOnScreen);
Log.v("List", "last:" + lastItemOnScreen);
// Bottom edge appears at top of screen
if (firstItemOnScreen == 2 && previousFirstItemOnScreen != 2) {
tvt.playEffect(2, 0);
}
// Top edge appears at top of screen
// AND
// Bottom edge appears at bottom of screen
if (firstItemOnScreen == 1 && lastItemOnScreen == 3) {
if (lastItemOnScreen != previousLastItemOnScreen || firstItemOnScreen != previousFirstItemOnScreen)
tvt.playEffect(2, 0);
}
// Top edge appears at bottom of screen
if (lastItemOnScreen == 2 && previousLastItemOnScreen != 2) {
tvt.playEffect(2, 0);
}
if (firstItemOnScreen == 3 && previousFirstItemOnScreen == 2)
tvt.playEffect(2, 0);
if (previousLastItemOnScreen == 3 && lastItemOnScreen == 2)
tvt.playEffect(2, 0);
if (previousFirstItemOnScreen == 1 && firstItemOnScreen == 2 && previousLastItemOnScreen == 3 && lastItemOnScreen == 3)
tvt.playEffect(2, 0);
if (firstItemOnScreen == 1 && previousFirstItemOnScreen == 1) {
if (lastItemOnScreen ==1 && previousLastItemOnScreen == 2)
tvt.playEffect(2, 0);
}
previousFirstItemOnScreen = firstItemOnScreen;
previousLastItemOnScreen = lastItemOnScreen;
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case OnScrollListener.SCROLL_STATE_IDLE:
mBusy = false;
int count = view.getChildCount();
for (int i=0; i<count; i++) {
ImageListView t = (ImageListView)view.getChildAt(i);
if (t.getTag() != null) {
t.setTag(null);
}
}
break;
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
mBusy = true;
break;
case OnScrollListener.SCROLL_STATE_FLING:
mBusy = true;
break;
}
}
This answer comes late, but the way scrolling is implemented in Android I think you may need to subclass ListView to do what you want. You can override scrollTo and scrollBy and check your conditions there (make sure to call super.scrollTo and super.scrollBy at the appropriate time).
精彩评论