コンテンツのパンとズームをサポートする ViewGroup を作成しようとしています。私がオンラインで見つけたのは、ImageView でこれを行うためのアイデアと実装だけでしたが、コンテナーではありませんでした。地図を表示したいのですが、その上に ImageButton である複数のマーカーを表示したいので、ユーザーはそれらをタップして詳細情報を取得できます。これは、iOS では UIScrollView によって実現されますが、Android では代替手段が見つかりませんでした。
FrameView を使用することにしたので、画像を背景として ImageView を設定し、その上に RelativeLayout を追加して、ImageButton を追加し、余白を使用して配置することができました。
ここでTouchImageView の実装の一部を借りましたが、問題が発生しました。私はパンニングから始めましたが、部分的に成功しました。コンテナをパンしますが、パンニングは恐ろしく機能し、多くのジッターが発生します。これが私のコードです:
public class ScrollingViewGroup extends FrameLayout {
private int x = 0;
private int y = 0;
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
public ScrollingViewGroup(Context context) {
super(context);
sharedConstructing(context);
}
public ScrollingViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
sharedConstructing(context);
}
private void sharedConstructing(Context context) {
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
Log.d("ScrollingViewGroup", Float.toString(deltaX));
Log.d("ScrollingViewGroup", Float.toString(deltaY));
float scaleWidth = Math.round(origWidth * saveScale);
float scaleHeight = Math.round(origHeight * saveScale);
x += deltaX;
y += deltaY;
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
// setImageMatrix(matrix);
setTranslationX(x);
setTranslationY(y);
invalidate();
return true; // indicate event was handled
}
});
}
どんなアイデアでも大歓迎です。
編集:移動するときに、デルタXとデルタYが正と負の数値を交互に繰り返し、LogCatをチェックするため、ジッターが原因のようです...理由はまだわかりません。これは、毎回異なる値を与える curr 変数によって引き起こされますが、一貫性がなく、指が前進するだけでなく、前後に動いているように見えます。たとえば、curr.x は 0、1、2、3、4 などではなく、0、1、0.5、2、1.5 などです。理由もわかりません。