java - Horizo​​ntalScrollView的scrollTo不会滚动到 View 的原始宽度之上

标签 java android scroll android-custom-view horizontalscrollview

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

封闭 View (自定义 View )的左右填充等于屏幕的一半(如果相关的话)。

示例:

  • 初始 Horizo​​ntalScrollView 的子级宽度:1000;
  • Horizo​​ntalScrollView 的父级宽度:1080;
  • Horizo​​ntalScrollView 的左/右内边距 = 540;
  • 新建 Horizo​​ntalScrollView 的子级宽度:2000;
  • scrollTo(1100, 0)=scrollTo(1000, 0); <----这就是问题

相关代码:

自定义 View 初始化:

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 之前仅安排 View 的更新在将来的某个时刻执行(与 invalidate() 相同)。

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

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

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

关于java - Horizo​​ntalScrollView的scrollTo不会滚动到 View 的原始宽度之上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58112629/

相关文章:

java - 使用 Spring 微服务从 kubernetes 集群中的服务中提取配置映射

java - 如何防止用作映射值的列表被修改?

java - 为什么在 launchBillingFlow 之后没有调用 onPurchasesUpdated

Java2D 相对于鼠标位置的缩放和滚动

javascript - 动态 Jquery 选项卡

java - 无法创建 JAXBContext 创建我的 wsdl

java - 为什么在 web.xml 中标记为 CONFIDENTIAL 的 URL 没有被 HttpServletResponse.encodeURL() 使用 HTTPS 重写?

android - 如何用 firebase 实时数据库中的新字段更新子项?

android - Android Liferay屏幕中的NoClassDefError com.liferay.mobile.screens.base.interactor.JSONObjectCallback

css - 溢出:带有持久 header 的自动