source

Android:보기를 아래로 스크롤합니다.

ittop 2023. 7. 31. 21:51
반응형

Android:보기를 아래로 스크롤합니다.

ScrollView는 맨 아래부터 시작했으면 합니다.방법이 있습니까?

당신은 scroll.post 안에서 다음과 같이 코드를 실행해야 합니다.

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

scroll.fullScroll(View.FOCUS_DOWN)또한 작동해야 합니다.

이것을 a에 넣으시오.scroll.Post(Runnable run)

코틀린 코드

scrollView.post {
   scrollView.fullScroll(View.FOCUS_DOWN)
}

scroll.fullScroll(View.FOCUS_DOWN)초점의 변화로 이어질 것입니다.이렇게 하면 두 개 이상의 포커스 가능한 보기(예: 텍스트 편집)가 있을 때 이상한 동작이 발생합니다.이 질문에 대한 다른 방법이 있습니다.

    View lastChild = scrollLayout.getChildAt(scrollLayout.getChildCount() - 1);
    int bottom = lastChild.getBottom() + scrollLayout.getPaddingBottom();
    int sy = scrollLayout.getScrollY();
    int sh = scrollLayout.getHeight();
    int delta = bottom - (sy + sh);

    scrollLayout.smoothScrollBy(0, delta);

이것은 잘 작동합니다.

코틀린 확장

fun ScrollView.scrollToBottom() {
    val lastChild = getChildAt(childCount - 1)
    val bottom = lastChild.bottom + paddingBottom
    val delta = bottom - (scrollY+ height)        
    smoothScrollBy(0, delta)
}

또는 스크롤하기 전에 맨 아래에 있는지 여부를 확인하기 위해 다음과 같은 작업을 수행할 수 있습니다.

    fun ScrollView.scrollToBottom() {
    val lastChild = children.lastOrNull() ?: return
    val bottom = lastChild.bottom + paddingBottom
    val currentY = height + scrollY
    val alreadyAtBottom = bottom <= currentY
    if (!alreadyAtBottom) {
        val delta = bottom - currentY
        smoothScrollBy(0, delta)
    } else {
        // already at bottom, do nothing
    }
}

때때로 scrollView.post 이 작동하지 않습니다.

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

하지만 scrollView.postDelayed를 사용하면 확실히 작동합니다.

 scrollView.postDelayed(new Runnable() {
        @Override
        public void run() {
            scrollView.fullScroll(ScrollView.FOCUS_DOWN);
        }
    },1000);

나에게 가장 잘 먹힌 것은

scroll_view.post(new Runnable() {
     @Override
     public void run() {
         // This method works but animates the scrolling 
         // which looks weird on first load
         // scroll_view.fullScroll(View.FOCUS_DOWN);

         // This method works even better because there are no animations.
         scroll_view.scrollTo(0, scroll_view.getBottom());
     }
});

저는 일을 완벽하게 하기 위해 증가합니다.

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

메모

이 답변은 정말 오래된 버전의 안드로이드에 대한 해결 방법입니다.오늘은 더 이상 그 버그가 없으므로 당신은 그것을 사용해야 합니다.

저는 그것을 성공적으로 시도했습니다.

scrollView.postDelayed(new Runnable() {
    @Override
    public void run() {
        scrollView.smoothScrollTo(0, scrollView.getHeight());
    }
}, 1000);

아래로 스크롤하는 몇 가지 다른 방법이 있습니다.

fun ScrollView.scrollToBottom() {
    // use this for scroll immediately
    scrollTo(0, this.getChildAt(0).height) 

    // or this for smooth scroll
    //smoothScrollBy(0, this.getChildAt(0).height)

    // or this for **very** smooth scroll
    //ObjectAnimator.ofInt(this, "scrollY", this.getChildAt(0).height).setDuration(2000).start()
}

사용.

이미 배치된 보기를 스크롤하는 경우

my_scroll_view.scrollToBottom()

되지 않은 )onCreate 메드서)...)

my_scroll_view.post { 
   my_scroll_view.scrollToBottom()          
}

보기가 아직 로드되지 않은 경우 스크롤할 수 없습니다.위와 같이 포스트나 슬립콜로 '나중에' 할 수 있지만, 이것은 그다지 우아하지 않습니다.

스크롤을 계획하고 다음 레이아웃()에서 실행하는 것이 좋습니다.여기 코드 예제:

https://stackoverflow.com/a/10209457/1310343

한 가지 고려해야 할 것은 설정하지 말아야 할 것입니다.자식 컨트롤, 특히 EditText 컨트롤에 RequestFocus 속성이 설정되어 있지 않은지 확인합니다.이 속성은 레이아웃에서 마지막으로 해석되는 속성 중 하나일 수 있으며 부모(레이아웃 또는 ScrollView)의 중력 설정을 재정의합니다.

질문에 대한 정확한 대답은 아니지만, 편집 텍스트가 포커스를 얻자마자 아래로 스크롤해야 했습니다.그러나 승인된 답변은 ET의 초점을 즉시 잃게 할 것입니다(ScrollView로 가정합니다).

