2

I have a ScrollView with a lot buttons. Each button is enabled when the user unlocks that button/level. I would like to focus the ScrollView on the latest unlocked button/level. See the screenshot below.

enter image description here

I found some functions like scrollTo() that could focus the ScrollView either at top, button or something like that but I would like to focus the ScrollView at certain places like the button ID that says Level 8 in the screenshot below. How would I go about doing this?

Matt
  • 3,882
  • 14
  • 46
  • 89
  • Possible duplicate of [Is there a way to programmatically scroll a scroll view to a specific edit text?](https://stackoverflow.com/questions/6831671/is-there-a-way-to-programmatically-scroll-a-scroll-view-to-a-specific-edit-text) – Suphi ÇEVİKER Sep 26 '19 at 12:41

7 Answers7

2

I think this should be good enough :

  yourButtonView.getParent().requestChildFocus(yourButtonView,yourButtonView);

public void RequestChildFocus (View child, View focused)

child - The child of this ViewParent that wants focus. This view will contain the focused view. It is not necessarily the view that actually has focus.

focused - The view that is a descendant of child that actually has focus

Swas_99
  • 2,350
  • 1
  • 15
  • 19
1

First you need to know the position of item in scroll that has to get focus once you know that you can use following code to make that item focus

    final int x;
            final int y;
            x = rowview[pos].getLeft();
            y = rowView[pos].getTop();

                yourScrollView.scrollTo(x, y);

refer this question

Community
  • 1
  • 1
Sourabh Saldi
  • 3,567
  • 6
  • 34
  • 57
1

I agree with the benefits of previous answers. However, by experience, I have found this to be more complex than this. The setSelectionFromTop is very sensitive and often breaks if it is executed too early. This may depend on different reasons but the two primary reasons are that

  • If executed from within Activity lifecycle methods the views have not been loaded/configured yet.
  • View modifications triggered after the list move action seems to break the move. Probably overwriting some value before the move has been finalized due to a recalculation of the views.

The reasoning seems to apply for both setSelectionFromTop and setSelection() methods although I tested mostly with setSelectionFromTop. smoothScrollToPosition() seems to be more robust, probably because it by definition changes the list position delayed whn doing the smooth scrolling.

Look at this example source code:

// Wee need to pospone the list move until all other view setup activities are finished
list.post(new Runnable(){
    @override
    public void run() {
        list.setSelectionFromTop(selectedPosition, Math.max(0, Math.round(list.getHeight() / 3))); // Make sure selection is in middle of page, if possible.
        // Make sure you do not modify (this or other) parts of the view afterwards - it may break the list move
        // activityButtons.setVisibility(View.GONE);
}});
Lmickos
  • 369
  • 3
  • 10
0

see: http://developer.android.com/reference/android/widget/ListView.html#setSelectionFromTop(int, int)

  • 'int selectedLevel' holds the currently selected level, information is held in a Level class.
  • 'values' is a list with all your levels, displayed by the list.

Example:

    ListView lv = (ListView)findViewById(android.R.id.list);
    int i = 0;
    for (Level l : values) {
        i++;
        if (l.level == selectedLevel) {
            lv.setSelectionFromTop(i, 200);
            break;
        }
    }
alvi
  • 2,622
  • 1
  • 22
  • 34
0

try this

sc.post(new Runnable() { 
        public void run() { 
             sc.smoothScrollTo(x, y);
        } 
    });

x the position where to scroll on the X axis

y the position where to scroll on the Y axis

Fahriyal Afif
  • 560
  • 3
  • 11
0

Use this code, taken from this answer

private final void focusOnView(){
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                your_scrollview.scrollTo(0, your_EditBox.getBottom());
            }
        });
    }
Community
  • 1
  • 1
TapanHP
  • 5,969
  • 6
  • 37
  • 66
0

Use this code, taken from my another answer

scrollViewSignup.post(new Runnable() {
    @Override
    public void run() {
        int scrollY = scrollViewSignup.getScrollY();
        scrollViewSignup.scrollTo(0, 0);
        final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
        view.requestRectangleOnScreen(rect, true);

        int new_scrollY = scrollViewSignup.getScrollY();
        scrollViewSignup.scrollTo(0, scrollY);
        scrollViewSignup.smoothScrollTo(0, new_scrollY);
    }
});

This code tries to smooth scroll and uses the standard behaviour of system to position to an item. You can simply change smoothScrollTo with scrollTo if you don't want the system to smooth scroll to the item. Or, you can use the code below only.

scrollViewSignup.post(new Runnable() {
    @Override
    public void run() {
        scrollViewSignup.scrollTo(0, 0);
        final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
        view.requestRectangleOnScreen(rect, true);
    }
});

Use the desired code block after trying, or, according to the need.

  • Whenever your answer answers 2 questions, that is a sign that these questions are in fact duplicates. In such a case you should flag the questions, not post your answer twice. – Max Vollmer Sep 26 '19 at 12:57