Задать вопрос
@devolegf

Как поправить CustomViewGroup on Fragment?

Доброго времени суток.. Ситуация следующая: есть компонент наследованный от ViewGroup в котором реализовано pinch-to-zoom, внутри размещаются еще несколько TextView и ImageView. В приложении 3 Fragments в каждом из которых должен быть этот компонент.. Пример:
<?xml version="1.0" encoding="utf-8"?>
<name.launcher.view.ZoomableViewGroup
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    >
    <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/ll2"
        >
    <ImageView
        android:src="@drawable/diff"
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:scaleType="centerCrop"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true" />
    <TextView
        android:text="TextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tvPage" />
    <TextView
        android:text="TextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tvPage1" />
    <Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_x="16dp"
        android:layout_y="193dp"
        android:id="@+id/btnUpdate" />
    </AbsoluteLayout>
</name.launcher.view.ZoomableViewGroup>


Первый фрагмент создается правильно(отображается содержимое, можно нажимать на кнопки ).., при листании другие отображаются пустыми, только после нескольких операций уменьшение масштаба появляются из одного края содержимое компонента и тогда его можно двигать по фрагменту..если не использовать данный компонент то содержимое всех фрагментов отображается нормально.. Подскажите в чем загвоздка? Куда нужно смотреть ?
Код компонента:
public class ZoomableViewGroup extends ViewGroup {
    private enum Mode {
        NONE,
        DRAG,
        ZOOM
    }

    private ZoomableViewGroup.Mode mode = ZoomableViewGroup.Mode.NONE;
    private float scale = 1.0f;
    private float lastScaleFactor = 0f;
    private float mFocusY;

    private float mFocusX;
    private ScaleGestureDetector mScaleDetector;

    private static final float MIN_ZOOM = 1.0f;
    private static final float MAX_ZOOM = 3.5f;

    private float startX = 0f;
    private float startY = 0f;

    // How much to translate the canvas
    private float dx = 0f;
    private float dy = 0f;
    private float prevDx = 0f;
    private float prevDy = 0f;

    private Matrix mScaleMatrix = new Matrix();
    private Matrix mScaleMatrixInverse = new Matrix();

    private Matrix mTranslateMatrix = new Matrix();
    private Matrix mTranslateMatrixInverse = new Matrix();

    private float[] mInvalidateWorkingArray = new float[6];
    private float[] mDispatchTouchEventWorkingArray = new float[2];
    private float[] mOnTouchEventWorkingArray = new float[2];

    public ZoomableViewGroup(Context context) {
        super(context);
    }

    public ZoomableViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ZoomableViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
        mTranslateMatrix.setTranslate(0, 0);
        mScaleMatrix.setScale(1, 1);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            Log.i("CUSTOM", "Width: " + child.getWidth());
            if (child.getVisibility() != GONE) {
                child.layout(l, t, l + child.getMeasuredWidth(), t + child.getMeasuredHeight());
            }
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.save();
        //canvas.translate(startX, startY);
        //canvas.scale(scale, scale);
        super.dispatchDraw(canvas);
        postInvalidate();
        canvas.restore();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);

            if (child.getVisibility() != GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent motionEvent) {

        switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                Log.i("CUSTOM", "DOWN");
                if (scale > MIN_ZOOM) {
                    mode = Mode.DRAG;
                    startX = motionEvent.getX() - prevDx;
                    startY = motionEvent.getY() - prevDy;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == Mode.DRAG) {
                    dx = motionEvent.getX() - startX;
                    dy = motionEvent.getY() - startY;
                }
                mTranslateMatrix.preTranslate(dx, dy);
                mTranslateMatrix.invert(mTranslateMatrixInverse);
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                mode = Mode.ZOOM;
                break;
            case MotionEvent.ACTION_POINTER_UP:
                mode = Mode.DRAG;
                break;
            case MotionEvent.ACTION_UP:
                Log.i("CUSTOM", "UP");
                mode = Mode.NONE;
                prevDx = dx;
                prevDy = dy;
                break;
        }
        mScaleDetector.onTouchEvent(motionEvent);

        if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
            getParent().requestDisallowInterceptTouchEvent(true);
            float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
            float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
            dx = Math.min(Math.max(dx, -maxDx), maxDx);
            dy = Math.min(Math.max(dy, -maxDy), maxDy);
            Log.i("CUSTOM", "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx
                    + ", max " + maxDx);
            applyScaleAndTranslation();
        }
        invalidate();

        return true;
    }

    private void applyScaleAndTranslation() {
        int childCount = getChildCount();
        child().setScaleX(scale);
        child().setScaleY(scale);
        child().setTranslationX(dx);
        child().setTranslationY(dy);
    }

    private View child() {
        return getChildAt(0);
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
            Log.i("CUSTOM", "onScaleBegin");
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {

            float scaleFactor = detector.getScaleFactor();
            Log.i("CUSTOM", "onScale" + scaleFactor);

            if (detector.isInProgress()) {
                mFocusX = detector.getFocusX();
                mFocusY = detector.getFocusY();
            }

            if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
                scale *= scaleFactor;
                scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
                lastScaleFactor = scaleFactor;
            } else {
                lastScaleFactor = 0;
            }
            invalidate();
            requestLayout();
            return true;
        }
    }

}
  • Вопрос задан
  • 103 просмотра
Подписаться 1 Оценить Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы