긴 ScrollView 레이아웃으로 스크롤하는 방법은 무엇입니까?


162

내 응용 프로그램의 일부로 사용자에게 이름 목록이 표시되고 적절하다고 생각되면 그룹화하라는 메시지가 표시됩니다.

(ListView 코드는 Android Views 튜토리얼에서 그대로 복사되었습니다. 아직 필요에 맞게 사용자 정의하지 않았 으므로이 작업을 수행하는 방법을 찾으려고합니다.)

기본 레이아웃은 LinearLayout이며 RelativeLayout을 포함하는 ScrollView (아래 코드에서 "groupsScrollView"라고 함)를 포함합니다. 버튼과 텍스트가 있고 그 아래에 ListView가 있는데 이름 목록이 표시됩니다. 이 모든 것이 보이는 화면 영역보다 높기 때문에 사용자는 세로로 스크롤하여 모두 볼 수 있습니다.

페이지가로드 될 때를 제외하고는 페이지 중간에 항상 내 ListView의 상단으로 미리 스크롤되는 것을 제외하고는 모두 아름답게 작동합니다. 내가 만든 텍스트와 버튼은 사용자에게 수행 할 작업을 표시하지 않습니다.

화면을 잡고 위로 스크롤 할 수 있지만 정상적으로 작동하지만 화면을 이미 맨 위로 스크롤하여로드하고 싶습니다. 새로로드 된 페이지의 상단을보기 위해 위로 스크롤 할 필요는 없습니다. 그러나 프로그래밍 방식으로 화면 상단으로 스크롤하려고 시도한 모든 것이 실패했습니다.

내 onCreate 메소드는 다음과 같습니다.

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.groups);

    mainScrollView = (ScrollView)findViewById(R.id.groupsScrollView);

    //get the Bundle out of the Intent...
    Bundle extras = getIntent().getExtras();
    mNames = extras.getStringArray("mNames");

    setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, mNames));

    ListView lv = getListView();
    lv.setTextFilterEnabled(true);

    //This is the line I'm having issues with
    mainScrollView.pageScroll(View.FOCUS_UP);

    lv.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {
          // When clicked, show a toast with the TextView text
          Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
              Toast.LENGTH_SHORT).show();
        }
      });
}

"mainScrollView.pageScroll (View.FOCUS_UP); 줄은 문제입니다. 오류가 발생하지 않지만 아무 것도하지 않는 것 같습니다. scrollTo (0,0), scrollDirection (View.FOCUS_UP ), 그리고 내가 생각할 수있는 모든 것.

오류가 발생하지 않기 때문에 이러한 스크롤 명령이 실제로 작동한다고 가정하지만 ScrollView 또는 RelativeLayout을 포함하는 ListView의 상단이 아닌 ListView의 상단으로 스크롤한다고 가정해야합니다. 이것은 구글이 scrollTo (int x, int y) 메소드에 대해 "이 버전은 스크롤을 우리 아이의 경계에 고정시킨다"고 설명한 것으로 보인다.

그래서 더 긴 질문을하기 위해 ScrollView에 포함 된 화면에 많은 뷰를로드 한 다음 프로그래밍 방식으로 전체를 페이지 상단으로 스크롤하여 사용자가 상호 작용할 수 있습니까?

감사!

답변:


264

시험

mainScrollView.fullScroll(ScrollView.FOCUS_UP);

작동해야합니다.


나를 위해 또한 작동합니다. : D
Muntasir Aonik

1
ScrollView # fullScroll ()이 현재 포커스를 변경하는 것을 발견했습니다. EditText로 테스트했습니다.
illusionJJ

175

같은 문제, 아마도 일종의 버그가 있었을 것입니다.

fullScroll(ScrollView.FOCUS_UP)다른 답변의 조차도 효과 가 없었습니다.
나를 위해 일한 것은 scroll_view.smoothScrollTo(0,0)대화 상자가 표시된 직후 에 전화 한 것입니다 .


이것은 처음에는 효과가 있었지만 나중에 다시 반복적으로 시도했을 때 만족스러운 결과를 얻지 못했습니다.
JaydeepW

