在childView.setScaleX()/ setScaleY()之后调整ScrollView视口大小

时间:2015-09-04 04:28:14

标签: android android-layout parent-child android-custom-view android-scrollview

我遇到了TwoDScrollView布局的问题。缩放其子项后,TwoDScrollView的垂直和水平滚动范围保持不变。

这是XML代码:

<com.fine.example.TwoDScrollView      
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scrolling"
    android:drawingCacheQuality="low"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/board"
        android:clipChildren="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:drawingCacheQuality="low"
        android:layout_marginTop="?android:attr/actionBarSize"
        android:layout_marginBottom="?android:attr/actionBarSize"
        android:paddingTop="@dimen/padmargsmedium"
        android:paddingBottom="?android:attr/actionBarSize"
        android:paddingLeft="@dimen/padmarg"
        android:paddingRight="@dimen/padmarg" >

        <RelativeLayout
            android:id="@+id/boardf"
            android:drawingCacheQuality="low"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

        </RelativeLayout>

    </RelativeLayout>

</com.fine.example.TwoDScrollView>

这就是我缩放childView的方法:

scale -= 0.25f;      // or scale += 0.25f;
board.setPivotX(0.5f/scale);
board.setPivotY(0.5f/scale);
board.setScaleX(1f/scale);
board.setScaleY(1f/scale);

实际上我设法修复了&#34;放大&#34;通过这样做:

TwoDScrollView.LayoutParams params = (TwoDScrollView.LayoutParams) board.getLayoutParams();
params.width = (int) (xwidth/scale);
params.height = (int) (yheight/scale);
board.setLayoutParams(params);

但是对于&#34;缩小&#34;相同的代码不起作用。孩子的大小会发生变化,但ScrollView不会更新其容器大小,滚动的方式比滚动视图与其缩放的孩子之间显示空白区域时的滚动方式更多。

你可以在这里找到TwoDScrollView源码(由Matt Clark提供):

https://web.archive.org/web/20121125032032/http://blog.gorges.us/2010/06/android-two-dimensional-scrollview/comment-page-1/#comments

我尝试的事情:

  • 替换ScrollView的TwoDScrollView并设置fillViewPort =&#34; true&#34;,但同样的情况也会发生。

  • 在两种布局和每种可能的组合中将layout_width和layout_height更改为WRAP_CONTENT或MATCH_PARENT。

  • 与invalidate()和requestLayout()相同。

  • 将可见性设置为GONE,然后设置为VISIBLE,如下所述:ScrollView does not resize directly after child changes

  • 我甚至尝试在这些TwoDScrollView方法中强制缩放:computeVerticalScrollRange,computeHorizo​​ntalScrollRange,measureChild,measureChildWithMargins和computeScroll,但没有结果。

  • 搜索stackoverflow:有一些像我这样的问题,但是当有答案时,遗憾的是它对我不起作用。

我该如何解决这个问题?任何帮助都会非常感激!

1 个答案:

答案 0 :(得分:1)

最后,我为缩小部分设计了一个解决方案脏hax。不是最佳但是嘿,它有效。

在TwoDScrollView.java中更改以下三种方法:

@Override
protected float getBottomFadingEdgeStrength() {
    if (getChildCount() == 0) {
        return 0.0f;
    }
    final int length = getVerticalFadingEdgeLength();
    final int bottomEdge = getHeight() - getPaddingBottom();
    final int span = (int) (getChildAt(0).getBottom()/scale) - getScrollY() - bottomEdge;
    if (span < length) {
        return span / (float) length;
    }
    return 1.0f;
}

@Override
protected float getRightFadingEdgeStrength() {
    if (getChildCount() == 0) {
        return 0.0f;
    }
    final int length = getHorizontalFadingEdgeLength();
    final int rightEdge = getWidth() - getPaddingRight();
    final int span = (int) (getChildAt(0).getRight()/scale) - getScrollX() - rightEdge;
    if (span < length) {
        return span / (float) length;
    }
    return 1.0f;
}

@Override
public void computeScroll() {
    if (mScroller.computeScrollOffset()) {
        int oldX = getScrollX();
        int oldY = getScrollY();
        int x = mScroller.getCurrX();
        int y = mScroller.getCurrY();
        if (getChildCount() > 0) {
            View child = getChildAt(0);
            scrollTo(clamp(x, getWidth() - getPaddingRight() - getPaddingLeft(), (int) (child.getWidth() / scale)),
                    clamp(y, getHeight() + getPaddingBottom() - getPaddingTop(), (int) ((child.getHeight() + child.getPaddingBottom()) / scale)));
        } else {
            scrollTo(x, y);
        }
        if (oldX != getScrollX() || oldY != getScrollY()) {
            onScrollChanged(getScrollX(), getScrollY(), oldX, oldY);
        }
        postInvalidate();
    }
}

另外,值得注意的是,我正在使用measureChildWithMargins()作为James McMurray在Gorges.blog上的建议,如果这有帮助的话。

@Override
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
    final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

    int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.leftMargin + lp.rightMargin, MeasureSpec.UNSPECIFIED);
    int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.topMargin + lp.bottomMargin, MeasureSpec.UNSPECIFIED);

    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}

所以现在scrollview父级将其边界限制为按比例缩小的子级。它可以超出极限,但在发布时,scrollview布局会再次以适当的大小捕捉。

如果有人有更好的解决方案,我会很乐意回答。

感谢神秘的恩人,赞成我的问题:)