android – How to programmatically scroll an HorizontalScrollView-ThrowExceptions

Exception or error:

I have an HorizontalScrollView which contains a RelativeLayout. This layout is empty in the XML, and is populated from java in the onCreate.

I would like this scroll view to be initially somewhere in the middle of the RelativeLayout, which is way larger than the screen.

I tried mHorizScrollView.scrollTo(offsetX, 0); which doesn’t work.
I don’t know what’s wrong with this.

I could post the code, but it is not really relevant. What matters is that everything is done programatically (has to :s), and that the initial position of the HorizontalScrollView has to be set programmatically.

Thanks for reading. Please tell me if you need more details or if this is not clear enough.

How to solve:

I found that if you extend the HorizontalScrollView and override the onLayout, you can cleanly scroll, after the super call to onLayout:

MyScrollView extends HorizontalScrollView {
    protected void onLayout (boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        this.scrollTo(wherever, 0);
    }
}

EDIT:
For scrolling to start or end you can use:

this.fullScroll(HorizontalScrollView.FOCUS_RIGHT/FOCUS_LEFT);

instead of

this.scrollTo(wherever, 0);

###

public void autoSmoothScroll() {

        final HorizontalScrollView hsv = (HorizontalScrollView) view.findViewById(R.id.horiscroll);
        hsv.postDelayed(new Runnable() {
            @Override
            public void run() {
                //hsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
                hsv.smoothScrollBy(500, 0);
            }
        },100);
    }

###

To test whether it’s a timing issue (which I think it is), instead of calling scrollTo() in onStart, call postDelayed() with a Runnable that calls scrollTo, with a delay of 30 or so.

###

A better approach would be using the ViewTreeObserver to observe layouts.

View interestedInView;
onCreate(){
  //Code

  //Observe for a layout change
  ViewTreeObserver viewTreeObserver = interestedInView.getViewTreeObserver();
  if (viewTreeObserver.isAlive()) {
    viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
      @Override
      public void onGlobalLayout() {
        //REMOVE THE VIEWTREE OBSERVER
        //interestedInView is ready for size and position queries because it has been laid out
      }
    });
  }
}

###

The problem is that the view doesn’t have a size yet. The Clean way to do this is to implement the onSizeChanged of the ScrollView to send a message to a Handler in your activity to in order to notify the activity that the view has a size and that scrolling is possible.

###

Use view.post and write scrollTo(x,y) inside run method. This the way to invalidate view in post method as per android API document.

###

The scrollTo function should work. What is the layout_width of the HSV, and the view inside of it?

###

The onSizeChanged function should work. What you fail to understand is that the onSizeChanged should send a message to a Handler of your activity and not any callback function, because a handler will execute code in the UI thread. You cannot do UI operations outside it. Have a look at handlers.

Leave a Reply

Your email address will not be published. Required fields are marked *