Horizo​​ntalScrollView scrollTo 不会滚动到视图的原始宽度之上

HorizontalScrollView scrollTo doesn't scroll above original width of the view

我有一个包含 Horizo​​ntalScrollView 的自定义视图。滚动视图的宽度为 match_parent,其子视图的宽度最初是根据自定义视图的属性值以编程方式设置的。在某些时候,滚动视图的子视图的宽度以编程方式更新(增加)。问题是,更新后,scrollTo 方法仍然无法滚动到原始宽度值以上(scrollBy 也一样)。

封闭视图(自定义视图)的左右内边距等于屏幕的一半,如果相关的话。

示例:

相关代码:

自定义视图初始化:

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 是 Horizo​​ntalScrollView 的子级):

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);
}

问题似乎是滚动发生在重绘子元素之前,在调用 requestLayout 之前仅安排在将来某个时间点执行视图的更新(对于 invalidate() 也是如此)。

我使用变通方法解决了问题,方法是在一段时间后执行 scrollTo:

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

我仍然愿意接受更好的解决方案。