Подтвердить что ты не робот

Прокрутите до определенного вида в режиме прокрутки

Я добавил scrollview и подчинды внутри scrollview. В какой-то момент мне нужно перейти к определенному виду.

<scrollview>

1. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

2. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

3. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

4. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

5. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

6. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

7. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

   <button>
   </button>

 </scrollview>

Вышеуказанный макет был создан динамически. поэтому я не могу опубликовать xml файл. Создание макета полностью динамично. Даже число детского представления внутри линейного расслоения также может меняться.

Поэтому, когда я нажимаю на кнопку, мне нужно прокрутить ее до определенного вида, скажем, здесь, когда я нажимаю кнопку, мне нужно прокрутить до линейного макета. Я попробовал метод scrollTo, но он прокручивается до верхней части прокрутки.

Просьба представить несколько предложений.

4b9b3361

Ответ 1

Это должно сделать трюк:

View targetView = findViewById(R.id.DESIRED_VIEW_ID);  
targetView.getParent().requestChildFocus(targetView,targetView);

public void RequestChildFocus (просмотр дочернего объекта, просмотр сфокусирован)

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

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

Ответ 2

Если ребенок, к которому мы должны перейти, не является прямым ребенком, то вышеуказанные решения не работают

Я использовал приведенное ниже решение в своем проекте, и делиться им может быть полезно другим

/**
 * Used to scroll to the given view.
 *
 * @param scrollViewParent Parent ScrollView
 * @param view View to which we need to scroll.
 */
private void scrollToView(final ScrollView scrollViewParent, final View view) {
    // Get deepChild Offset
    Point childOffset = new Point();
    getDeepChildOffset(scrollViewParent, view.getParent(), view, childOffset);
    // Scroll to child.
    scrollViewParent.smoothScrollTo(0, childOffset.y);
}

/**
 * Used to get deep child offset.
 * <p/>
 * 1. We need to scroll to child in scrollview, but the child may not the direct child to scrollview.
 * 2. So to get correct child position to scroll, we need to iterate through all of its parent views till the main parent.
 *
 * @param mainParent        Main Top parent.
 * @param parent            Parent.
 * @param child             Child.
 * @param accumulatedOffset Accumulated Offset.
 */
private void getDeepChildOffset(final ViewGroup mainParent, final ViewParent parent, final View child, final Point accumulatedOffset) {
    ViewGroup parentGroup = (ViewGroup) parent;
    accumulatedOffset.x += child.getLeft();
    accumulatedOffset.y += child.getTop();
    if (parentGroup.equals(mainParent)) {
        return;
    }
    getDeepChildOffset(mainParent, parentGroup.getParent(), parentGroup, accumulatedOffset);
}

Ответ 3

попробуйте следующее:

ScrollView sv = // your scrollview
View insideView = // find the View that you need to scroll to which is inside this ScrollView
sv.scrollTo(0, (int)insideView.getY());

insideView.getY() не будет работать ниже уровня API 11, для уровня API ниже 11 вы можете заменить insideView.getY() на insideView.getTop()

Ответ 4

Я думаю, что нашел более элегантное решение с ошибкой, используя

ScrollView.requestChildRectangleOnScreen

Нет вовлеченной математики, и вопреки другим предлагаемым решениям она будет обрабатывать правильную прокрутку в обоих направлениях вверх и вниз.

void scrollToRow(ScrollView scrollView, LinearLayout linearLayout, TextView textViewToShow) {
    Rect textRect = new Rect(); //coordinates to scroll to
    textViewToShow.getHitRect(textRect); //fills textRect with coordinates of TextView relative to its parent (LinearLayout) 
    scrollView.requestChildRectangleOnScreen(linearLayout, textRect, false); //ScrollView will make sure, the given textRect is visible
}

Это хорошая идея, чтобы превратить его в postDelayed, чтобы сделать его более надежным, в случае, если ScrollView изменяется в данный момент

private void scrollToRow(final ScrollView scrollView, final LinearLayout linearLayout, final TextView textViewToShow) {
    long delay = 100; //delay to let finish with possible modifications to ScrollView
    scrollView.postDelayed(new Runnable() {
        public void run() {
            Rect textRect = new Rect(); //coordinates to scroll to
            textViewToShow.getHitRect(textRect); //fills textRect with coordinates of TextView relative to its parent (LinearLayout) 
            scrollView.requestChildRectangleOnScreen(linearLayout, textRect, false); //ScrollView will make sure, the given textRect is visible
        }
    }, delay);
}

