Прокрутите до определенного вида в режиме прокрутки
Я добавил 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, но он прокручивается до верхней части прокрутки.
Просьба представить несколько предложений.
Ответы
Ответ 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()
в представлении, которое вы хотите прокрутить.