16
scroll_view.smoothScrollTo (0,0)에서 해결합니다. 목록보기가 측면에 스크롤보기가있을 때 fullScroll (ScrollView.FOCUS_UP)이 작동하지 않습니다.
Kirtikumar A.

1
scroll_view.smoothScrollTo (0,0)은 mainScrollView.fullScroll (ScrollView.FOCUS_UP)보다 나에게 더 효과적이었습니다. 감사!
marienke

2
대부분의 장치에서 fullScroll (ScrollView.FOCUS_UP)이 작동했지만 Nexus 5 및 텍스트 크기가 커진 장치에서 fullSscroll이 작업 표시 줄 아래로 이동하면 smoothScrollTo (0,0)이 모든 장치에서 더 잘 작동했습니다.
jt-gilkeson

또한 fullScroll()이동 후에 선택한 항목을 계속 선택된 상태로 유지한다는 이점이 있습니다 . 을 사용 fullScroll()하면 스크롤보기가 위로 이동하기 전에 선택한 항목과 관계없이 스크롤보기의 첫 번째 항목이 필자의 경우 매번 다시 선택되었습니다.
GeertVc

97

나는 같은 문제가 있었고 이것을 고쳤다. 그것이 당신을 돕기를 바랍니다.

listView.setFocusable(false);

3
이것은 그리드 뷰에 대한 올바른 솔루션입니다. 동일한 뷰 그룹에 둘 이상의 뷰 요소, 특히 목록 또는 그리드 뷰 위에 다른 뷰뷰가있는 경우 발생합니다. 어댑터가 UI 스레드에 알리므로보기가 다시 작성되고 첫 번째 요소까지 스크롤됩니다. listView.setFocusable (false) / gridView.setFocusable (false)를 호출하십시오. xml 파일에서 수행하면 작동하지 않습니다.
omersem

이 솔루션은 내 경우에도 효과가 있었고 NestedScrollView 내부에 RecyclerView가 있으므로 자동으로 아래로 스크롤되었습니다. 고마워요!
Nilesh Rathore

어댑터를 설정하기 전에 이것을 추가해야했지만 그 후에 매력처럼 작동합니다. 감사합니다
Community

완벽한 설명 !!
Borja López '

당신에게 특히 omersem 설명 모두 미구엘하고, 그것은 XML에 설정하면 작동 실 거예요 방법에 대한, 특히 부분 감사, 이것은 나에게 약간의 두통 저장
buradd

53

scrollViewObject.fullScroll(ScrollView.FOCUS_UP)이것은 잘 작동하지만이 줄의 문제는 scrollViewObject에서 데이터가 채워질 때 즉시 호출되었다는 것입니다. 데이터가 채워질 때까지 몇 밀리 초 동안 기다려야합니다. 이 코드를 사용해보십시오 :

scrollViewObject.postDelayed(new Runnable() {
    @Override
    public void run() {
        scroll.fullScroll(ScrollView.FOCUS_UP);
    }
}, 600);

또는

 scrollViewObject.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        scrollViewObject.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        scrollViewObject.fullScroll(View.FOCUS_UP);
    }
});

스크롤보기가 페이지의 맨 아래로 스크롤되어야하는 것과 동일한 문제를 처리하고 있었고 바로 수정했습니다!
Machine Tribe

1
View 객체는 "매직"x 대기 시간 (밀리 초)을 추측하는 대신 위젯이 UI에서 렌더링되면 실행 가능 파일을 게시 할 수있는 post (Runnable) 메소드를 제공합니다.
Ryan

@Ryan : post (Runnable)가 Nexus 5 (Genymotion)에서 항상 작동하지 않습니다
Dika

post infloation 단계 후 데이터를 가져 오면 먼저 스크롤이 작동하고 데이터가 뷰에 채워 지므로 post (Runnable)가 작동하지 않을 수 있습니다. 따라서 postDelayed (Runnable, dummyMillis)를 사용하거나 데이터가 채워진 프로세스 후에 scroll.fullScroll (ScrollView.FOCUS_UP)을 사용해야합니다.
oguzhan

