我有一个HorizontalScrollView
,里面有多个视图。我已经实现了pinch zoom gesture
,其中缩放了我的两个手指之间的多个视图。
但我面临一个小故障。当我进行捏缩放时,捏缩放的中点正在移动但是为了用户体验,我希望这个点保持固定,其他东西应该在缩放时自行调整,以使中点保持静止。
有人可以告诉我该怎么做。
自定义视图的 onDraw()
方法是
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);
}
上述自定义视图由HorizontalScrollView
的子类调用12次。因此,HorizontalScrollview
有12个子视图。
在本课程中,我正在做以下事情
检测两根手指的触摸坐标。
计算触摸第一根手指的子视图的索引。
计算触摸第二根手指的子视图的索引。
将捏拉缩放的比例因子传递给start和last之间的所有子视图。 这两个指数是在前两个步骤中计算出来的。
最后在子视图上调用invalidate()。因此,孩子可以根据父视图传递的比例因子进行缩放。
但这里有一个问题。两个手指的中点应该保持静止,其他东西应该在缩放期间调整。但我的中点是随着扩展而变化。
有人可以帮我这么做吗?请告诉我代码的任何部分是否需要。
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;
}
这是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();
}
答案 0 :(得分:0)
对于您正在缩放的视图,您可以设置&#34;不变&#34;不应使用setPivotX()
和setPivotY()
移动的点。当我使用ScaleGestureDetector
时,我会使用focus
点。例如:
@Override
public boolean onScaleBegin(ScaleGestureDetector detector)
{
...
mScaledView.setPivotX(detector.getFocusX());
mScaledView.setPivotY(detector.getFocusY());
...
在您的情况下,我不确定您是否要与所有孩子或父视图一起执行此操作,但通常您只需要对单个&#34;父母进行此操作&#34 ;视图,它将适用于该视图的孩子。
与此相关,我并不完全理解为什么在缩放父视图时将比例因子传递给每个孩子也会扩展其所有子项。也许您只需要在托管孩子的FrameLayout
中添加一个ViewGroup
(或其他HorizontalScrollView
后代),然后只需缩放(在适当设置其轴后)?
更新了评论
鉴于您只想在手指之间的缩小区域缩放视图,我相信您有几个选项,具体取决于您的应用:
1)将这些视图动态添加到中间FrameLayout
,后者得到缩放并设置其轴心,将非缩放视图保留为HorizontalScrollView
的直接子视图;或
2)在首先调整孩子的位置后,将焦点向下传递到每个缩放的子视图。例如,假设您的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();
}