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


145

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

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

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

Ответы:


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

или

sv.scrollTo(5, 10);


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);
        } 
});

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 Рад, что это помогло тебе :)
Маттиа Руджеро



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);
    }
});

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());*/
                }
            });
        }
    });
}

3

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

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

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

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

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

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


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


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() );
    }
}

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


1

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

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

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

Привет.


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

        }
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.