多点触控 实现图片自由缩放

来源:互联网 发布:床垫 知乎 编辑:程序博客网 时间:2024/05/02 01:20

由于需要真机测试, 所以没有弄效果图..


1, 建立一个类MultiTouch  继承 ImageView, 并在xml使用, 获取要缩放图片. 如果图片的宽/高大于屏幕宽/高, 那么我们进行缩放,并移动到屏幕中心点.

    那么问题来了. 如果我们在构造器中直接获取宽度 那么可能会获取不到. 我们需要知道布局什么时候加载完成. 这时候就需要用到一个接口 OnGlobalLayoutListener (全球布局监听)   实现 onGlobalLayout() 方法. 并且需要在view 从window出现时 监听它, 从window时 移除.

 于是对图片初始化的操作 都会在 onGlobalLayout()内执行.

2,我们还需要实现  OnScaleGestureListener  接口 来对 多点触控进行操作...    很方便

3. 把touch 事件 交给 OnScaleGestureListener .  


下面贴代码

public class MultiTouch extends ImageView implements OnGlobalLayoutListener,OnScaleGestureListener, OnTouchListener {private Context context;private boolean mOnce = false; // 初始化一次private float scale = 1.0f; // 默认缩放比private float mInitScale;// 初始化缩放比, 也就是最小缩放private float mMidScale; // 双击时的 缩放比private float mMaxScale; // 极限 最大 的缩放比private ScaleGestureDetector mScaleGestureDetector;private Matrix mMatrix;private Drawable drawable;public MultiTouch(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MultiTouch(Context context) {this(context, null);}public MultiTouch(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);this.context = context;// 初始化操作// 是一个 3*3的矩阵.// xScale xskwe xtrans// yskwe yscale ytrans// 0 0 0mMatrix = new Matrix();setOnTouchListener(this);}/** * 当 自定义空间 显示在window上 */@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();// 返回一个布局层级视图getViewTreeObserver().addOnGlobalLayoutListener(this);// 监听布局加载完成事件}/** * 当view 从window消失 */@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();// 取消监听getViewTreeObserver().removeGlobalOnLayoutListener(this);}// 当图片加载完成后, 图片大的话我们需要进行 缩小, 图片小的话我们需要进行放大.// 怎么知道图片加载完成 ? 需要实现 接口 OnGlobalLayoutListener 全球布局监听// 布局都加载完的方法. 需要注册@Overridepublic void onGlobalLayout() {// 初始化只需要一次. need boolean 变量if (!mOnce) {int width = getWidth(); // 控件宽int height = getHeight(); // 控件高drawable = getDrawable();if (drawable != null) {// 返回的是根据像素密度 变化后的值.. dip.// ldip * 0.75 mdip *1 hdip *1.5 xhdip*2 xxhdip *3int dw = drawable.getIntrinsicWidth();int dh = drawable.getIntrinsicHeight();// 图片宽大于 view宽, 高小于view 高if (dw > width && dh < height) {scale = width * 1.0f / dw;}// 图片宽小于view宽,高大于view高if (dw < width && dh > height) {scale = height * 1.0f / dh;}// 图片宽高 都大于 view宽高 || 图片宽高 都小于 view宽高if ((dw > width && dh > height) || (dw < width && dh < height)) {scale = Math.min(width * 1.0f / dw, height * 1.0f / dh);}mInitScale = scale; // 初始缩放比mMidScale = mInitScale * 2; // 双击时缩放比mMaxScale = mInitScale * 4; // 最大缩放比int dx = getWidth() / 2 - dw / 2;int dy = getHeight() / 2 - dh / 2;mMatrix.postTranslate(dx, dy);mMatrix.postScale(mInitScale, mInitScale);setImageMatrix(mMatrix);// 多点触控 的apimScaleGestureDetector = new ScaleGestureDetector(context, this);}mOnce = true;}}public float getScale() {float[] values = new float[9];mMatrix.getValues(values);return values[Matrix.MSCALE_X];}/** * 缩放进行 */@Overridepublic boolean onScale(ScaleGestureDetector detector) {float scale = getScale(); // 当前的缩放比float currScale = detector.getScaleFactor(); // 准备要缩放的值if (drawable == null)return true;if ((scale < mMaxScale && currScale > 1.0f)|| (scale > mInitScale && currScale < 1.0f)) {// 进行放大 || 缩小if (scale * currScale < mInitScale) { //当缩放比 小于最小点时 直接返回return true;}if (scale * currScale > mMaxScale) { // 当缩放比 大于最大点时,直接返回return true;}}mMatrix.postScale(currScale, currScale, detector.getFocusX(),detector.getFocusY());checkBorderAndCenterWhenScale();setImageMatrix(mMatrix);return true;}/** * 返回缩放时候图片的信息 *  * @return */private RectF getMatrixRectF() {Matrix matrix = mMatrix;RectF rect = new RectF();Drawable d = getDrawable();if (d != null) {rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());matrix.mapRect(rect); // 这样就能得到图片放大缩小以后的大小,位置}return rect;}/** * 检查边界和中心在缩放时 */private void checkBorderAndCenterWhenScale() {// 获取到缩放后的图片大小RectF rect = getMatrixRectF();float deltaX = 0f;float deltaY = 0f;int width = getWidth();int height = getHeight();//Log.v("info", "rect.left--->" + rect.left);//Log.v("info", "rect.top--->" + rect.top);//Log.v("info", "rect.right--->" + rect.right);//Log.v("info", "rect.bottom--->" + rect.bottom);//Log.v("info", "rect.width--->" + rect.width());//Log.v("info", "rect.height--->" + rect.height());if (rect.width() >= width) {if (rect.left > 0) {deltaX = -rect.left;}if (rect.right < width) {deltaX = width - rect.right;}}if (rect.height() >= height) {if (rect.top > 0) {deltaY = -rect.top;}if (rect.bottom < height) {deltaY = height - rect.bottom;}}// 如果宽度或高度 小于控件的宽和高 让齐居中if (rect.width() < width) {deltaX = width / 2f - rect.right + rect.width() / 2f;}if (rect.height() < height) {deltaY = height / 2f - rect.bottom + rect.height() / 2f;}mMatrix.postTranslate(deltaX, deltaY);}/** * 缩放开始 */@Overridepublic boolean onScaleBegin(ScaleGestureDetector detector) {// 必须返回truereturn true;}/** * 缩放结束 */@Overridepublic void onScaleEnd(ScaleGestureDetector detector) {}@Overridepublic boolean onTouch(View v, MotionEvent event) {mScaleGestureDetector.onTouchEvent(event);return true;}}


0 0
原创粉丝点击