Horizontalscrollview: Auto-Scroll to End When New Views Are Added

HorizontalScrollView: auto-scroll to end when new Views are added?

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).

Auto Scroll to HorizontalScrollView

DmRomantsov's answer is the right way to scroll to the 12th button. However, getLeft() and getRight() methods return 0 because the layout is not displayed yet on the screen. It is too early to calculate the width of the layout parent and children. To achieve it, you need to do your auto-scroll inside onWindowFocusChanged.

@Override
public void onWindowFocusChanged(boolean hasFocus){
super.onWindowFocusChanged(hasFocus);
if(hasFocus){
// do smoothScrollTo(...);
}
}

However, inside a Fragment, this method above will not work. I just wrote it to give a clue, to understand the concept. To have the same behaviour in Fragment, you just need to do a Runnable which lets the time to your UI to be displayed. Then, do this with a LinearLayout oriented to horizontal:

// Init variables
HorizontalScrollView mHS;
LinearLayout mLL;

// onCreateView method
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_container, container, false);

// Find your views
mHS = (HorizontalScrollView)view.findViewById(R.id.hscrollview);
mLL = (LinearLayout)view.findViewById(R.id.hscrollview_container);

// Do a Runnable on the inflated view
view.post(new Runnable() {
@Override
public void run() {
Log.v("","Left position of 12th child = "+mLL.getChildAt(11).getLeft());
mHS.smoothScrollTo(mLL.getChildAt(11).getLeft(), 0);
}
});
return view;
}

Middle HorizontalScrollView:

Your question was to auto-scroll until your 12th child. However, in the comments below, you ask me to auto-scroll at the middle of the HorizontalScrollView, I assume on every device. You need to calculate the width of the screen, the total width of the container and how many children are displayed inside the device width. Here is a simple code:

// Auto scroll to the middle (regardless of the width screen)
view.post(new Runnable() {
@Override
public void run() {
// Width of the screen
DisplayMetrics metrics = getActivity().getResources()
.getDisplayMetrics();
int widthScreen = metrics.widthPixels;
Log.v("","Width screen total = " + widthScreen);

// Width of the container (LinearLayout)
int widthContainer = mLL.getWidth();
Log.v("","Width container total = " + widthContainer );

// Width of one child (Button)
int widthChild = mLL.getChildAt(0).getWidth();
Log.v("","Width child = " + widthChild);

// Nb children in screen
int nbChildInScreen = widthScreen / widthChild;
Log.v("","Width screen total / Width child = " + nbChildInScreen);

// Width total of the space outside the screen / 2 (= left position)
int positionLeftWidth = (widthContainer
- (widthChild * nbChildInScreen))/2;
Log.v("","Position left to the middle = " + positionLeftWidth);

// Auto scroll to the middle
mHS.smoothScrollTo(positionLeftWidth, 0);

}
});

/**
* Your value might be resumed by:
*
* int positionLeftWidth =
* ( mLL.getWidth() - ( mLL.getChildAt(0).getWidth() *
* ( metrics.widthPixels / mLL.getChildAt(0).getWidth() ) ) ) / 2;
*
**/

Middle HorizontalScrollView with chosen Value:

I have a bit misunderstand the real request. Actually, you wanted to auto-scroll until a chosen child view, and display this view at the middle of the screen.

Then, I changed the last int positionLeftWidth which refers now to the left position of the chosen view relative to its parent, the number of children contained in one screen, and the half width of the chosen view. So, the code is the same as above, except positionLeftWidth:

// For example the chosen value is 7

// 7th Child position left
int positionChildAt = mLL.getChildAt(6).getLeft();

// Width total of the auto-scroll (positionLeftWidth)
int positionLeftWidth = positionChildAt - // position 7th child from left less
( ( nbChildInScreen // ( how many child contained in screen
* widthChild ) / 2 ) // multiplied by their width ) divide by 2
+ ( widthChild / 2 ); // plus ( the child view divide by 2 )

// Auto-scroll to the 7th child
mHS.smoothScrollTo(positionLeftWidth, 0);

Then, whatever the value in getChildAt() method, and whatever the width screen, you will always have the chosen (in your case) button at the middle of the screen.

HorizontalScrollView, auto-scroll to end with animation

This is a demo project I created for one of my projects. Its a scroller the scroll automatically and continously. It was made to show a credits screen by continously scrolling through a list of images.
This might help you or give you some idea.

https://github.com/blessenm/SlideshowDemo

android, scroll HorizontalScrollView to end in ListView

Finally I found the solution, absolutely at my view when I wanted my HorizontalScrollView to show rtl (right-to-left) textView, The soluion is using RelativeLayout as parent .

HorizontalScrollView - auto scroll to a selected view

You can use smoothScrollTo(int x, int y) method, (x, y) represents the position of selected view, you can calculate it easily: (View.getLeft() + View.getPaddingLeft(), View.getTop()).

How to make HorizontalScrollView RIGHT to LEFT Scroll android

You can scroll it to the right edge of your scroll view in your code with something like this:

scrollView.postDelayed(new Runnable() {
public void run() {
scrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
}, 100L);

Related Q and A is https://stackoverflow.com/a/4720563/2511775

How to get a horizontal ScrollView in SwiftUI to scroll automatically to end when the enclosed Text is updated

I assume you wanted this:

ScrollViewReader { scrollView in
VStack {
ScrollView(.horizontal) {
Text(model.combinedString)
.id("combinedText")
}
.onChange(of: model.combinedString) { // << here !!
withAnimation {
scrollView.scrollTo("combinedText", anchor: .trailing)
}
}
}
}

Issue of horizontal scrollview automatically scrolls on Edittext focus

I am able to resolve my Problem here but still dont know why this is happening.

I remove all the properties of editext that are defined and added that all properties one by one and check which property causing issue and I found out that when I add gravity="center" property to edittext again horizontal scroll view scrolls to end.

So It is happening because of gravity="center" property of edittext.

But still I don't know why gravity that is of edittext is direct affecting to horizontal scroll view weird behavior . is gravity is somehow related to content view of parent container ?

If any one have answer about this behavior please share your views.



Related Topics



Leave a reply



Submit