해결 방법은 다음과 같습니다.

emailEt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if(hasFocus){
            Toast.makeText(getActivity(), "got the focus", Toast.LENGTH_LONG).show();
            scrollView.postDelayed(new Runnable() {
                @Override
                public void run() {
                    scrollView.fullScroll(ScrollView.FOCUS_DOWN);
                }
            }, 200);
        }else {
            Toast.makeText(getActivity(), "lost the focus", Toast.LENGTH_LONG).show();
        }
    }
});

실제로 fullScroll을 두 번 호출하면 다음과 같은 효과가 있다는 것을 알게 되었습니다.

myScrollView.fullScroll(View.FOCUS_DOWN);

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

첫 번째(성공하지 못한) 스크롤을 수행한 직후 post() 메서드가 활성화된 것과 관련이 있을 수 있습니다.이러한 동작은 myScrollView에서 이전 메서드를 호출한 후에 발생하므로 첫 번째 fullScroll() 메서드를 사용자와 관련이 있을 수 있는 다른 메서드로 대체할 수 있습니다.

코틀린 코루틴으로 이것을 하는 또 다른 멋진 방법이 있습니다.실행 가능(지연 후/지연 후)이 있는 처리기와 반대되는 코루틴을 사용하는 장점은 지연된 작업을 실행하기 위해 값비싼 스레드를 실행하지 않는다는 것입니다.

launch(UI){
    delay(300)
    scrollView.fullScroll(View.FOCUS_DOWN)
}

코루틴의 처리기 컨텍스트를 UI로 지정하는 것이 중요합니다. 그렇지 않으면 UI 스레드에서 지연된 작업이 호출되지 않을 수 있습니다.

이 경우 scroll.scrollTo(0, sc.getBottom()만 사용하면 작동하지 않습니다. scroll.post 을 사용하여 사용하십시오.

예:

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

한 가지 가능한 이유는scroll.fullScroll(View.FOCUS_DOWN)에 싸여도 작동하지 않을 수 있습니다..post()뷰가 배치되지 않았다는 것입니다.경우 View.doOnLayout()이 더 나은 옵션이 될 수 있습니다.

scroll.doOnLayout(){
    scroll.fullScroll(View.FOCUS_DOWN)
}

아니면, 용감한 영혼들을 위해 더 정교한 것: https://chris.banes.dev/2019/12/03/suspending-views/

모든 답변을 조합하여 유용하게 사용할 수 있었습니다.

확장 기능 게시 지연

private fun ScrollView.postDelayed(
    time: Long = 325, // ms
    block: ScrollView.() -> Unit
) {
    postDelayed({block()}, time)
}

확장 기능 측정스크롤 높이

fun ScrollView.measureScrollHeight(): Int {
    val lastChild = getChildAt(childCount - 1)
    val bottom = lastChild.bottom + paddingBottom
    val delta = bottom - (scrollY+ height)
    return delta
}

확장 기능 아래로 스크롤

fun ScrollView.scrollToBottom() {
    postDelayed {
        smoothScrollBy(0, measureScrollHeight())
    }
}

최소 지연 시간은 325ms 이상이어야 합니다. 그렇지 않으면 스크롤이 작동하지 않습니다(전체 하단으로 스크롤하지 않음).현재 높이와 하단 사이의 델타가 클수록 지연 시간이 커야 합니다.

여기에 있는 몇몇 사람들은 scrollView.post 이 작동하지 않는다고 말했습니다.

ScrollView.postDelayed를 사용하지 않으려면 수신기를 사용하는 방법도 있습니다.다음은 다른 사용 사례에서 수행한 작업입니다.

ViewTreeObserver.OnPreDrawListener viewVisibilityChanged = new ViewTreeObserver.OnPreDrawListener() {
    @Override
    public boolean onPreDraw() {
        if (my_view.getVisibility() == View.VISIBLE) {
            scroll_view.smoothScrollTo(0, scroll_view.getHeight());
        }
        return true;
    }
};

다음과 같은 방법으로 보기에 추가할 수 있습니다.

my_view.getViewTreeObserver().addOnPreDrawListener(viewVisibilityChanged);

최소 SDK가 29 이상이면 다음을 사용할 수 있습니다.

View childView = findViewById(R.id.your_view_id_in_the_scroll_view)
if(childView != null){
  scrollview.post(() -> scrollview.scrollToDescendant(childView));
}

이것은 즉시 작동합니다.지체 없이.

// wait for the scroll view to be laid out
scrollView.post(new Runnable() {
  public void run() {
    // then wait for the child of the scroll view (normally a LinearLayout) to be laid out
    scrollView.getChildAt(0).post(new Runnable() {
      public void run() {
        // finally scroll without animation
        scrollView.scrollTo(0, scrollView.getBottom());
      }
    }
  }
}

언급URL : https://stackoverflow.com/questions/3080402/android-scrollview-force-to-bottom

반응형