HorizontalScrollView: auto-scroll to end when new Views are added?
Use the View method smoothScrollTo
postDelayed(new Runnable() {
public void run() {
scrollView.smoothScrollTo(newView.getLeft(), newView.getTop());
}
}, 100L);
You need to put in a runnable so you give time to the layout process to position the new View
I agree with @monxalo and @granko87 that the better approach is with a listener instead of making an assumption that the layout will be complete if we let some arbitrary amount of time pass.
In case, like me, you don't need to use a custom HorizontalScrollView subclass you can just add an OnLayoutChangeListener to keep things simple:
mTagsScroller.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
mTagsScroller.removeOnLayoutChangeListener(this);
mTagsScroller.fullScroll(View.FOCUS_RIGHT);
}
});
I think there's a timing issue. Layout isn't done when a view is added. It is requested and done a short time later. When you call fullScroll immediately after adding the view, the width of the linearlayout hasn't had a chance to expand.
Try replacing:
s.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
with:
s.postDelayed(new Runnable() {
public void run() {
s.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
}, 100L);
The short delay should give the system enough time to settle.
P.S. It might be sufficient to simply delay the scrolling until after the current iteration of the UI loop. I have not tested this theory, but if it's right, it would be sufficient to do the following:
s.post(new Runnable() {
public void run() {
s.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
});
I like this better because introducing an arbitrary delay seems hacky to me (even though it was my suggestion).
Just another sugestion, since this question helped me a lot :).
You can put a listener when the view has finished its layout phase, and right after do the fullScroll althought you'll need to extend the class for that.
I only did this because i wanted to scroll to a section right after onCreate() to avoid that flickering from starting point to scroll point.
Something like:
public class PagerView extends HorizontalScrollView {
private OnLayoutListener mListener;
///...
private interface OnLayoutListener {
void onLayout();
}
public void fullScrollOnLayout(final int direction) {
mListener = new OnLayoutListener() {
@Override
public void onLayout() {
fullScroll(direction)
mListener = null;
}
};
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if(mListener != null)
mListener.onLayout();
}
}