Можно ли прокручивать ScrollView программно в Android?

145

Есть ли способ ScrollViewпрограммно прокрутить до определенной позиции?

Я создал динамический, TableLayoutкоторый находится в ScrollView. Поэтому я хочу, чтобы в конкретном действии (например, нажатие кнопки и т. Д.) Конкретная строка автоматически прокручивалась до верхней позиции.

Является ли это возможным?

Арун Бадоле
источник

Ответы:

165
ScrollView sv = (ScrollView)findViewById(R.id.scrl);
sv.scrollTo(0, sv.getBottom());

или

sv.scrollTo(5, 10);

Android
источник
43
Сочетая ответ ercu и комментарий, сделанный на нем, лучший способ выглядит так:mScrollView.post(new Runnable() { public void run() { mScrollView.fullScroll(View.FOCUS_DOWN); } });
sparrowt
2
scrollTo () не приведет к желаемому результату. Надо идти с fullScroll ()
Амит Ядав
3
Более приятный свиток с естественным эффектом: sv.smoothScrollTo (5, 10)
ivan.panasiuk
205

Ответ от Pragna не всегда работает, попробуйте это:

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.scrollTo(0, mScrollView.getBottom());
        } 
});

или

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_DOWN);
        } 
});

если вы хотите прокрутить, чтобы начать

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_UP);
        } 
});
ercu
источник
28
Я использовал mScrollView.fullScroll(mScrollView.FOCUS_DOWN);с успехом.
amcc
3
Я могу подтвердить выводы Вантела. mScrollView.fullScroll в готовом посте сделал свое дело.
AlanKley
1
Превосходно ! Действительно, без Runnable, это не сработало. Теперь это работает! :)
Regis_AG
5
@HiteshDhamshaniya Если вы хотите плавную прокрутку, попробуйте mScrollView.smoothScrollTo(0, mScrollView.getBottom());.
Майк Ортиз
1
Зачем postздесь это нужно ?
Лютинг
35

Я хотел, чтобы scrollView прокручивался непосредственно после onCreateView () (а не после, например, нажатия кнопки). Чтобы заставить его работать, мне нужно было использовать ViewTreeObserver:

mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mScrollView.post(new Runnable() {
                public void run() {
                    mScrollView.fullScroll(View.FOCUS_DOWN);
                }
            });
        }
    });

Но имейте в виду, что это будет вызываться каждый раз, когда что-то размещается (например, если вы устанавливаете представление невидимым или похожим), поэтому не забудьте удалить этот слушатель, если он вам больше не нужен:

public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) на SDK Lvl <16

или

public void removeOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) в SDK Lvl> = 16

Патрик Фавр
источник
23

Здесь много хороших ответов, но я хочу добавить только одну вещь. Иногда случается, что вы хотите прокрутить ScrollView до определенного вида макета вместо полной прокрутки вверх или вниз.

Простой пример: если в форме регистрации пользователь нажимает кнопку «Регистрация», когда текст для редактирования формы не заполнен, вы хотите перейти к этому конкретному тексту для редактирования, чтобы сообщить пользователю, что он должен заполнить это поле.

В этом случае вы можете сделать что-то вроде этого:

scrollView.post(new Runnable() { 
        public void run() { 
             scrollView.scrollTo(0, editText.getBottom());
        } 
});

или, если вы хотите плавную прокрутку вместо мгновенной прокрутки:

scrollView.post(new Runnable() { 
            public void run() { 
                 scrollView.smoothScrollTo(0, editText.getBottom());
            } 
    });

Очевидно, что вы можете использовать любой тип представления вместо редактирования текста. Обратите внимание, что getBottom () возвращает координаты представления на основе его родительского макета, поэтому все представления, используемые внутри ScrollView, должны иметь только родителя (например, линейный макет).

Если у вас есть несколько родителей внутри дочернего элемента ScrollView, единственное решение, которое я нашел, это вызвать requestChildFocus в родительском представлении:

editText.getParent().requestChildFocus(editText, editText);

но в этом случае вы не можете иметь плавную прокрутку.

Я надеюсь, что этот ответ может помочь кому-то с той же проблемой.

Маттиа Руджеро
источник
1
@JohnT Рад, что это помогло тебе :)
Маттиа Руджеро
20

Используйте что-то вроде этого:

mScrollView.scrollBy(10, 10);

или

mScrollView.scrollTo(10, 10);
Сриханд Йелла
источник
8

Если вы хотите прокрутить мгновенно, вы можете использовать:

ScrollView scroll= (ScrollView)findViewById(R.id.scroll);
scroll.scrollTo(0, scroll.getBottom());

            OR

scroll.fullScroll(View.FOCUS_DOWN);

            OR

scroll.post(new Runnable() {            
    @Override
    public void run() {
           scroll.fullScroll(View.FOCUS_DOWN);              
    }
});

Или, если вы хотите прокрутить плавно и медленно, чтобы вы могли использовать это:

private void sendScroll(){
        final Handler handler = new Handler();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {Thread.sleep(100);} catch (InterruptedException e) {}
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.fullScroll(View.FOCUS_DOWN);
                    }
                });
            }
        }).start();
    }
Мэдди
источник
что делает этот catchблок?
Джон Сардинья
1
Блок Catch предназначен для перехвата исключений во время прокрутки, если они есть.
Мэдди,
5

** для прокрутки до желаемой высоты. Я нашел хорошее решение **

                scrollView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.scrollBy(0, childView.getHeight());
                    }
                }, 100);
Викас Чаухан
источник
4

Я получил это, чтобы работать, чтобы прокрутить до конца ScrollView (с TextView внутри):

