스크롤 보기를 특정 편집 텍스트로 프로그래밍 방식으로 스크롤하는 방법이 있습니까?
스크롤 보기를 사용하여 매우 긴 작업을 수행합니다.사용자가 입력해야 하는 다양한 필드가 있는 양식입니다.양식 중간에 확인란이 있으며 사용자가 확인하면 보기의 특정 부분으로 스크롤하고 싶습니다.EditText 개체(또는 다른 보기 개체)로 프로그래밍 방식으로 스크롤할 수 있는 방법이 있습니까?
또한 X 좌표와 Y 좌표를 사용하면 가능하다는 것을 알고 있지만 양식이 사용자마다 변경될 수 있기 때문에 이 작업은 피하고 싶습니다.
private final void focusOnView(){
yourScrollView.post(new Runnable() {
@Override
public void run() {
yourScrollView.scrollTo(0, yourEditText.getBottom());
}
});
}
보기를 스크롤 보기의 중앙으로 스크롤하려면 Sherrifel Khatib의 응답이 크게 향상될 수 있습니다.이 재사용 가능한 방법은 보기를 수평 스크롤 보기의 눈에 보이는 중심까지 부드럽게 스크롤합니다.
private final void focusOnView(final HorizontalScrollView scroll, final View view) {
new Handler().post(new Runnable() {
@Override
public void run() {
int vLeft = view.getLeft();
int vRight = view.getRight();
int sWidth = scroll.getWidth();
scroll.smoothScrollTo(((vLeft + vRight - sWidth) / 2), 0);
}
});
}
직의 경우수의 ScrollView
사용하다
...
int vTop = view.getTop();
int vBottom = view.getBottom();
int sHeight = scroll.getBottom();
scroll.smoothScrollTo(0, ((vTop + vBottom - sHeight) / 2));
...
이것은 나에게 잘 맞습니다.
targetView.getParent().requestChildFocus(targetView,targetView);
public voidRequestChildFocus(하위 보기, 집중 보기)
자식 - 포커스를 원하는 이 부모 보기의 자식입니다.이 보기에는 포커스가 지정된 보기가 포함됩니다.실제로 초점을 맞추는 것은 반드시 관점이 아닙니다.
집중 - 실제로 초점을 맞춘 어린이의 후손이라는 관점
제 생각에 주어진 직사각형으로 스크롤하는 가장 좋은 방법은 을 사용하는 것입니다.당신은 그것을 전화로 해야 합니다.View
화면에 표시할 로컬 직사각형으로 스크롤하여 통과합니다.는 " 두번매변는다같합아니다야과음수개째합▁be다▁should"false
과 원한롤을위해스크활▁smooth.true
즉시 스크롤할 수 있습니다.
final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
view.requestRectangleOnScreen(rect, false);
저는 WarrenFaith의 답변을 기반으로 작은 유틸리티 방법을 만들었습니다. 이 코드는 스크롤 뷰에 해당 보기가 이미 표시되어 있으면 스크롤이 필요하지 않은 경우에도 고려합니다.
public static void scrollToView(final ScrollView scrollView, final View view) {
// View needs a focus
view.requestFocus();
// Determine if scroll needs to happen
final Rect scrollBounds = new Rect();
scrollView.getHitRect(scrollBounds);
if (!view.getLocalVisibleRect(scrollBounds)) {
new Handler().post(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, view.getBottom());
}
});
}
}
은 당신의 것을 .TextView
요청 포커스:
mTextView.requestFocus();
또 다른 변형은 다음과 같습니다.
scrollView.postDelayed(new Runnable()
{
@Override
public void run()
{
scrollView.smoothScrollTo(0, img_transparent.getTop());
}
}, 200);
또는 사용할 수 있습니다.post()
방법.
내 편집 텍스트는 레이아웃의 루트 뷰가 아닌 ScrollView 내부에 여러 개의 레이어가 중첩되어 있습니다.getTop()과 getBottom()이 포함된 뷰 내의 좌표를 보고하는 것 같았기 때문에 EditText의 부모를 통해 반복하여 ScrollView 상단에서 EditText 상단까지의 거리를 계산하도록 했습니다.
// Scroll the view so that the touched editText is near the top of the scroll view
new Thread(new Runnable()
{
@Override
public
void run ()
{
// Make it feel like a two step process
Utils.sleep(333);
// Determine where to set the scroll-to to by measuring the distance from the top of the scroll view
// to the control to focus on by summing the "top" position of each view in the hierarchy.
int yDistanceToControlsView = 0;
View parentView = (View) m_editTextControl.getParent();
while (true)
{
if (parentView.equals(scrollView))
{
break;
}
yDistanceToControlsView += parentView.getTop();
parentView = (View) parentView.getParent();
}
// Compute the final position value for the top and bottom of the control in the scroll view.
final int topInScrollView = yDistanceToControlsView + m_editTextControl.getTop();
final int bottomInScrollView = yDistanceToControlsView + m_editTextControl.getBottom();
// Post the scroll action to happen on the scrollView with the UI thread.
scrollView.post(new Runnable()
{
@Override
public void run()
{
int height =m_editTextControl.getHeight();
scrollView.smoothScrollTo(0, ((topInScrollView + bottomInScrollView) / 2) - height);
m_editTextControl.requestFocus();
}
});
}
}).start();
ScrollView가 ChildView의 직접 상위 항목인 경우 위의 답변이 제대로 작동합니다.ScrollView에서 ChildView가 다른 ViewGroup으로 감싸여 있는 경우 View.getTop()이 상위 항목에 상대적인 위치를 얻기 때문에 예기치 않은 동작이 발생합니다.이 경우 다음을 구현해야 합니다.
public static void scrollToInvalidInputView(ScrollView scrollView, View view) {
int vTop = view.getTop();
while (!(view.getParent() instanceof ScrollView)) {
view = (View) view.getParent();
vTop += view.getTop();
}
final int scrollPosition = vTop;
new Handler().post(() -> scrollView.smoothScrollTo(0, scrollPosition));
}
더 나은 대답을 하기에는 너무 늦었지만 원하는 완벽한 솔루션은 포지셔너와 같은 시스템이어야 합니다.제 말은, 시스템이 편집기 필드를 위한 위치를 만들 때, 키보드까지 필드를 배치하기 때문에 UI/UX 규칙에 따라 완벽합니다.
아래 코드는 안드로이드 웨이 포지셔닝을 원활하게 합니다.우선 현재 스크롤 포인트를 참조 포인트로 유지합니다.두 번째는 편집자에게 가장 적합한 위치 지정 스크롤 지점을 찾는 것입니다. 이렇게 하려면 맨 위로 스크롤한 다음 편집자 필드에 ScrollView 구성 요소를 가장 적합한 위치 지정을 하도록 요청합니다.갓챠!우리는 최고의 위치를 배웠습니다.이제 이전 지점에서 새로 찾은 지점까지 부드럽게 스크롤합니다.원하는 경우 smoothScrollTo만 사용하는 대신 scrollTo를 사용하여 smooth스크롤을 생략할 수 있습니다.
참고: 주 컨테이너 ScrollView는 scrollViewSignup이라는 이름의 멤버 필드입니다. 이 예는 많은 것을 알 수 있듯이 등록 화면이었기 때문입니다.
view.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(final View view, boolean b) {
if (b) {
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);
}
});
}
}
});
모든 EditText 인스턴스에 대해 이 블록을 사용하고 화면 코드와 신속하게 통합하려면 이 블록을 사용합니다.아래와 같이 간단히 트래버서를 만들 수 있습니다.이를 위해 메인 OnFocusChangeListener를 FocusChangeListenerToScrollEditor라는 이름의 멤버 필드로 만들고 아래와 같이 onCreate에서 호출합니다.
traverseEditTextChildren(scrollViewSignup, focusChangeListenerToScrollEditor);
그리고 방법 구현은 아래와 같습니다.
private void traverseEditTextChildren(ViewGroup viewGroup, View.OnFocusChangeListener focusChangeListenerToScrollEditor) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = viewGroup.getChildAt(i);
if (view instanceof EditText)
{
((EditText) view).setOnFocusChangeListener(focusChangeListenerToScrollEditor);
}
else if (view instanceof ViewGroup)
{
traverseEditTextChildren((ViewGroup) view, focusChangeListenerToScrollEditor);
}
}
}
여기서는 모든 EditText 인스턴스 아이들이 청취자를 포커스에 맞게 호출하도록 합니다.
이 솔루션에 도달하기 위해 여기에 있는 모든 솔루션을 확인하고 더 나은 UI/UX 결과를 위한 새로운 솔루션을 생성했습니다.
다른 모든 답변에 많은 영감을 주셔서 감사합니다.
yourScrollView.smoothScrollTo(0, yourEditText.getTop());
Just Do It ;)
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, myTextView.getTop());
}
});
실제 프로젝트에서 답변하는 중입니다.
다음을 사용하여 보다 우아하고 오류가 발생하기 쉬운 솔루션을 찾은 것 같습니다.
수학은 포함되지 않으며, 제안된 다른 솔루션과는 달리 위 아래로 스크롤하는 것을 올바르게 처리합니다.
/**
* Will scroll the {@code scrollView} to make {@code viewToScroll} visible
*
* @param scrollView parent of {@code scrollableContent}
* @param scrollableContent a child of {@code scrollView} whitch holds the scrollable content (fills the viewport).
* @param viewToScroll a child of {@code scrollableContent} to whitch will scroll the the {@code scrollView}
*/
void scrollToView(ScrollView scrollView, ViewGroup scrollableContent, View viewToScroll) {
Rect viewToScrollRect = new Rect(); //coordinates to scroll to
viewToScroll.getHitRect(viewToScrollRect); //fills viewToScrollRect with coordinates of viewToScroll relative to its parent (LinearLayout)
scrollView.requestChildRectangleOnScreen(scrollableContent, viewToScrollRect, false); //ScrollView will make sure, the given viewToScrollRect is visible
}
로 포장하는 것이 좋습니다.postDelayed
할 수 있게 하기 , 더신할수하위해기만, .ScrollView
입니다.
/**
* Will scroll the {@code scrollView} to make {@code viewToScroll} visible
*
* @param scrollView parent of {@code scrollableContent}
* @param scrollableContent a child of {@code scrollView} whitch holds the scrollable content (fills the viewport).
* @param viewToScroll a child of {@code scrollableContent} to whitch will scroll the the {@code scrollView}
*/
private void scrollToView(final ScrollView scrollView, final ViewGroup scrollableContent, final View viewToScroll) {
long delay = 100; //delay to let finish with possible modifications to ScrollView
scrollView.postDelayed(new Runnable() {
public void run() {
Rect viewToScrollRect = new Rect(); //coordinates to scroll to
viewToScroll.getHitRect(viewToScrollRect); //fills viewToScrollRect with coordinates of viewToScroll relative to its parent (LinearLayout)
scrollView.requestChildRectangleOnScreen(scrollableContent, viewToScrollRect, false); //ScrollView will make sure, the given viewToScrollRect is visible
}
}, delay);
}
참조: https://stackoverflow.com/a/6438240/2624806
팔로잉이 훨씬 더 잘 작동했습니다.
mObservableScrollView.post(new Runnable() {
public void run() {
mObservableScrollView.fullScroll([View_FOCUS][1]);
}
});
Android 소스 코드를 조사해 보면 이미 다음의 멤버 기능이 있음을 알 수 있습니다.ScrollView
–scrollToChild(View)
그게 정확히 요청한 것을 해줍니다.유감스럽게도 이 기능은 몇 가지 모호한 이유로 표시되어 있습니다.private
그 함수를 기반으로 첫 번째 함수를 찾는 다음 함수를 작성했습니다.ScrollView
보다 위에View
매개 변수로 지정하고 스크롤하여 내부에서 볼 수 있도록 합니다.ScrollView
:
private void make_visible(View view)
{
int vt = view.getTop();
int vb = view.getBottom();
View v = view;
for(;;)
{
ViewParent vp = v.getParent();
if(vp == null || !(vp instanceof ViewGroup))
break;
ViewGroup parent = (ViewGroup)vp;
if(parent instanceof ScrollView)
{
ScrollView sv = (ScrollView)parent;
// Code based on ScrollView.computeScrollDeltaToGetChildRectOnScreen(Rect rect) (Android v5.1.1):
int height = sv.getHeight();
int screenTop = sv.getScrollY();
int screenBottom = screenTop + height;
int fadingEdge = sv.getVerticalFadingEdgeLength();
// leave room for top fading edge as long as rect isn't at very top
if(vt > 0)
screenTop += fadingEdge;
// leave room for bottom fading edge as long as rect isn't at very bottom
if(vb < sv.getChildAt(0).getHeight())
screenBottom -= fadingEdge;
int scrollYDelta = 0;
if(vb > screenBottom && vt > screenTop)
{
// need to move down to get it in view: move down just enough so
// that the entire rectangle is in view (or at least the first
// screen size chunk).
if(vb-vt > height) // just enough to get screen size chunk on
scrollYDelta += (vt - screenTop);
else // get entire rect at bottom of screen
scrollYDelta += (vb - screenBottom);
// make sure we aren't scrolling beyond the end of our content
int bottom = sv.getChildAt(0).getBottom();
int distanceToBottom = bottom - screenBottom;
scrollYDelta = Math.min(scrollYDelta, distanceToBottom);
}
else if(vt < screenTop && vb < screenBottom)
{
// need to move up to get it in view: move up just enough so that
// entire rectangle is in view (or at least the first screen
// size chunk of it).
if(vb-vt > height) // screen size chunk
scrollYDelta -= (screenBottom - vb);
else // entire rect at top
scrollYDelta -= (screenTop - vt);
// make sure we aren't scrolling any further than the top our content
scrollYDelta = Math.max(scrollYDelta, -sv.getScrollY());
}
sv.smoothScrollBy(0, scrollYDelta);
break;
}
// Transform coordinates to parent:
int dy = parent.getTop()-parent.getScrollY();
vt += dy;
vb += dy;
v = parent;
}
}
내 솔루션은 다음과(와)
int[] spinnerLocation = {0,0};
spinner.getLocationOnScreen(spinnerLocation);
int[] scrollLocation = {0, 0};
scrollView.getLocationInWindow(scrollLocation);
int y = scrollView.getScrollY();
scrollView.smoothScrollTo(0, y + spinnerLocation[1] - scrollLocation[1]);
세로 스크롤, 양식에 적합합니다.정답은 아마달리발로치 가로 스크롤을 기반으로 합니다.
private final void focusOnView(final HorizontalScrollView scroll, final View view) {
new Handler().post(new Runnable() {
@Override
public void run() {
int top = view.getTop();
int bottom = view.getBottom();
int sHeight = scroll.getHeight();
scroll.smoothScrollTo(0, ((top + bottom - sHeight) / 2));
}
});
}
사용할 수 있습니다.ObjectAnimator
다음과 같이:
ObjectAnimator.ofInt(yourScrollView, "scrollY", yourView.getTop()).setDuration(1500).start();
getTop()이 0을 반환하지 않도록 보기에 postDelayed를 추가합니다.
binding.scrollViewLogin.postDelayed({
val scrollTo = binding.textInputLayoutFirstName.top
binding.scrollViewLogin.isSmoothScrollingEnabled = true
binding.scrollViewLogin.smoothScrollTo(0, scrollTo)
}, 400
)
또한 보기가 scrollView의 직접 자식인지 확인하십시오. 그렇지 않으면 Top()이 0으로 표시됩니다.예: TextInputLayout에 포함된 편집 텍스트의 getTop()은 0을 반환합니다.따라서 이 경우 ScrollView의 직접 자식인 TextInputLayout의 getTop()을 계산해야 합니다.
<ScrollView>
<TextInputLayout>
<EditText/>
</TextInputLayout>
</ScrollView>
저 같은 경우에는 그렇지 않습니다.EditText
,그건.googleMap
그리고 이렇게 성공적으로 작동합니다.
private final void focusCenterOnView(final ScrollView scroll, final View view) {
new Handler().post(new Runnable() {
@Override
public void run() {
int centreX=(int) (view.getX() + view.getWidth() / 2);
int centreY= (int) (view.getY() + view.getHeight() / 2);
scrollView.smoothScrollBy(centreX, centreY);
}
});
}
Q: 스크롤 보기를 특정 편집 텍스트로 프로그래밍 방식으로 스크롤하는 방법이 있습니까?
답변: 레코드 데이터가 추가된 재활용기 보기 마지막 위치의 중첩 스크롤 보기입니다.
adapter.notifyDataSetChanged();
nested_scroll.setScrollY(more Detail Recycler.getBottom());
스크롤 보기를 특정 편집 텍스트로 프로그래밍 방식으로 스크롤하는 방법이 있습니까?
다음은 제가 사용하는 것입니다.
int amountToScroll = viewToShow.getBottom() - scrollView.getHeight() + ((LinearLayout.LayoutParams) viewToShow.getLayoutParams()).bottomMargin;
// Check to see if scrolling is necessary to show the view
if (amountToScroll > 0){
scrollView.smoothScrollTo(0, amountToScroll);
}
그러면 뷰 하단의 여백을 포함하여 뷰 하단을 표시하는 데 필요한 스크롤 양이 표시됩니다.
Sherrif의 답변에 따르면, 다음은 제 사용 사례에 가장 적합했습니다.주목할 만한 변화는getTop()
대신에getBottom()
그리고.smoothScrollTo()
대신에scrollTo()
.
private void scrollToView(final View view){
final ScrollView scrollView = findViewById(R.id.bookmarksScrollView);
if(scrollView == null) return;
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, view.getTop());
}
});
}
소프트 키보드를 열 때 보기로 스크롤하려는 경우 보기가 다소 까다로울 수 있습니다.지금까지 제가 가진 가장 좋은 해결책은 삽입 콜백과requestRectangleOnScreen
방법.
먼저 콜백을 설정해야 합니다.
fun View.doOnApplyWindowInsetsInRoot(block: (View, WindowInsetsCompat, Rect) -> Unit) {
val initialPadding = recordInitialPaddingForView(this)
val root = getRootForView(this)
ViewCompat.setOnApplyWindowInsetsListener(root) { v, insets ->
block(v, insets, initialPadding)
insets
}
requestApplyInsetsWhenAttached()
}
fun View.requestApplyInsetsWhenAttached() {
if (isAttachedToWindow) {
requestApplyInsets()
} else {
addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
v.removeOnAttachStateChangeListener(this)
v.requestApplyInsets()
}
override fun onViewDetachedFromWindow(v: View) = Unit
})
}
}
호출을 확인하기 위해 루트 뷰에 콜백을 설정하고 있습니다.해당 뷰가 수신하기 전에 인셋이 소모될 수 있으므로 여기서 추가 작업을 해야 합니다.
이제 거의 쉬워졌습니다.
doOnApplyWindowInsetsInRoot { _, _, _ ->
post {
if (viewInQuestion.hasFocus()) {
requestRectangleOnScreen(Rect(0, 0, width, height))
}
}
}
포커스 체크를 없앨 수 있습니다.통화 수를 제한하기 위해 사용됩니다.requestRectangleOnScreen
사용합니다post
예약된 상위 항목을 포커스가 있는 보기로 스크롤한 후 작업을 실행합니다.
코틀린 버전을 찾고 있는 사람이 있다면 확장 기능으로 이 작업을 수행할 수 있습니다.
fun ScrollView.scrollToChild(view: View, onScrolled: (() -> Unit)? = null) {
view.requestFocus()
val scrollBounds = Rect()
getHitRect(scrollBounds)
if (!view.getLocalVisibleRect(scrollBounds)) {
findViewTreeLifecycleOwner()?.lifecycleScope?.launch(Dispatchers.Main) {
smoothScrollTo(0, view.bottom - 40)
onScrolled?.invoke()
}
}
}
스크롤 후에 무언가를 할 수 있는 작은 콜백이 있습니다.
한다면scrlMain
의 신의입니다.NestedScrollView
그런 다음 다음을 사용합니다.
scrlMain.post(new Runnable() {
@Override
public void run() {
scrlMain.fullScroll(View.FOCUS_UP);
}
});
효율적인 스크롤을 위한 또 다른 더 나은 버전이 있습니다.
스크롤 뷰에 추가된 특정 뷰 위치로 스크롤하는 코틀린 코드(추가)
horizontalScrollView.post {
val targetView = findViewById<View>(R.id.target_view)
val targetX = targetView.left
horizontalScrollView.smoothScrollTo(targetX, 0)
}
수직 스크롤의 경우 다음으로 변경합니다.
JAVA의 경우 다음은 샘플 코드입니다.
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
int targetViewY = targetView.getTop();
scrollView.smoothScrollTo(0, targetViewY);
}
}, 500);
언급URL : https://stackoverflow.com/questions/6831671/is-there-a-way-to-programmatically-scroll-a-scroll-view-to-a-specific-edit-text
'bestsource' 카테고리의 다른 글
HTML5 테이블에서 셀 패딩, 셀 간격, 유효성 검사 및 정렬을 대체하는 것은 무엇입니까? (0) | 2023.08.17 |
---|---|
R 마크다운, SQL 코드 청크가 구문 오류를 생성합니다. (0) | 2023.08.12 |
심포니 만들기:마이그레이션: 메타데이터 저장소가 최신이 아닙니다. 이 문제를 해결하려면 sync-metadata-storage 명령을 실행하십시오. (0) | 2023.08.12 |
JavaScript로 브라우저에서 Android 전화기 회전 감지 (0) | 2023.08.12 |
봄에 어떤 종류의 "이벤트 버스"를 이용합니까?빌트인, 리액터, 아카? (0) | 2023.08.12 |