【Android】可移动的ImageView

 

 

可移动的ImageView

 

 

今天做了一个可移动的ImageView,要点如下:

1 ontouch

2 ongloballayout

3 image放置适当的位置

4 matrix变换(平移,缩放)

代码很简单

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context=".MainActivity">  
  
    <com.none.view.MoveImage  
        android:id="@+id/id_img"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        android:scaleType="matrix" />  
  
</RelativeLayout>  

MainActivity.java

package com.none.moveimage;  
  
import android.support.v7.app.ActionBarActivity;  
import android.os.Bundle;  
import android.view.Menu;  
import android.view.MenuItem;  
import android.widget.ImageView;  
  
import com.none.view.MoveImage;  
  
  
public class MainActivity extends ActionBarActivity {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
  
        MoveImage img = (MoveImage)findViewById(R.id.id_img);  
        img.setImageResource(R.drawable.dou);  
    }  
}  

MoveImage.java

package com.none.view;  
  
import android.content.Context;  
import android.graphics.Matrix;  
import android.graphics.RectF;  
import android.graphics.drawable.Drawable;  
import android.util.AttributeSet;  
import android.view.MotionEvent;  
import android.view.View;  
import android.view.ViewConfiguration;  
import android.view.ViewTreeObserver;  
import android.widget.ImageView;  
  
/** 
 * Created by pc on 2015/5/11. 
 */  
public class MoveImage extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener, View.OnTouchListener {  
  
    private boolean mInit;  
    private boolean mIsCanMove;  
    private float mLastX;  
    private float mLastY;  
    private Matrix mScaleMatrix;  
    private int mMoveSlop;  
  
    public MoveImage(Context context) {  
        this(context, null);  
    }  
  
    public MoveImage(Context context, AttributeSet attrs) {  
        this(context, attrs, 0);  
    }  
  
    public MoveImage(Context context, AttributeSet attrs, int defStyleAttr) {  
        super(context, attrs, defStyleAttr);  
  
        init(context);  
    }  
  
    private void init(Context context) {  
        mScaleMatrix = new Matrix();  
        mMoveSlop = ViewConfiguration.get(context).getScaledTouchSlop();  
        setOnTouchListener(this);  
        mIsCanMove = false;  
    }  
  
    @Override  
    protected void onAttachedToWindow() {  
        getViewTreeObserver().addOnGlobalLayoutListener(this);  
    }  
  
    @Override  
    protected void onDetachedFromWindow() {  
        getViewTreeObserver().removeOnGlobalLayoutListener(this);  
    }  
  
    @Override  
    public void onGlobalLayout() {  
        if (!mInit) {  
            Drawable d = getDrawable();  
            if (d != null) {  
                float scale = 1.0f;  
  
                int dw = d.getIntrinsicWidth();  
                int dh = d.getIntrinsicHeight();  
  
                int width = getWidth();  
                int height = getHeight();  
  
                if (dw > width && dh < height) {  
                    scale = width * 1.0f / dw;  
                } else if (dw < width && dh > height) {  
                    scale = height * 1.0f / dh;  
                } else if (dw < width && dh < height) {  
                    scale = Math.min(width * 1.0f / dw, height * 1.0f / dh);  
                } else if (dw > width && dh > height) {  
                    scale = Math.min(width * 1.0f / dw, height * 1.0f / dh);  
                } else {  
                    scale = 1.0f;  
                }  
  
                int centerX = (width - dw) / 2;  
                int centerY = (height - dh) / 2;  
                mScaleMatrix.postTranslate(centerX, centerY);  
                scale = scale / 2.0f;  
                mScaleMatrix.postScale(scale, scale, width / 2, height / 2);  
                setImageMatrix(mScaleMatrix);  
            }  
        }  
        mInit = true;  
    }  
  
    private RectF getMatrixRectF() {  
        RectF rectf = new RectF();  
        final Matrix matrix = mScaleMatrix;  
        Drawable d = getDrawable();  
        if (d != null) {  
            rectf.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());  
            matrix.mapRect(rectf);  
        }  
        return rectf;  
    }  
  
    private boolean isMoveAction(float dx, float dy) {  
        return Math.sqrt(dx * dx + dy * dy) > mMoveSlop;  
    }  
  
    @Override  
    public boolean onTouch(View v, MotionEvent event) {  
        RectF rectF = getMatrixRectF();  
        switch (event.getAction()) {  
            case MotionEvent.ACTION_DOWN:  
                mLastX = event.getX();  
                mLastY = event.getY();  
                mIsCanMove = rectF.contains(mLastX, mLastY);  
                break;  
            case MotionEvent.ACTION_MOVE:  
                if (mIsCanMove) {  
                    float x = event.getX();  
                    float y = event.getY();  
                    float deltaX = x - mLastX;  
                    float deltaY = y - mLastY;  
  
                    if (isMoveAction(deltaX, deltaY)) {  
                        checkBorderWhenMove(deltaX, deltaY, rectF);  
                        setImageMatrix(mScaleMatrix);  
                    }  
  
                    mLastX = x;  
                    mLastY = y;  
                }  
                break;  
            case MotionEvent.ACTION_UP:  
            case MotionEvent.ACTION_CANCEL:  
                mIsCanMove = false;  
                break;  
        }  
        return true;  
    }  
  
    private void checkBorderWhenMove(float deltaX, float deltaY, RectF rectF) {  
        int width = getWidth();  
        int height = getHeight();  
  
        if (rectF.left + deltaX < 0) {  
            deltaX = -rectF.left;  
        } else if (rectF.right + deltaX > width) {  
            deltaX = width - rectF.right;  
        }  
        if (rectF.top + deltaY < 0) {  
            deltaY = -rectF.top;  
        } else if (rectF.bottom + deltaY > height) {  
            deltaY = height - rectF.bottom;  
        }  
        mScaleMatrix.postTranslate(deltaX, deltaY);  
    }  
}  


其中图片缩放使用了matrix方式,在xml中需要将imageview的scale方式设置为matrix。

 

之后在根据ongloballayout中的得到的图片size和屏幕大小进行比例计算,之后使用matrix.postscale对图片进行缩放。

图片的平移使用了matrix.posttranslate,平移的距离可随意指定。

另外还需要获得每次缩放后图片的rectf,也就是图片当前的位置。这个可以使用matrix.maprect获得。

最后在ontouch中控制图片的平移,在Down中对触摸点进行判断,非图片的点击不会对图片产生影响,当点击的是图片时,使用setimagematrix对图片移动进行刷新。

在移动的过程中判断图片是否会移动出屏幕,对上下左右进行判断,防止图片移动出屏幕。

 

参考http://www.imooc.com/learn/239中对图片伸缩和伸缩和的上下左右位置的处理。


Taily老段的微信公众号,欢迎交流学习

https://blog.csdn.net/taily_duan/article/details/81214815


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值