Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android问题:无休止滚动的视图_Android_Image_Scroll_Limits_Edges - Fatal编程技术网

Android问题:无休止滚动的视图

Android问题:无休止滚动的视图,android,image,scroll,limits,edges,Android,Image,Scroll,Limits,Edges,我有一个实现了滚动的自定义视图,但它看起来像是在图像上无休止地滚动。 即使我找到图像的边缘,它也会一直滚动到空白背景 我不能使用网络视图,因为我还有一些画布 有人知道如何为这个问题设定限制吗 如何使图像边缘适合滚动? 编辑:我通过@Josepharl帮助找到了最佳解决方案。 我只设置了左边界和上边界,因为我的图像比屏幕大。 另外,我在使用缩放功能时关闭了边界,否则我将无法再移动它。 1)在onTouch事件的ACTION\u MOVE案例中,插入以下代码: if(!isZoomed) {

我有一个实现了滚动的自定义视图,但它看起来像是在图像上无休止地滚动。
即使我找到图像的边缘,它也会一直滚动到空白背景

我不能使用网络视图,因为我还有一些画布 有人知道如何为这个问题设定限制吗
如何使图像边缘适合滚动?


编辑:我通过@Josepharl帮助找到了最佳解决方案。
我只设置了左边界和上边界,因为我的图像比屏幕大。
另外,我在使用缩放功能时关闭了边界,否则我将无法再移动它。

1)在onTouch事件的ACTION\u MOVE案例中,插入以下代码:

if(!isZoomed) {
    if(mPosX < 0)
        mPosX = 0;
    else if(mPosX > mWidth)
        mPosX = mWidth;
    if(mPosY < 0)
        mPosY = 0;
    else if(mPosY > mHeight)
        mPosY = mHeight;
}
case MotionEvent.ACTION_POINTER_UP: {

    final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
    final int pointerId = ev.getPointerId(pointerIndex);

    if (pointerId == mActivePointerId) {
        final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
        mLastTouchX = ev.getX(newPointerIndex);
        mLastTouchY = ev.getY(newPointerIndex);
        mActivePointerId = ev.getPointerId(newPointerIndex);
        isZoomed = true;

    } else
        isZoomed = false;

    break;

}

就这些
以下是所有相关方法和完成的onTouch事件:

private float scaleFactor = 1.f;
private ScaleGestureDetector detector;

private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;

private float mPosX;
private float mPosY;
private float mLastTouchX;
private float mLastTouchY;

private float mWidth;
private float mHeight;
private boolean isZoomed = false;

// OTHER CODE GOES HERE

@Override
public boolean onTouchEvent(MotionEvent ev) {
    detector.onTouchEvent(ev);

    final int action = ev.getAction();
    switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {
            final float x = ev.getX();
            final float y = ev.getY();

            mLastTouchX = x;
            mLastTouchY = y;
            mActivePointerId = ev.getPointerId(0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
            final float x = ev.getX(pointerIndex);
            final float y = ev.getY(pointerIndex);

            if (!detector.isInProgress()) {
                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;
                mPosX += dx;
                mPosY += dy;

                if(!isZoomed) {
                    if(mPosX < 0)
                        mPosX = 0;
                    else if(mPosX > mWidth)
                        mPosX = mWidth;
                    if(mPosY < 0)
                        mPosY = 0;
                    else if(mPosY > mHeight)
                        mPosY = mHeight;
                }

                invalidate();
            }

            mLastTouchX = x;
            mLastTouchY = y;

            break;
        }

        case MotionEvent.ACTION_UP: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_POINTER_UP: {

            final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
            final int pointerId = ev.getPointerId(pointerIndex);

            if (pointerId == mActivePointerId) {
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = ev.getX(newPointerIndex);
                mLastTouchY = ev.getY(newPointerIndex);
                mActivePointerId = ev.getPointerId(newPointerIndex);
                isZoomed = true;

            } else
                isZoomed = false;

            break;

        }
    }

    return true;
}

private class ScaleListener extends
        ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        scaleFactor *= detector.getScaleFactor();
        scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));
        invalidate();
        return true;
    }
}

@Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
     super.onSizeChanged(xNew, yNew, xOld, yOld);
     mWidth = xNew;
     mHeight = yNew;
}

