I have a HorizontalScrollView containing a LinearLayout. On screen I have a Button that will add new Views to the LinearLayout at runtime, and I\'d like the scroll view to
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);
}
});
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 think the best approach is the one posted by monxalo because you can not know how much time will it take until the layout is done. I tried it and it works perfectly. The only difference is, that I added only one row to my custom horizontal scroll view:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
this.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
This is what I did.
//Observe for a layout change
ViewTreeObserver viewTreeObserver = yourLayout.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
yourHorizontalScrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
});
}
The child View
may not be immediately added in a ViewGroup
. So it is required to post a Runnable
which will run after other pending tasks are completed.
So after adding View
, use:
horizontalScrollView.post(new Runnable() {
@Override
public void run() {
horizontalScrollView.fullScroll(View.FOCUS_RIGHT);
}
});
This is my way for 3 ImageViews in kotlin:
var p1 = true; var p2 = false; var p3 = false
val x = -55
val handler = Handler()
handler.postDelayed(object : Runnable {
override fun run() {
if (p1){
mainView.picsScrollViewID.smoothScrollTo(mainView.bigPic1ID.x.toInt() + x, 0)
p1 = false
p2 = true
p3 = false
}
else if(p2){
mainView.picsScrollViewID.smoothScrollTo(mainView.bigPic2ID.x.toInt() + x, 0)
p1 = false
p2 = false
p3 = true
}
else if(p3){
mainView.picsScrollViewID.smoothScrollTo(mainView.bigPic3ID.x.toInt() + x, 0)
p1 = true
p2 = false
p3 = false
}
handler.postDelayed(this, 2000)
}
}, 1400)