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