我有一个 HorizontalScrollView
,其中有多个 View 。我已经实现了 pinch zoom gesture
,其中我的两个手指之间的多个 View 被缩放。
但是我遇到了一个小故障。当我进行双指缩放时,双指缩放的中点在移动,但为了用户体验,我希望这个点保持固定,其他东西应该在缩放时自行调整,以便中点保持静止。
谁能告诉我怎么做。
onDraw()
自定义 View 的方法是
Rect r =new Rect(0, 0, 700, 40);
public void onDraw(Canvas canvas) {
float kk=mScaleFactor; //this variable will be set by pinch zoom event and represent how much to scale
sf*=kk; // this view must scale according to previous scaling
canvas.save();
canvas.scale(sf , 1);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
canvas.drawRect(r, paint);
width=sf*700;
canvas.restore();
requestLayout(); //this will change view width to fit the expanded rectangle
}
在requestLayout 上调用onMeasure 方法
@Override protected void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
setMeasuredDimension((int)width, 340);
}
上面的自定义 View 被 HorizontalScrollView
的子类调用了 12 次。所以 HorizontalScrollview
有 12 个 subview 。
在这门课上我做了以下事情
检测两根手指的触摸坐标。
计算第一个手指触摸的 subview 的索引。
计算中指触摸的 subview 的索引。
将缩放比例因子传递给开始和最后之间的所有 subview 。 这两个指标是前两步计算得到的。
最后在 subview 上调用 invalidate()。所以 child 可以根据父 View 传递的比例因子缩放自己。
但是这里有一个问题。两个手指的中点应该保持静止,其他东西应该在缩放过程中调整。但我的中点是随着缩放而移动。
有人可以帮我做这件事吗?请告诉我是否需要任何部分代码。
HorizontalScrollview
的手势监听代码为
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
ViewGroup pp=takeparent(); //give object of this class
for(int i=start;i<=last;i++)
{
LinearLayout ll=(LinearLayout)pp.getChildAt(i);
DrawView view=(DrawView)ll.findViewById(R.id.drawview);
view.mScaleFactor=mScaleFactor;
view.invalidate();
view.donesf=true;
}
我的示例应用程序
按照评论中的建议进行编辑:
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
ViewGroup pp=takeparent(); pp contains all the custom child views
//start and last are indices of range of child for which we have to apply gesture
for(int i=start;i<=last;i++)
{
LinearLayout ll=(LinearLayout)pp.getChildAt(i);
DrawView view=(DrawView)ll.findViewById(R.id.drawview);
view.mScaleFactor=mScaleFactor;
view.pivotx=detector.getFocusX()+view.getLeft();
view.pivoty=detector.getFocusY()+view.getTop();
view.invalidate();
}
return true;
}
这是自定义view的onDraw方法
public void onDraw(Canvas canvas) {
sf=mScaleFactor //this scale factor is set by parent view
width=sf*700; //this width will be use to rescale the view's width in requestLayout()
canvas.save();
canvas.scale(sf,1,pivotx,pivoty); //pivotX and pivotY are also set by parent's onScale method of gestureListener
canvas.drawRect(r, paint);
requestLayout();
canvas.restore();
}
最佳答案
对于要缩放的 View ,您可以使用 setPivotX()
和 setPivotY()
设置不应移动的“不变”点。当我使用 ScaleGestureDetector
时,我为此使用了 focus
点。例如:
@Override
public boolean onScaleBegin(ScaleGestureDetector detector)
{
...
mScaledView.setPivotX(detector.getFocusX());
mScaledView.setPivotY(detector.getFocusY());
...
我不确定你是想对所有 subview 执行此操作,还是只对父 View 执行此操作,但通常你只需要对单个“父” View 执行此操作即可正常工作对于该 View 的子项。
与此相关,我不太明白为什么在缩放父 View 时将缩放因子向下传递给每个 subview 也会缩放其所有 subview 。也许您只需要将一个 FrameLayout
(或其他一些 ViewGroup
后代)添加到托 pipe 项的 HorizontalScrollView
中,然后缩放它(在适本地设置它的枢轴之后)?
更新评论
鉴于您只想缩放手指之间捏合区域的 View ,我相信您有几个选择,具体取决于您的应用:
1) 动态地将这些 View 添加到一个中间 FrameLayout
中,它会缩放并设置其轴心,将非缩放 View 保留为 HorizontalScrollView
的直接 subview ;或
2) 在第一次调整 child 的位置后,将焦点向下传递到每个缩放的 subview 。例如,假设您的 DrawView
直接或间接继承自 android.view.View
,我强烈建议您这样做,那么您可以执行以下操作:
for (int i = start; i <= last; i++) {
LinearLayout ll = (LinearLayout)pp.getChildAt(i);
DrawView view = (DrawView)ll.findViewById(R.id.drawview);
view.setScaleX(mScaleFactor);
view.setScaleY(mScaleFactor);
view.setPivotX(detector.getFocusX() - view.getLeft()); // Note: minus, not plus...
view.setPivotY(detector.getFocusY() - view.getTop());
view.invalidate();
}
关于java - 在android中围绕两个手指的中点缩放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23358112/