OnTouch ACTION_DOWN需要调整ImageView的高度

时间:2014-06-03 12:48:40

标签: android imageview draggable

我正在浏览Tinder App的用户界面。我非常喜欢ImageView的Drag事件,我想实现相同的功能。我来了一点。但是当我缩放时,我找不到任何解决方案来刷新视图或增加视图的高度。

希望有人可以帮助我。

package com.scaleimageview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.util.Log;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class ScaleImageView extends ImageView implements OnTouchListener,
        OnDragListener {
    private Context mContext;
    private float MAX_SCALE = 2f;

    private Matrix mMatrix;
    private final float[] mMatrixValues = new float[9];

    // display width height.
    private int mWidth;
    private int mHeight;

    private int mIntrinsicWidth;
    private int mIntrinsicHeight;

    private float mScale;
    private float mMinScale;

    private float mPrevDistance;
    private boolean isScaling;

    private int mPrevMoveX;
    private int mPrevMoveY;
    private GestureDetector mDetector;

    String TAG = "ScaleImageView";

    public ScaleImageView(Context context, AttributeSet attr) {
        super(context, attr);
        this.mContext = context;
        initialize();
    }

    public ScaleImageView(Context context) {
        super(context);
        this.mContext = context;
        initialize();
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        this.initialize();
    }

    @Override
    public void setImageResource(int resId) {
        super.setImageResource(resId);
        this.initialize();
    }

    private void initialize() {
        this.setScaleType(ScaleType.MATRIX);
        this.mMatrix = new Matrix();
        Drawable d = getDrawable();
        if (d != null) {
            mIntrinsicWidth = d.getIntrinsicWidth();
            mIntrinsicHeight = d.getIntrinsicHeight();
            setOnTouchListener(this);
            setOnDragListener(this);
        }
        mDetector = new GestureDetector(mContext,
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onDoubleTap(MotionEvent e) {
                        // maxZoomTo((int) e.getX(), (int) e.getY());
                        // cutting();
                        return super.onDoubleTap(e);
                    }
                });

    }

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

        Log.d("TAG", "called");
        setMeasuredDimension(measureWidth(widthMeasureSpec),
                measureHeight(heightMeasureSpec));
        this.postInvalidate();
    }

    private int measureWidth(int measureSpec) {

        Log.i("TAG WIDTH", measureSpec + "");
        int preferred = this.getWidth() * 2;
        return getMeasurement(measureSpec, preferred);
    }

    private int measureHeight(int measureSpec) {

        Log.i("TAG HEIGHT", measureSpec + "");
        int preferred = measureSpec * 2;
        return getMeasurement(measureSpec, preferred);
    }

    private int getMeasurement(int measureSpec, int preferred) {
        int specSize = MeasureSpec.getSize(measureSpec);
        int measurement = 0;

        switch (MeasureSpec.getMode(measureSpec)) {
        case MeasureSpec.EXACTLY:

            Log.d(TAG, "Exactly : " + specSize + "");
            measurement = specSize;

            break;
        case MeasureSpec.AT_MOST:
            Log.d(TAG, "At most : " + specSize + "");
            // Take the minimum of the preferred size and what
            // we were told to be.
            measurement = Math.min(preferred, specSize);
            break;

        case MeasureSpec.UNSPECIFIED:
            measurement = preferred;
            Log.d("TAG UNSPECK", "This is called Prefered " + preferred
                    + " This is for specSize : " + specSize);
        default:
            measurement = preferred;
            break;
        }

        return measurement;
    }

    @Override
    protected boolean setFrame(int l, int t, int r, int b) {
        mWidth = r - l;
        mHeight = b - t;

        mMatrix.reset();
        int r_norm = r - l;
        mScale = (float) r_norm / (float) mIntrinsicWidth;

        int paddingHeight = 0;
        int paddingWidth = 0;
        // scaling vertical
        if (mScale * mIntrinsicHeight > mHeight) {
            mScale = (float) mHeight / (float) mIntrinsicHeight;
            mMatrix.postScale(mScale, mScale);
            paddingWidth = (r - mWidth) / 2;
            paddingHeight = 0;
            // scaling horizontal
        } else {
            mMatrix.postScale(mScale, mScale);
            paddingHeight = (b - mHeight) / 2;
            paddingWidth = 0;
        }
        mMatrix.postTranslate(paddingWidth, paddingHeight);

        setImageMatrix(mMatrix);
        mMinScale = mScale;
        zoomTo(mScale, mWidth / 2, mHeight / 2);

        // this.onMeasure(480, 500);
        cutting();
        return super.setFrame(l, t, r, b);
    }

    protected float getValue(Matrix matrix, int whichValue) {
        matrix.getValues(mMatrixValues);
        return mMatrixValues[whichValue];
    }

    protected float getScale() {
        return getValue(mMatrix, Matrix.MSCALE_X);
    }

    public float getTranslateX() {
        return getValue(mMatrix, Matrix.MTRANS_X);
    }

    protected float getTranslateY() {
        return getValue(mMatrix, Matrix.MTRANS_Y);
    }

    protected void maxZoomTo(int x, int y) {
        if (mMinScale != getScale() && (getScale() - mMinScale) > 0.1f) {
            // threshold 0.1f
            float scale = mMinScale / getScale();
            zoomTo(scale, x, y);
        } else {
            float scale = MAX_SCALE / getScale();
            zoomTo(scale, x, y);
        }
    }

    public void zoomTo(float scale, int x, int y) {
        if (getScale() * scale < mMinScale) {
            return;
        }
        if (scale >= 1 && getScale() * scale > MAX_SCALE) {
            return;
        }
        mMatrix.postScale(scale, scale);
        // move to center
        mMatrix.postTranslate(-(mWidth * scale - mWidth) / 2,
                -(mHeight * scale - mHeight) / 2);

        // move x and y distance
        mMatrix.postTranslate(-(x - (mWidth / 2)) * scale, 0);
        mMatrix.postTranslate(0, -(y - (mHeight / 2)) * scale);
        setImageMatrix(mMatrix);
    }

    public void cutting() {
        int width = (int) (mIntrinsicWidth * getScale());
        int height = (int) (mIntrinsicHeight * getScale());
        if (getTranslateX() < -(width - mWidth)) {
            mMatrix.postTranslate(-(getTranslateX() + width - mWidth), 0);
        }
        if (getTranslateX() > 0) {
            mMatrix.postTranslate(-getTranslateX(), 0);
        }
        if (getTranslateY() < -(height - mHeight)) {
            mMatrix.postTranslate(0, -(getTranslateY() + height - mHeight));
        }
        if (getTranslateY() > 0) {
            mMatrix.postTranslate(0, -getTranslateY());
        }
        if (width < mWidth) {
            mMatrix.postTranslate((mWidth - width) / 2, 0);
        }
        if (height < mHeight) {
            mMatrix.postTranslate(0, (mHeight - height) / 2);
        }
        setImageMatrix(mMatrix);
    }

    private float distance(float x0, float y0) {
        float x = x0;// - x1;
        float y = y0; // - y1;
        return FloatMath.sqrt(x * x + y * y);
    }

    private float dispDistance() {
        return FloatMath.sqrt(mWidth * mWidth + mHeight * mHeight);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mDetector.onTouchEvent(event)) {
            return true;
        }
        int touchCount = event.getPointerCount();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_POINTER_INDEX_MASK:
            if (touchCount == 1) {

                Log.d("TAG", touchCount + "");
                float distance = distance(event.getX(0), event.getY(0));
                mPrevDistance = distance;
                this.measure(480, 500);
                isScaling = true;
            } else {
                mPrevMoveX = (int) event.getX();
                mPrevMoveY = (int) event.getY();
            }
            break;
        case MotionEvent.ACTION_POINTER_2_DOWN:

        case MotionEvent.ACTION_MOVE:
            if (touchCount == 1 && isScaling) {
                float dist = distance(event.getX(0), event.getY(0));
                float scale = (dist - mPrevDistance) / dispDistance();
                this.measure(480, 500);
                mPrevDistance = dist;
                scale += 1;
                scale = scale * scale;
                zoomTo(scale, mWidth / 2, mHeight / 2);
                cutting();
            } else if (!isScaling) {
                int distanceX = mPrevMoveX - (int) event.getX();
                int distanceY = mPrevMoveY - (int) event.getY();
                mPrevMoveX = (int) event.getX();
                mPrevMoveY = (int) event.getY();
                mMatrix.postTranslate(-distanceX, -distanceY);
                cutting();
            }
            break;
        case MotionEvent.ACTION_UP:
            // if (isScaling) {
            // isScaling = false;
            // // handle single click
            // } else if (ScaleImageView.this.isDragging()) {
            // new Handler().postDelayed(new Runnable() {
            // @Override
            // public void run() {
            // if (this.isDragging()) {
            // // Drop never got received, so call stopDrag
            // this.stopDrag();
            // }
            // }
            // }, 1000);
            // }
            // break;
        case MotionEvent.ACTION_POINTER_UP:
        case MotionEvent.ACTION_POINTER_2_UP:
            if (event.getPointerCount() <= 1) {
                isScaling = false;
            }
            break;
        }
        return true;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int height = dpToPx(500);
        Log.e("TAG", "" + height);
        this.measure(this.getWidth(), height);
        this.invalidate();
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onDrag(View v, DragEvent event) {
        int action = event.getAction();
        switch (action) {
        case DragEvent.ACTION_DRAG_STARTED:

            break;
        case DragEvent.ACTION_DRAG_EXITED:
            // int ht = dpToPx(500);
            // Log.e("TAG EXITED", "" + ht);
            // this.measure(image.getWidth(), ht);
            // Log.d("TAG", "Drag event exited from " + v.toString());
            break;
        }
        return true;
    }

    public int dpToPx(int dp) {
        DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
        int px = Math.round(dp
                * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
        return px;
    }
}

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

public View.OnTouchListener listener(final float screen_width){

    View.OnTouchListener listener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            float oldx = screen_width/2 , fraction, min_alpha = 0.5f;

            switch (event.getAction()) {

                case MotionEvent.ACTION_DOWN:
                    oldx = event.getRawX();
                    break;


                case MotionEvent.ACTION_MOVE:
                    //Get the distance of the touch from the initial touch point of the screen and divide it by half the screen width
                     fraction = ((event.getRawX() - oldx) / (screen_width/2) );

                    //set the view's rotation based on how far the user drags the image
                    view.setRotation(90 * fraction);

                    //set transparency of the view
                    view.setAlpha(1f - Math.abs(fraction) * ((1f - min_alpha)));
                    break;

                case MotionEvent.ACTION_UP:

                    break;

            }

            return true;
        }

    };

    return listener;
}

设置触摸侦听器说:imageView.setOnTouchListener(listener(screen_width)),以获取屏幕:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
screen_width = metrics.widthPixels;

*请注意,您可能需要更改imageView的轴心,以使旋转看起来接近于火种:

imageView.setPivotX(imageView.getWidth()/2);
imageView.setPivotY(imageView.getHeight());