스크롤보기로 매우 긴 활동이 있습니다. 사용자가 작성 해야하는 다양한 필드가있는 양식입니다. 양식의 절반 아래에 확인란이 있으며 사용자가 확인하면보기의 특정 부분으로 스크롤하고 싶습니다. 프로그래밍 방식으로 EditText 객체 (또는 다른 뷰 객체)로 스크롤하는 방법이 있습니까?
또한 X 및 Y 좌표를 사용하여 이것이 가능하다는 것을 알고 있지만 양식이 사용자마다 변경 될 수 있으므로이 작업을 피하고 싶습니다.
스크롤보기로 매우 긴 활동이 있습니다. 사용자가 작성 해야하는 다양한 필드가있는 양식입니다. 양식의 절반 아래에 확인란이 있으며 사용자가 확인하면보기의 특정 부분으로 스크롤하고 싶습니다. 프로그래밍 방식으로 EditText 객체 (또는 다른 뷰 객체)로 스크롤하는 방법이 있습니까?
또한 X 및 Y 좌표를 사용하여 이것이 가능하다는 것을 알고 있지만 양식이 사용자마다 변경 될 수 있으므로이 작업을 피하고 싶습니다.
답변:
private final void focusOnView(){
your_scrollview.post(new Runnable() {
@Override
public void run() {
your_scrollview.scrollTo(0, your_EditBox.getBottom());
}
});
}
your_scrollview.post(...
보기를 스크롤보기의 중앙으로 스크롤 하려는 경우 Sherif elKhatib의 대답을 크게 향상시킬 수 있습니다 . 이 재사용 가능한 메소드는 뷰를 HorizontalScrollView의 보이는 중심으로 부드럽게 스크롤합니다.
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(((vTop + vBottom - sHeight) / 2), 0);
...
이것은 나를 위해 잘 작동합니다 :
targetView.getParent().requestChildFocus(targetView,targetView);
public void RequestChildFocus (자식보기, 초점보기)
아이 - 초점을 원하는이 ViewParent의 아이입니다. 이 뷰에는 포커스 된 뷰가 포함됩니다. 실제로 포커스가있는 것은 아닙니다.
집중 -실제로 초점이있는 자녀의 후손
내 의견으로는 주어진 사각형으로 스크롤하는 가장 좋은 방법은 View.requestRectangleOnScreen(Rect, Boolean)
입니다. View
스크롤하려는 화면에서 호출 하고 화면에 표시하려는 로컬 사각형을 전달해야합니다. 두 번째 매개 변수는 false
부드러운 스크롤 및 true
즉각적인 스크롤을위한 것이어야합니다 .
final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
view.requestRectangleOnScreen(rect, false);
scrollview.smoothScrollTo
필요한보기가 화면 밖에서 작동하지 않으면 작동하지 않습니다 (sdk 버전 26의 Android 에뮬레이터에서 시도)
new Handler().post()
?
나는 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());
}
});
}
}
scrollBounds
의 매개 변수가되어야한다고 생각 합니다 scrollView.getHitRect
.
TextView
요청에 집중 해야합니다 .
mTextView.requestFocus();
내 EditText는 내 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.postDelayed(new Runnable()
{
@Override
public void run()
{
scrollView.smoothScrollTo(0, img_transparent.getTop());
}
}, 2000);
또는 post()
방법을 사용할 수 있습니다 .
나는 이것이 더 나은 대답을하기에는 너무 늦을 수도 있지만 원하는 완벽한 솔루션은 포지셔너와 같은 시스템이어야합니다. 내 말은, 시스템이 Editor 필드의 위치를 지정할 때 UI / UX 규칙처럼 완벽하게 키보드까지 필드를 배치합니다.
아래 코드는 안드로이드 방식을 부드럽게 배치하는 것입니다. 우선 현재 스크롤 포인트를 참조 포인트로 유지합니다. 두 번째는 편집기에 가장 적합한 위치 지정 스크롤 포인트를 찾고이를 위해 맨 위로 스크롤 한 다음 ScrollView 구성 요소가 최상의 위치 지정을 수행하도록 편집기 필드를 요청하는 것입니다. 가차! 우리는 최고의 위치를 배웠습니다. 이제 우리가 할 일은 이전 지점에서 새로 찾은 지점으로 부드럽게 스크롤하는 것입니다. 원하는 경우 smoothScrollTo 대신 scrollTo 를 사용하여 부드러운 스크롤을 생략 할 수 있습니다. .
참고 : 메인 컨테이너 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 결과를위한 새로운 솔루션을 생성했습니다.
다른 모든 답변 덕분에 많은 영감을 얻었습니다.
ScrollView가 ChildView의 직접적인 부모이면 위의 답변이 제대로 작동합니다. ChildView가 ScrollView의 다른 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));
}
참조 : https://stackoverflow.com/a/6438240/2624806
다음은 훨씬 잘 작동했습니다.
mObservableScrollView.post(new Runnable() {
public void run() {
mObservableScrollView.fullScroll([View_FOCUS][1]);
}
});
나는 더 우아하고 오류가 발생하기 쉬운 솔루션을 사용했다고 생각합니다.
관련된 수학이 없으며 다른 제안 된 솔루션과 달리 위아래로 스크롤을 올바르게 처리합니다.
/**
* 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);
}
안드로이드 소스 코드를 살펴보면 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;
}
}
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, myTextView.getTop());
}
});
내 실제 프로젝트에서 응답합니다.
내 경우에는, 그 아니에요 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);
}
});
}
Que : 프로그래밍 방식으로 스크롤보기를 특정 편집 텍스트로 스크롤하는 방법이 있습니까?
Ans : recyclerview의 마지막 스크롤보기에 레코드 데이터가 추가되었습니다.
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);
}
뷰의 맨 아래에있는 여백을 포함하여 뷰의 맨 아래를 표시하는 데 필요한 스크롤 양을 가져옵니다.
세로 스크롤, 양식에 적합합니다. 대답은 Ahmadalibaloch 가로 스크롤을 기반으로합니다.
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));
}
});
}
HorizontalScrollView
이 방법으로 반드시 사용해야 합니까?
Sherif의 답변을 바탕으로 다음은 내 유스 케이스에 가장 효과적이었습니다. 주목할만한 변경 사항은 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());
}
});
}
the form may changed from user to user
하지만 당신은 그냥 사용할 수 있습니다mEditView.getTop();