Просто славный isn`t?

Ответ 5

Поскольку вы можете узнать дочерний LinearLayout, который вам нужно прокрутить, как пробовать это.

ScrollView sv = // your scrollview
View highlightedItem = // find the LinearLayout or View that you need to scroll to which is inside this ScrollView
sv.scrollTo(0, highlightedItem.getY());

Дополнительная информация о scrollTo, а также smoothScrollTo

Ответ 6

Здесь решение, которое работает, если целевой вид не является прямым дочерним элементом вашего ScrollView:

public int findYPositionInView (View rootView, View targetView)
{
  return findYPositionInView (rootView, targetView, 0);
}


// returns -1 if targetView not found
private int findYPositionInView (View rootView, View targetView, int yCumulative)
{
  if (rootView == targetView)
    return yCumulative;

  if (rootView instanceof ViewGroup)
  {
    ViewGroup parentView = (ViewGroup)rootView;
    for (int i = 0;  i < parentView.getChildCount ();  i++)
    {
      View child = parentView.getChildAt (i);
      int yChild = yCumulative + (int)child.getY ();

      int yNested = findYPositionInView (child, targetView, yChild);
      if (yNested != -1)
        return yNested;
    }
  }

  return -1; // not found
}

Используйте его следующим образом:

int yScroll = findYPositionInView (scrollView, targetView);
scrollView.scrollTo (0, yScroll);

Кроме того, если вы хотите установить фокус, сделайте следующее:

targetView.requestFocus ();

И, если вы хотите, чтобы клавиатура отображалась, сделайте следующее:

if (targetView instanceof EditText)
{
  targetView.post (new Runnable ()
  {
    @Override public void run ()
    {
      InputMethodManager imm = (InputMethodManager)context.getSystemService (Context.INPUT_METHOD_SERVICE);
      imm.showSoftInput (targetView, InputMethodManager.SHOW_FORCED);
    }
  });
}

Ответ 7

Использование:

final  ScrollView scrollView= (ScrollView) 
int speed=1000;
findViewById(R.id.main_scrollView);
final View view = findViewById(R.id.your_view); 
ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() { view.getViewTreeObserver().removeOnGlobalLayoutListener(this);   
                ObjectAnimator.ofInt(scrollView, "scrollY",  (int) view.getY()).setDuration(speed).start();
            }
        }); 

Ответ 8

Я получил желаемый результат, используя requestChildFocus(), как предложено в ответе Swas_99 выше.

Однако, так как он не делает плавный скроллинг, я посмотрел в исходный код для requestChildFocus который вызывает scrollToChild который вызывает offsetDescendantRectToMyCoords. Оттуда у меня появилась идея использовать следующий код С#/Xamarin, который дает эффект, аналогичный использованию requestChildFocus(), но с плавной прокруткой:

private static void ScrollToView(View ArgTarget) {
    var CurParent = ArgTarget.Parent;

    while (CurParent != null) {
      var ScrollArea = CurParent as ScrollView;

      if (ScrollArea != null) {
        var ViewRect = new Rect();
        ArgTarget.GetDrawingRect(ViewRect);

        ScrollArea.OffsetDescendantRectToMyCoords(ArgTarget, ViewRect);
        ScrollArea.SmoothScrollTo(ViewRect.Left, ViewRect.Top);

        break;
      }

      CurParent = CurParent.Parent;
   }
}

Основная идея состоит в том, чтобы найти целевой вид, содержащий ScrollView. Затем возьмите прямоугольник рисования целевого вида, отрегулируйте его координаты так, чтобы они были понятны ScrollView, затем попросите ScrollView прокрутить до плавного перехода к этой позиции. Конечным эффектом является то, что вид, который вы хотите прокрутить, всегда будет полностью видимым в верхней части экрана (вы можете поиграться с ViewRect.Top, если хотите вместо этого центрировать вид на экране).

Ответ 9

Здесь rootView - это ваше родительское представление, а childView - это представление, в котором вы хотите прокрутить свое представление.

public static int getRelativeTop(View rootView, View childView) {
    if(childView.getParent() == rootView) return childView.getTop();
    else return childView.getTop() + getRelativeTop(rootView, (View) childView.getParent());
}

Ответ 10

Вы можете использовать метод smoothScrollTo для прокрутки к определенному представлению в представлении прокрутки. - Пример:

my_scroll_View.smoothScrollTo(0, editText.getBottom());

Удачи!

Ответ 11

Попробуйте вызвать view.requestFocus() в представлении, которое вы хотите прокрутить.