(Я положил это на метод, который обновляет TextView)

final ScrollView myScrollView = (ScrollView) findViewById(R.id.myScroller);
    myScrollView.post(new Runnable() {
    public void run() {
        myScrollView.fullScroll(View.FOCUS_DOWN);
    }
});
Ohiovr
источник
4

Да, ты можешь.

Допустим, у вас есть один Layoutи внутри, у вас есть много Views. Поэтому, если вы хотите прокрутить любую Viewпрограмму программным способом, вам нужно написать следующий фрагмент кода:

Например:

content_main.xml

<ScrollView
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/txtView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>
</ScrollView>

MainActivity.java

ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
Button btn = (Button) findViewById(R.id.ivEventBanner);
TextView txtView = (TextView) findViewById(R.id.ivEditBannerImage);

Если вы хотите прокрутить до определенного View, скажем, txtview , в этом случае просто напишите:

scrollView.smoothScrollTo(txtView.getScrollX(),txtView.getScrollY());

И вы сделали.

Панкадж Лилан
источник
3

Примечание: если вы уже в теме, вы должны создать новую тему сообщения, или она не прокручивает новую длинную высоту до полного конца (для меня). Например:

void LogMe(final String s){
    runOnUiThread(new Runnable() {
        public void run() {
            connectionLog.setText(connectionLog.getText() + "\n" + s);
            final ScrollView sv = (ScrollView)connectLayout.findViewById(R.id.scrollView);
            sv.post(new Runnable() {
                public void run() {
                    sv.fullScroll(sv.FOCUS_DOWN);
                    /*
                    sv.scrollTo(0,sv.getBottom());
                    sv.scrollBy(0,sv.getHeight());*/
                }
            });
        }
    });
}
djdance
источник
3

Добавление другого ответа, который не включает координаты.

Это позволит сфокусировать желаемый вид (но не на верхнюю позицию):

  yourView.getParent().requestChildFocus(yourView,yourView);

public void RequestChildFocus (Просмотреть ребенка, Просмотреть сосредоточен)

child - дочерний элемент этого ViewParent, который хочет сосредоточиться. Это представление будет содержать сфокусированное представление. Это не обязательно точка зрения, которая на самом деле имеет фокус.

сосредоточенный - вид, который является потомком ребенка, который на самом деле имеет фокус

Swas_99
источник
Именно то, что мне было нужно, спасибо. Сначала запросите фокус для просмотра прокрутки, а затем scrollView.smoothScrollTo (0, scrollView.getChildAt (0) .getBottom ());
Вулович Вукасин
3

просто прокрутите страницу:

ScrollView sv = (ScrollView) findViewById(your_scroll_view);
sv.pageScroll(View.FOCUS_DOWN);
Кирилл Вашило
источник
2

Каждый публикует такие сложные ответы.

Я нашел простой ответ, для прокрутки до дна, приятно:

final ScrollView myScroller = (ScrollView) findViewById(R.id.myScrollerView);

// Scroll views can only have 1 child, so get the first child's bottom,
// which should be the full size of the whole content inside the ScrollView
myScroller.smoothScrollTo( 0, myScroller.getChildAt( 0 ).getBottom() );

И, если необходимо, вы можете поместить вторую строку кода, приведенную выше, в исполняемый файл:

myScroller.post( new Runnable() {
    @Override
    public void run() {
        myScroller.smoothScrollTo( 0, myScroller.getChildAt( 0 ).getBottom() );
    }
}

Мне понадобилось много исследований и игр, чтобы найти это простое решение. Надеюсь, вам это тоже поможет! :)

Nalorin
источник
1

Я использовал Runnable с sv.fullScroll (View.FOCUS_DOWN); Он отлично работает для немедленной проблемы, но этот метод заставляет ScrollView брать фокус со всего экрана, если вы выполняете эту автопрокрутку каждый раз, никакой EditText не сможет получать информацию от пользователя, мое решение использовало другой код под управлением:

sv.scrollTo (0, sv.getBottom () + sv.getScrollY ());

делая то же самое, не теряя внимания на важные взгляды

Привет.

Sebasu
источник
0

это работает для меня

mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mScrollView.post(new Runnable() {
                public void run() {
                    mScrollView.fullScroll(View.FOCUS_DOWN);
                }
            });
        }
    });
Али Асади
источник
0
private int totalHeight = 0;

ViewTreeObserver ScrollTr = loutMain.getViewTreeObserver();
ScrollTr.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            loutMain.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        } else {
            loutMain.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
        TotalHeight = loutMain.getMeasuredHeight();

    }
});

scrollMain.smoothScrollTo(0, totalHeight);
П. Патель
источник
0
I had to create Interface

public interface ScrollViewListener {
    void onScrollChanged(ScrollViewExt scrollView, 
                         int x, int y, int oldx, int oldy);
}    

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;

public class CustomScrollView extends ScrollView {
    private ScrollViewListener scrollViewListener = null;
    public ScrollViewExt(Context context) {
        super(context);
    }

    public CustomScrollView (Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CustomScrollView (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
        }
    }
}




<"Your Package name ".CustomScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusableInTouchMode="true"
    android:scrollbars="vertical">

    private CustomScrollView scrollView;

scrollView = (CustomScrollView)mView.findViewById(R.id.scrollView);
        scrollView.setScrollViewListener(this);


    @Override
    public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {
        // We take the last son in the scrollview
        View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1);
        int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));

        // if diff is zero, then the bottom has been reached
        if (diff == 0) {
                // do stuff
            //TODO keshav gers
            pausePlayer();
            videoFullScreenPlayer.setVisibility(View.GONE);

        }
    }
Кешав Гера
источник