HorizontalScrollView scrollTo не прокручивается выше исходной ширины вида - PullRequest
0 голосов
/ 26 сентября 2019

У меня есть пользовательское представление, содержащее HorizontalScrollView.Ширина представления прокрутки равна match_parent, а ширина его дочерних элементов изначально устанавливается программно на основе значения атрибута пользовательского представления.В какой-то момент ширина дочерних элементов представления прокрутки обновляется (увеличивается) программно.Проблема в том, что после обновления метод scrollTo по-прежнему не может прокручиваться выше исходного значения ширины (то же самое для scrollBy).

Вмещающий вид (пользовательский) имеет отступы слева и справа, равныена половину экрана, если это уместно.

Пример:

  • Начальная ширина дочернего элемента HorizontalScrollView: 1000;
  • Ширина родительского элемента HorizontalScrollView: 1080;
  • Горизонтальное заполнение HorizontalScrollView влево / вправо = 540;
  • Новая дочерняя ширина HorizontalScrollView: 2000;
  • scrollTo (1100, 0) = scrollTo (1000, 0);<---- вот в чем проблема </li>

Соответствующий код:

Инициализация пользовательского представления:

private void init(AttributeSet attrs, int defStyle) {
    inflate(getContext(), R.layout.timeline_view, this);

    // Load attributes
    final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.TimelineView, defStyle, 0);

    m_timelineInitialLength = a.getDimension(R.styleable.TimelineView_timelineInitialLength, DEFAULT_LENGTH);

    a.recycle();

    DisplayMetrics displayMetrics = new DisplayMetrics();
    ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
    LinearLayout timelineWidget = findViewById(R.id.timeline_widget);
    int horizontalPadding = displayMetrics.widthPixels / 2;
    timelineWidget.setPadding(horizontalPadding, 0, horizontalPadding, 0);

    m_horizontalScrollView = findViewById(R.id.scroll_view);
    m_horizontalScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            m_currentScrollX = m_horizontalScrollView.getScrollX();
        }
    });
    m_currentScrollX = m_horizontalScrollView.getScrollX();

    update(m_timelineInitialLength, m_timelineInitialStepWidth, m_currentScrollX);
}

Update и scrollTo (этот метод вызывается также приконец инициализации. m_rulerView и m_timelineLayout являются дочерними элементами HorizontalScrollView):

private void update(float timelineLength, float timelineStepWidth, int currentScrollX) {
    m_rulerView = findViewById(R.id.ruler);
    m_rulerView.setIndicator(null);
    m_rulerView.getLayoutParams().width = (int) timelineLength;
    m_rulerView.requestLayout();

    m_timelineLayout = findViewById(R.id.timeline);
    m_timelineLayout.getLayoutParams().width = (int) timelineLength;
    m_timelineLayout.requestLayout();

    m_horizontalScrollView.scrollTo(currentScrollX, 0);
}

1 Ответ

0 голосов
/ 26 сентября 2019

Кажется, проблема в том, что прокрутка происходит до того, как дочерние элементы были перерисованы, перед вызовом requestLayout только запланировать обновление представления, которое будет выполнено в какой-то момент в будущем (то же самое для invalidate ()).

Я решил использовать обходной путь, через некоторое время выполнив scrollTo:

new Handler().postDelayed(() -> ((Activity) getContext()).runOnUiThread(() -> m_horizontalScrollView.scrollTo(currentScrollX, 0)), 200);

Я все еще открыт для лучших решений.

...