代码之家  ›  专栏  ›  技术社区  ›  Scott Smith

在布局中旋转图像视图…如何?

  •  3
  • Scott Smith  · 技术社区  · 15 年前

    我有一个布局,上面有一个图像(嵌入在图像视图中)。我需要把图像逆时针旋转90度。

    我已经编写了代码来动画图像旋转…:

    public class MainActivity extends Activity
    {
        private ImageView mImageView = null;
        private Animation mRotateAnimation = null;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            mImageView = (ImageView) findViewById(R.id.my_image);
            mRotateAnimation = AnimationUtils.loadAnimation(this, R.anim.my_rotate_90);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                mImageView.startAnimation(mRotateAnimation);
                return true;
            }
            return super.onTouchEvent(event);
        }
    }
    

    图像平滑地旋转90度,但随后会捕捉回其原始状态。这就是安卓文档所说的动画完成后会发生的事情。大概,在动画结束的通知中,我应该转换ImageView(或底层Drawable),并可能使其无效以触发重绘。

    一切都很好,除了 我找不到方法,也找不到任何其他人这样做的例子 .

    我试着用 getImageMatix / setImageMatrix mImageView 没有明显效果。Drawable的子类将旋转图像,但在ImageView上没有setDrawable()方法,所以我不知道如何使用它。

    我搜索了一些例子;虽然其中有一些涉及动画和旋转(特别是lunarlander),但没有一个是动画图像视图,然后将其保留在某种转换状态。

    我肯定错过了一些简单的东西…aaaargh,如何在布局中旋转图像视图?

    谢谢。

    2 回复  |  直到 15 年前
        1
  •  2
  •   Cheryl Simon    15 年前

    ImageView SetImageDrawable将配置图像中的Drawable。这应该允许您使用ImageView类,从而在上面使用矩阵函数。

        2
  •  0
  •   Android Leo    10 年前

    试试这个多点触摸视图,它对我很管用。

    public class MultiTouchImageView extends ImageView implements OnTouchListener{
    
    float[] lastEvent = null;
    float d = 0f;
    float newRot = 0f;
    public static String fileNAME;
    public static int framePos = 0;
    //private ImageView view;
    private boolean isZoomAndRotate;
    private boolean isOutSide;
    // We can be in one of these 3 states
    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;
    
    private PointF start = new PointF();
    private PointF mid = new PointF();
    float oldDist = 1f;
    public MultiTouchImageView(Context context) {
        super(context);
    }
    
    
    public MultiTouchImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    
    
    public MultiTouchImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    
    @SuppressWarnings("deprecation")
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //view = (ImageView) v;
        bringToFront();
        // Handle touch events here...
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            //savedMatrix.set(matrix);
            start.set(event.getX(), event.getY());
            mode = DRAG;
            lastEvent = null;
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            oldDist = spacing(event);
            if (oldDist > 10f) {
                midPoint(mid, event);
                mode = ZOOM;
            }
    
            lastEvent = new float[4];
            lastEvent[0] = event.getX(0);
            lastEvent[1] = event.getX(1);
            lastEvent[2] = event.getY(0);
            lastEvent[3] = event.getY(1);
            d =  rotation(event);
            break;
        case MotionEvent.ACTION_UP:
            isZoomAndRotate = false;
        case MotionEvent.ACTION_OUTSIDE:
            isOutSide = true;
            mode = NONE;
            lastEvent = null;
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            lastEvent = null;
            break;
        case MotionEvent.ACTION_MOVE:
            if(!isOutSide){
                if (mode == DRAG && !isZoomAndRotate) {
                    isZoomAndRotate = false;
                    setTranslationX((event.getX() - start.x) + getTranslationX());
                    setTranslationY((event.getY() - start.y) + getTranslationY());
                } else if (mode == ZOOM && event.getPointerCount() == 2) {
                    isZoomAndRotate = true;
                    boolean isZoom = false;
                    if(!isRotate(event)){
                        float newDist = spacing(event);
                        if (newDist > 10f) {
                            float scale = newDist / oldDist * getScaleX();
                            setScaleX(scale);
                            setScaleY(scale);
                            isZoom = true;
                        }
                    }
                    else if(!isZoom){
                        newRot = rotation(event);
                        setRotation((float)(getRotation() + (newRot - d)));
                    }
                }
            }
    
            break;
        }
        new GestureDetector(new MyGestureDectore());
        Constants.currentSticker = this;
        return true;
    }
    private class MyGestureDectore extends GestureDetector.SimpleOnGestureListener{
    
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            bringToFront();
            return false;
        }
    
        @Override
        public boolean onDoubleTapEvent(MotionEvent e) {
            return false;
        }
    
    }
    private float rotation(MotionEvent event) {
        double delta_x = (event.getX(0) - event.getX(1));
        double delta_y = (event.getY(0) - event.getY(1));
        double radians = Math.atan2(delta_y, delta_x);
        return (float) Math.toDegrees(radians);
    }
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }
    
    private void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }
    
    private boolean isRotate(MotionEvent event){
        int dx1 = (int) (event.getX(0) - lastEvent[0]);
        int dy1 = (int) (event.getY(0) - lastEvent[2]);
        int dx2 = (int) (event.getX(1) - lastEvent[1]);
        int dy2 = (int) (event.getY(1) - lastEvent[3]);
        Log.d("dx1 ", ""+ dx1);
        Log.d("dx2 ", "" + dx2);
        Log.d("dy1 ", "" + dy1);
        Log.d("dy2 ", "" + dy2);
        //pointer 1
        if(Math.abs(dx1) > Math.abs(dy1) && Math.abs(dx2) > Math.abs(dy2)) {
            if(dx1 >= 2.0 && dx2 <=  -2.0){
                Log.d("first pointer ", "right");
                return true;
            }
            else if(dx1 <= -2.0 && dx2 >= 2.0){
                Log.d("first pointer ", "left");
                return true;
            }
        }
        else {
             if(dy1 >= 2.0 && dy2 <=  -2.0){
                    Log.d("seccond pointer ", "top");
                    return true;
                }
                else if(dy1 <= -2.0 && dy2 >= 2.0){
                    Log.d("second pointer ", "bottom");
                    return true; 
                }
    
        }
    
        return false;
    }
    }