【发布时间】:2014-10-03 11:50:08
【问题描述】:
我有以下情况:
ZoomAndPanLayout
|
+---> ImageView
|
+---> FrameLayout (DragLayer)
|
+---> One or more controls. A view with a circle drawn on it.
有一些小问题,因为我现在不关心 ZoomAndPanLayout 工作的屏幕绑定。我这样实现了 ZoomAndPan:
public class ZoomAndPanLayout extends FrameLayout {
//region Constants
public static final float DEFAULT_MIN_SCALE_FACTOR = 1.0f;
public static final float DEFAULT_MAX_SCALE_FACTOR = 5.0f;
// endregion Constants
// region Fields
private float translationX = 0;
private float translationY = 0;
private float pivotX = 0;
private float pivotY = 0;
private float oldX;
private float oldY;
private float scaleFactor = 1.0f;
private float minScaleFactor = ZoomAndPanLayout.DEFAULT_MIN_SCALE_FACTOR;
private float maxScaleFactor = ZoomAndPanLayout.DEFAULT_MAX_SCALE_FACTOR;
private ScaleGestureDetector scaleGestureDetector = null;
// endregion Fields
// region Constructor
public ZoomAndPanLayout(Context context) {
super(context);
this.initialize(context);
}
public ZoomAndPanLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.initialize(context);
}
public ZoomAndPanLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.initialize(context);
}
private void initialize(Context context) {
this.scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
}
// endregion Constructor
@Override
public boolean onTouchEvent(MotionEvent event) {
this.scaleGestureDetector.onTouchEvent(event);
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
this.oldX = event.getX();
this.oldY = event.getY();
break;
}
case MotionEvent.ACTION_MOVE:
{
if (!this.scaleGestureDetector.isInProgress())
{
float x = event.getX();
float y = event.getY();
float deltaX = x - this.oldX;
float deltaY = y - this.oldY;
this.translationX += deltaX;
this.translationY += deltaY;
this.applyTransformations();
this.oldX = x;
this.oldY = y;
}
}
}
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return this.scaleGestureDetector.onTouchEvent(event);
}
private void applyTransformations() {
final View child = this.getChildAt(0);
if (child != null)
{
child.setPivotX(this.pivotX);
child.setPivotY(this.pivotY);
child.setScaleX(this.scaleFactor);
child.setScaleY(this.scaleFactor);
// TODO: bound child to screen limits
child.setTranslationX(this.translationX);
child.setTranslationY(this.translationY);
}
}
public Rect getChildRect() {
View child = this.getChildAt(0);
if (child != null)
{
Rect outRect = new Rect();
outRect.right = (int) (child.getWidth() * child.getScaleX());
outRect.bottom = (int) (child.getHeight() * child.getScaleY());
int[] location = new int[2];
child.getLocationOnScreen(location);
outRect.offset(location[0], location[1]);
return outRect;
}
else
{
return new Rect(0, 0, 0, 0);
}
}
// region Private Inner Enums, Interfaces and Classes
private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
private ZoomAndPanLayout upper = ZoomAndPanLayout.this;
@Override
public boolean onScale(ScaleGestureDetector detector) {
float newScaleFactor = detector.getScaleFactor();
float originalScaleFactor = upper.scaleFactor;
upper.scaleFactor *= newScaleFactor;
// Bound the scaleFactor to the min and max limits
if (upper.scaleFactor >= upper.maxScaleFactor)
{
upper.scaleFactor = upper.maxScaleFactor;
newScaleFactor = upper.maxScaleFactor / originalScaleFactor;
}
else if (upper.scaleFactor * newScaleFactor <= upper.minScaleFactor)
{
upper.scaleFactor = upper.minScaleFactor;
newScaleFactor = upper.minScaleFactor / originalScaleFactor;
}
// set pivot
View child = upper.getChildAt(0);
if (child != null)
{
if (newScaleFactor * child.getWidth() * upper.scaleFactor <= originalScaleFactor * child.getWidth()
|| newScaleFactor * child.getHeight() * upper.scaleFactor <= originalScaleFactor * child.getWidth())
{
upper.pivotX = newScaleFactor * child.getWidth() / 2;
upper.pivotY = newScaleFactor * child.getHeight() / 2;
}
else
{
upper.pivotX = detector.getFocusX();
upper.pivotY = detector.getFocusY();
}
}
upper.applyTransformations();
return true;
}
}
// endregion Private Inner Enums, Interfaces and Classes
}
当我创建 DragLayer 的每个子级时,我为它们分配了一个 OnLongClickListener,但该死的东西不会触发。当我长按 DragLayer 的任何子项时。
知道如何使用我的 ZoomAndPanLayout 想法或任何想法来实现这一点。如果你问自己为什么需要 ZoomAndPanLayout,那是因为我必须能够缩放和平移任何布局,而不仅仅是 ImageView。
有什么想法吗?
【问题讨论】:
标签: android drag-and-drop zooming drag