2013-04-08 78 views
4

我有一个自定义类,我从ScrollView扩展。我想要做的是实现与这个班的缩放缩放,我想要缩放到ScrollView的孩子,并根据需要滚动放大的内容。基本上,我希望iOS的UIScrollView类别具有相同的行为(它是一个SHAME,Android不提供像iOS这样的任何内置缩放功能,我们必须从头开始编写所有内容)。我在课堂中有ScaleGestureListener,我在ScrollView内更新子视图的布局维度,当我收到onScale事件时:我将布局宽度和高度乘以从ScaleGestureListener收到的比例因子。令我困扰的是,ScrollView根据其孩子的新维度不更新其滚动条。例如,如果孩子的宽度大于ScrollView's,它将不会显示水平滚动条。我在滚动视图及其子视图上调用了invalidaterequestLayout,但它们都失败了。使用ScrollView缩放缩放:在子尺寸更改时更新其滚动行为

下面我给我的代码:

public class PinchZoomScrollView extends ScrollView{ 

private ScaleGestureDetector mScaleDetector;// = new ScaleGestureDetector(context, new ScaleListener()); 
private float mScaleFactor = 1.0f; 
private float referenceTextSize; 
private static final float MIN_ZOOM_AMOUNT = 1.0f; 
private static final float MAX_ZOOM_AMOUNT = 2.0f; 

private float refChildWidth; 
private float refChildHeight; 

private boolean shownForTheFirstTime = true; 
//private View content; 


private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 

    private WeakReference<PinchZoomScrollView> containerRef; 

    public ScaleListener(PinchZoomScrollView container) 
    { 
     super(); 

     containerRef = new WeakReference<PinchZoomScrollView>(container); 
    } 

    @Override 
    public boolean onScale(ScaleGestureDetector detector) { 
     mScaleFactor *= detector.getScaleFactor(); 

     // Don't let the object get too small or too large. 
     mScaleFactor = Math.max(MIN_ZOOM_AMOUNT, Math.min(mScaleFactor, MAX_ZOOM_AMOUNT)); 

     //Get Child object 
     View content = containerRef.get().getChildAt(0); 

     if(shownForTheFirstTime) 
     { 
      shownForTheFirstTime = false; 

      refChildWidth = content.getWidth(); 
      refChildHeight = content.getHeight(); 
     } 

     LayoutParams params = new LayoutParams(Math.round(mScaleFactor*refChildWidth), Math.round(mScaleFactor*refChildHeight)); 
     content.setLayoutParams(params); 


     System.out.println("this.width="+containerRef.get().getWidth()); 
     System.out.println("content.width="+Math.round(mScaleFactor*refChildWidth)); 


     content.invalidate(); 
     content.requestLayout(); 

     containerRef.get().updateViewLayout(content, params); 

     containerRef.get().invalidate(); 
     containerRef.get().requestLayout(); 

     return true; 
    } 
} 


public PinchZoomScrollView(Context context) 
{ 
    super(context); 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener(this)); 
} 

public PinchZoomScrollView(Context context, AttributeSet attrs) 
{ 
    super(context,attrs); 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener(this)); 
} 

public PinchZoomScrollView(Context context, AttributeSet attrs, int defStyle) 
{ 
    super(context,attrs,defStyle); 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener(this)); 
} 

@Override 
public boolean onTouchEvent(MotionEvent ev) { 

    super.onTouchEvent(ev); 

    mScaleDetector.onTouchEvent(ev); 

    return true; 
} 

} 

采取长话短说,我需要的滚动型根据其孩子的更新大小,以更新其滚动条,每次用户进行捏放大和缩小。

预先感谢

回答

4

这里是一个解决方案:

  1. 而不是延伸滚动型,我写延伸的FrameLayout其是滚动型和Horizo​​ntalScrollView的组合的TwoDimensionScrollView,以便它可以显示两个水平/垂直滚动条,即使孩子被缩放。另外我没有使用手势检测器。相反,我实现了我自己的捏缩放。

  2. 要更新滚动条,改写以下功能:

    @Override 
    protected int computeVerticalScrollRange() { 
        final int count = getChildCount(); 
        final int contentHeight = getHeight() - getPaddingBottom() 
         - getPaddingTop(); 
        if (count == 0) { 
         return contentHeight; 
        } 
    
    
    @Override 
    protected int computeVerticalScrollOffset() { 
        int result = Math.max(0, super.computeVerticalScrollOffset()); 
        return result - getScrollVerticalMin(); 
    } 
    @Override 
    protected int computeHorizontalScrollRange() { 
        final int count = getChildCount(); 
        final int contentWidth = getWidth() - getPaddingLeft() 
         - getPaddingRight(); 
        if (count == 0) { 
         return contentWidth; 
        } 
    
        int scrollRange = getChildAt(0).getRight(); 
        final int scrollX = getScrollX(); 
        final int overscrollRight = Math.max(0, scrollRange - contentWidth); 
        if (scrollX < 0) { 
         scrollRange -= scrollX; 
        } else if (scrollX > overscrollRight) { 
         scrollRange += scrollX - overscrollRight; 
        } 
        return (int) (scrollRange * mScaleFactor + getScrollHorizontalMin()); 
    } 
    
    @Override 
    protected int computeHorizontalScrollOffset() { 
        int result = Math.max(0, super.computeHorizontalScrollOffset()); 
        return result - getScrollHorizontalMin(); 
    } 
    @Override 
    protected int computeVerticalScrollExtent() { 
        return getHeight() + getScrollVerticalMin(); 
    } 
    
    @Override 
    protected int computeHorizontalScrollExtent() { 
        return getWidth() + getScrollHorizontalMin(); 
    } 
    private int getScrollHorizontalMin() { 
        if (this.getChildCount() < 1) 
         return 0; 
        View child = this.getChildAt(0); 
        return (int) ((1 - mScaleFactor) * child.getPivotX()); 
    } 
    
    private int getScrollVerticalMin() { 
        if (this.getChildCount() < 1) 
         return 0; 
        View child = this.getChildAt(0); 
        return (int) ((1 - mScaleFactor) * child.getPivotY()); 
    } 
    private int getScrollVerticalRange() { 
        int scrollRange = 0; 
        if (getChildCount() > 0) { 
         View child = getChildAt(0); 
         scrollRange = (int) Math.max(0, child.getHeight() * mScaleFactor 
           - (getHeight() - getPaddingBottom() - getPaddingTop()) 
           + getScrollVerticalMin()); 
        } 
    return scrollRange; 
    } 
    
    private int getScrollHorizontalRange() { 
        int scrollRange = 0; 
        if (getChildCount() > 0) { 
         View child = getChildAt(0); 
         scrollRange = (int) Math.max(0, child.getWidth() * mScaleFactor 
           - (getWidth() - getPaddingRight() - getPaddingLeft()) 
           + getScrollHorizontalMin()); 
        } 
        return scrollRange; 
    } 
    
  3. 您还需要找到所有代码调用回弹()和一扔(),然后使用设定的最小值为x和y上述函数getScrollHorizo​​ntalMin()和getScrollVerticalMin()而不是0