정적 밀리 초를 제공하는 첫 번째 솔루션은 나쁜 접근 방식입니다.
Malwinder Singh

35

이 모든 유효한 솔루션의 주된 문제점은 화면에 스크롤이 그려지지 않은 경우 스크롤을 위로 올리려고한다는 것입니다.

스크롤보기가 화면에 나타날 때까지 기다렸다가 이러한 솔루션 중 하나를 사용하여 위로 스크롤해야합니다. 지연에 대해 신경 쓰지 않기 때문에 postdelay보다 더 나은 솔루션입니다.

    // Wait until my scrollView is ready
    scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Ready, move up
            scrollView.fullScroll(View.FOCUS_UP);
        }
    });

7
좋은 해결책- onGlobalLayout메소드 호출 이 끝날 때 전역 리스너를 제거하는 것을 잊지 마십시오scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Nilhcem

30

아주 쉽게

    ScrollView scroll = (ScrollView) findViewById(R.id.addresses_scroll);
    scroll.setFocusableInTouchMode(true);
    scroll.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);

3
나를 위해 그것은 작동하지 않았습니다 (3 번째 줄), 해결책은 다음과 같습니다. scroll.fullScroll (View.FOCUS_UP); (첫 2 줄 포함)
medskill

@medskill, 안녕하세요, XML 파일로 작성 했습니까? 나는 이것이에서만 작동한다는 것을 잊어 버린다 onCreate().
imknown

@ imknownJ.Kimu xml 파일에서 나를 위해 작동
Paglian

이것은 나를 위해 일했습니다. 두 번째와 세 번째 줄이 모두 필요합니다. XML에서는 작동하지 않습니다.
ET

2
내가 할 수 있다면 나는 당신에게 키스 할 것입니다! 이것에 1-2 시간을 보냈다. 두 개의 목록보기가로드 될 때까지 기다리는 데 가장 적합하며 초점을 맞추고 싶지 않았습니다. onResume ()에 추가했습니다.
John T

24

View Flipper 또는 Dialog에서 Scrollview를 사용하는 경우 동일한 문제 scrollViewObject.fullScroll(ScrollView.FOCUS_UP)가 발생 scrollViewObject.smoothScrollTo(0, 0)했습니다.

스크롤 초점 상단


19
 final ScrollView scrollview = (ScrollView)findViewById(R.id.selected_place_layout_scrollview);

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

9
runOnUiThread( new Runnable(){
   @Override
   public void run(){
      mainScrollView.fullScroll(ScrollView.FOCUS_UP);
   }
}


6

이것은 scrollview에 대한 강제 스크롤입니다 .

            scrollView.post(new Runnable() {
                @Override
                public void run() {
                    scrollView.scrollTo(0, 0);
                    scrollView.pageScroll(View.FOCUS_UP);
                    scrollView.smoothScrollTo(0,0);
                }
            });

4
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Ready, move up
        scrollView.fullScroll(View.FOCUS_UP);
    }
});

1

Kotlin에서 다음과 같이 문제를 해결했습니다.

scrollview.isFocusableInTouchMode = true
scrollview.fullScroll(View.FOCUS_UP)
scrollview.smoothScrollTo(0,0)

0
@SuppressWarnings({ "deprecation", "unchecked" })
public void swipeTopToBottom(AppiumDriver<MobileElement> driver) 
                    throws InterruptedException {
       Dimension dimensions = driver.manage().window().getSize();
        Double screenHeightStart = dimensions.getHeight() * 0.30;
        int scrollStart = screenHeightStart.intValue();
        System.out.println("s="+scrollStart);
        Double screenHeightEnd = dimensions.getHeight()*0.90;
        int scrollEnd = screenHeightEnd.intValue();
        driver.swipe(0,scrollStart,0,scrollEnd,2000);
        CommonUtils.threadWait(driver, 3000);
    }

이것은 확실히 실행될 것이다
Ajeet Gour

이 답변으로 문제를 해결하는 방법에 대한 간단한 설명을 제공하십시오.
Ayberk Özgür
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.