【问题标题】:ListView in Fragment in ViewPager in ScrollView for android >=2.3ListView in Fragment in ViewPager in ScrollView for android >=2.3
【发布时间】:2023-04-05 07:37:01
【问题描述】:

有可能吗?

重点是:

  • listView 之外的复杂标题,但必须滚动
  • 一个 ListView,其滚动由远端 ScrollView 父级处理。
  • ListView必须有recycling,所以linearLayout不能解决

谢谢

【问题讨论】:

  • 所以 ListView 实际上是在 ViewPager 里面??那么在每个页面中都有一个不同的 ListView 吗?
  • 是的,listView 位于 ViewPager 添加的片段内。在每个页面中都有任何可能,有时是 ListView
  • 您找到合适的解决方案了吗?我也在尝试做完全相同的事情,但我找不到任何解决方案。

标签: android android-listview android-scrollview


【解决方案1】:

直接回答问题:

有可能吗?

是的。您可以在相册和个人资料部分看到this example here。但这并不简单,也不直截了当。

在 ScrollView 中添加 ListView 存在两个问题(您可以自行研究),即 TouchEvents 会混淆,因为它不知道哪个 View 会消耗触摸而系统不会知道如何在另一个无限的 sidez View 中布局无限大小的 View。

因为实现起来既不简单也不直截了当,所以有几种可能的实现方式,所有这些实现方式都包含大量代码和大量测试。我将向您指出一个开源示例,您可以从那里开始:

https://github.com/kmshack/Android-ParallaxHeaderViewPager

【讨论】:

    【解决方案2】:

    这里的问题是在 ScrollView 中包含 ListView。下面给出的步骤描述了如何将 任何 垂直可滚动视图封装到另一个可垂直滚动视图中。

    第一步

    编写一个确定视图是否可以垂直滚动的方法,并将该方法放在一个通用实用程序类中,如下所示。该方法取自 ViewPager.java 并修改为查看 View 是否可以垂直滚动。

    public static boolean canScroll(View v, boolean checkV, int dy, int x, int y) {
        if (v instanceof ViewGroup) {
            final ViewGroup group = (ViewGroup) v;
            final int scrollX = v.getScrollX();
            final int scrollY = v.getScrollY();
            final int count = group.getChildCount();
            for (int i = count - 1; i >= 0; i--) {
                final View child = group.getChildAt(i);
                if (x + scrollX >= child.getLeft()
                        && x + scrollX < child.getRight()
                        && y + scrollY >= child.getTop()
                        && y + scrollY < child.getBottom()
                        && canScroll(child, true, dy,
                                x + scrollX - child.getLeft(), y + scrollY
                                        - child.getTop())) {
                    return true;
                }
            }
        }
        return checkV && ViewCompat.canScrollVertically(v, -dy);
    }
    

    第 2 步

    子类化封闭的垂直可滚动视图,它可以是 ScrollView 或 ListView(在您的情况下是 ScrollView)等,并覆盖 onInterceptTouchEvent() 方法,如下所示。

    public boolean onInterceptTouchEvent(MotionEvent event) {
      int action = event.getAction();
        float x = event.getX();
        float y = event.getY();
        float dy = y - mLastMotionY;
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            mLastMotionY = y;
            break;
        case MotionEvent.ACTION_MOVE:
            if (Util.canScroll(this, false, (int) dy, (int) x, (int) y)) {
                mLastMotionY = y;
                return false;
            }
            break;
        }
        return super.onInterceptTouchEvent(event);
    }
    

    第 3 步

    子类化封闭的垂直可滚动视图,它可能是 GridView 或 ListView 等(在您的情况下为ListView)并覆盖 onMeasure() 方法,如下所示。无需在 ScrollView 中重写此方法。它的默认实现以正确的方式运行。

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        if (mode == MeasureSpec.UNSPECIFIED) {
            int height = getLayoutParams().height;
            if (height > 0)
                setMeasuredDimension(getMeasuredWidth(), height);
        }
    }
    

    第四步

    最后创建一个 xml 布局文件并使用您子类化的 ScrollView 和 ListView,并且您必须对 layout_height 进行硬编码。如果您通过 java 代码创建视图层次结构,则将高度硬编码为LayoutParams。如果您使用自己的测量策略而不是第 3 步中指定的测量策略,则不需要这种硬编码。

    更多详情请查看ScrollInsideScroll这个帖子,下载项目并检查代码。

    【讨论】:

      【解决方案3】:

      如果您不自己编写,您将无法回收ListView。如果您想使用嵌套片段的解决方案(如图所示),请尝试this

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-29
        • 2012-01-25
        • 1970-01-01
        相关资源
        最近更新 更多