// OTHER CODE GOES HERE
private float scaleFactor=1.f;
专用电子秤检测器;
私有静态final int无效\u指针\u ID=-1;
private int mActivePointerId=无效的\u指针\u ID;
私人浮动mPosX;
私家车;
私有浮动mLastTouchX;
私密的浮躁和敏感;
私人浮动宽度;
私人浮动mhweight;
私有布尔值isZoomed=false;
//其他代码在这里
@凌驾
公共事件(MotionEvent ev){
探测器。开闭式排气管(ev);
final int action=ev.getAction();
开关(动作和动作事件.动作屏蔽){
case MotionEvent.ACTION\u DOWN:{
最终浮点数x=ev.getX();
最终浮动y=ev.getY();
mLastTouchX=x;
mLastTouchY=y;
MacTivePointId=ev.getPointerId(0);
打破
}
case MotionEvent.ACTION\u移动:{
final int pointerIndex=ev.findPointerIndex(mactivePointId);
最终浮动x=ev.getX(指针索引);
最终浮动y=ev.getY(指针索引);
如果(!detector.isInProgress()){
最终浮点数dx=x-mLastTouchX;
最终浮子dy=y—最大浮子厚度;
mPosX+=dx;
mPosY+=dy;
如果(!已缩放){
if(mPosX<0)
mPosX=0;
否则如果(mPosX>mWidth)
mPosX=mWidth;
if(mPosY<0)
mPosY=0;
否则如果(mPosY>mHeight)
mPosY=mHight;
}
使无效();
}
mLastTouchX=x;
mLastTouchY=y;
打破
}
case MotionEvent.ACTION\u UP:{
MacTivePointId=无效的\u指针\u ID;
打破
}
case MotionEvent.ACTION\u取消:{
MacTivePointId=无效的\u指针\u ID;
打破
}
case MotionEvent.ACTION\u指针\u向上:{
final int pointerIndex=(ev.getAction()&MotionEvent.ACTION\u POINTER\u INDEX\u MASK)>>MotionEvent.ACTION\u POINTER\u INDEX\u SHIFT;
final int pointerId=ev.getPointerId(pointerIndex);
if(pointerId==MacTivePointId){
final int newPointerIndex=pointerIndex==0?1:0;
mLastTouchX=ev.getX(newPointerIndex);
mLastTouchY=ev.getY(新指针索引);
MacTivePointId=ev.getPointerId(newPointerIndex);
isZoomed=真;
}否则
isZoomed=假;
打破
}
}
返回true;
}
私有类ScaleListener扩展
ScaleGetStureDetector.SimpleOnScaleGetStureListener{
@凌驾
公共布尔标度(scalegestruedetector检测器){
scaleFactor*=检测器。getScaleFactor();
scaleFactor=Math.max(最小缩放,数学最小(scaleFactor,最大缩放));
使无效();
返回true;
}
}
@凌驾
IzeChanged上的受保护无效(int xNew、int yNew、int xOld、int yOld){
super.onSizeChanged(xNew、yNew、xOld、yOld);
mWidth=xNew;
mHeight=yNew;
}
//其他代码在这里

从您的代码中可以看出,您在任何时候都不会试图检测可滚动区域的大小,并将位置限制在这些范围内,也就是说,您应该检查以确保
mPosX
mPosY
不会超出其范围

系统不会自动限制自定义视图的位置,这是您需要自己做的事情

顶部和左侧边界将为0,0——您应该确保
mPosX
mPosY
不大于此值

右边界将是(容器视图的宽度-滚动视图的宽度)——这应该是负数(如果大于,则将右边界设置为0),并且您应该确保
mPosX
不小于此值。底部边界将是(容器高度-滚动视图高度)--这同样应该是负数,并且您应该确保
mPosY
不小于该值

总之,当触摸事件开始时,计算边界:

// Calculate our bounds.
int leftBound = 0;
int topBound = 0;
int rightBound = imageWidth - getWidth();
if (rightBound > 0) {
    rightBound = 0;
}
int bottomBound = imageHeight - getHeight();
if (bottomBound > 0) {
    bottomBound = 0;
}
其中,
imageWidth
imageHeight
是要滚动的内容的宽度和高度

然后在滚动时,确保遵守边界:

if (mPosX > leftBound) {
    mPosX = leftBound;
} else if (mPosX < rightBound) {
    mPosX = rightBound;
}

if (mPosY > topBound) {
    mPosY = topBound;
} else if (mPosY < bottomBound) {
    mPosY = bottomBound;
}
if(mPosX>leftBound){
mPosX=左边界;
}else if(mPosX<右边界){
mPosX=右边界;
}
如果(mPosY>上界){
mPosY=上界;
}else if(mPosY<底部边界){
mPosY=底部边界;
}

这正是我不知道该怎么做的:上面有关于如何做的信息。现在没有滚动图像了!:(可能是因为我设置了错误的宽度和高度值吗?我应该为其设置图像或屏幕值吗?我的自定义视图在线性布局中只有两个按钮,下面有一个图像。您是否移动自定义视图本身(使视图中的所有内容都移动)?还是自定义视图中的某些内容,例如图像?