Android实现手势控制ImageView图片大小
本文实例实现的主要功能是在ImageView中识别手势用以控制图片放大或缩小,具有一定的参考价值,分享给大家。
publicclassMatrixImageViewextendsImageView{ privateGestureDetectormGestureDetector; privateMatrixmMatrix=newMatrix(); privatefloatmImageWidth; privatefloatmImageHeight; privatefloatmScale; privateOnMovingListenermMoveListener; privateOnSingleTapListenermSingleTapListener; publicMatrixImageView(Contextcontext,AttributeSetattrs){ super(context,attrs); init(); } publicMatrixImageView(Contextcontext){ super(context,null); init(); } privatevoidinit(){ MatrixTouchListenerlistener=newMatrixTouchListener(); setOnTouchListener(listener); mGestureDetector=newGestureDetector(getContext(), newGestureListener(listener)); setBackgroundColor(Color.BLACK); setScaleType(ScaleType.FIT_CENTER); } publicvoidsetOnMovingListener(OnMovingListenerlistener){ mMoveListener=listener; } publicvoidsetOnSingleTapListener(OnSingleTapListeneronSingleTapListener){ this.mSingleTapListener=onSingleTapListener; } @Override publicvoidsetImageBitmap(Bitmapbm){ super.setImageBitmap(bm); if(getWidth()==0){ ViewTreeObservervto=getViewTreeObserver(); vto.addOnPreDrawListener(newViewTreeObserver.OnPreDrawListener(){ publicbooleanonPreDraw(){ initData(); MatrixImageView.this.getViewTreeObserver() .removeOnPreDrawListener(this); returntrue; } }); }else{ initData(); } } privatevoidinitData(){ mMatrix.set(getImageMatrix()); float[]values=newfloat[9]; mMatrix.getValues(values); mImageWidth=getWidth()/values[Matrix.MSCALE_X]; mImageHeight=(getHeight()-values[Matrix.MTRANS_Y]*2) /values[Matrix.MSCALE_Y]; mScale=values[Matrix.MSCALE_X]; } publicclassMatrixTouchListenerimplementsOnTouchListener{ privatestaticfinalintMODE_DRAG=1; privatestaticfinalintMODE_ZOOM=2; privatestaticfinalintMODE_UNABLE=3; privatestaticfinalfloatMAX_SCALE=6; privatestaticfinalfloatDOUBLE_CLICK_SACLE=2; privateintmMode=0; privatefloatmStartDis; privateMatrixmCurrentMatrix=newMatrix(); privatebooleanmLeftDragable; privatebooleanmRightDragable; privatebooleanmFirstMove=false; privatePointFmStartPoint=newPointF(); @Override publicbooleanonTouch(Viewv,MotionEventevent){ switch(event.getActionMasked()){ caseMotionEvent.ACTION_DOWN: mMode=MODE_DRAG; mStartPoint.set(event.getX(),event.getY()); isMatrixEnable(); startDrag(); checkDragable(); break; caseMotionEvent.ACTION_UP: caseMotionEvent.ACTION_CANCEL: reSetMatrix(); stopDrag(); break; caseMotionEvent.ACTION_MOVE: if(mMode==MODE_ZOOM){ setZoomMatrix(event); }elseif(mMode==MODE_DRAG){ setDragMatrix(event); }else{ stopDrag(); } break; caseMotionEvent.ACTION_POINTER_DOWN: if(mMode==MODE_UNABLE) returntrue; mMode=MODE_ZOOM; mStartDis=distance(event); break; caseMotionEvent.ACTION_POINTER_UP: break; default: break; } returnmGestureDetector.onTouchEvent(event); } privatevoidstartDrag(){ if(mMoveListener!=null) mMoveListener.startDrag(); } privatevoidstopDrag(){ if(mMoveListener!=null) mMoveListener.stopDrag(); } privatevoidcheckDragable(){ mLeftDragable=true; mRightDragable=true; mFirstMove=true; float[]values=newfloat[9]; getImageMatrix().getValues(values); if(values[Matrix.MTRANS_X]>=0) mRightDragable=false; if((mImageWidth)*values[Matrix.MSCALE_X] +values[Matrix.MTRANS_X]<=getWidth()){ mLeftDragable=false; } } publicvoidsetDragMatrix(MotionEventevent){ if(isZoomChanged()){ floatdx=event.getX()-mStartPoint.x; floatdy=event.getY()-mStartPoint.y; if(Math.sqrt(dx*dx+dy*dy)>10f){ mStartPoint.set(event.getX(),event.getY()); mCurrentMatrix.set(getImageMatrix()); float[]values=newfloat[9]; mCurrentMatrix.getValues(values); dy=checkDyBound(values,dy); dx=checkDxBound(values,dx,dy); mCurrentMatrix.postTranslate(dx,dy); setImageMatrix(mCurrentMatrix); } }else{ stopDrag(); } } privatebooleanisZoomChanged(){ float[]values=newfloat[9]; getImageMatrix().getValues(values); floatscale=values[Matrix.MSCALE_X]; returnscale!=mScale; } privatefloatcheckDyBound(float[]values,floatdy){ floatheight=getHeight(); if(mImageHeight*values[Matrix.MSCALE_Y]<height) return0; if(values[Matrix.MTRANS_Y]+dy>0) dy=-values[Matrix.MTRANS_Y]; elseif(values[Matrix.MTRANS_Y]+dy<-(mImageHeight *values[Matrix.MSCALE_Y]-height)) dy=-(mImageHeight*values[Matrix.MSCALE_Y]-height) -values[Matrix.MTRANS_Y]; returndy; } privatefloatcheckDxBound(float[]values,floatdx,floatdy){ floatwidth=getWidth(); if(!mLeftDragable&&dx<0){ if(Math.abs(dx)*0.4f>Math.abs(dy)&&mFirstMove){ stopDrag(); } return0; } if(!mRightDragable&&dx>0){ if(Math.abs(dx)*0.4f>Math.abs(dy)&&mFirstMove){ stopDrag(); } return0; } mLeftDragable=true; mRightDragable=true; if(mFirstMove) mFirstMove=false; if(mImageWidth*values[Matrix.MSCALE_X]<width){ return0; } if(values[Matrix.MTRANS_X]+dx>0){ dx=-values[Matrix.MTRANS_X]; }elseif(values[Matrix.MTRANS_X]+dx<-(mImageWidth *values[Matrix.MSCALE_X]-width)){ dx=-(mImageWidth*values[Matrix.MSCALE_X]-width) -values[Matrix.MTRANS_X]; } returndx; } privatevoidsetZoomMatrix(MotionEventevent){ if(event.getPointerCount()<2) return; floatendDis=distance(event); if(endDis>10f){ floatscale=endDis/mStartDis; mStartDis=endDis; mCurrentMatrix.set(getImageMatrix()); float[]values=newfloat[9]; mCurrentMatrix.getValues(values); scale=checkMaxScale(scale,values); PointFcenterF=getCenter(scale,values); mCurrentMatrix.postScale(scale,scale,centerF.x,centerF.y); setImageMatrix(mCurrentMatrix); } } privatePointFgetCenter(floatscale,float[]values){ if(scale*values[Matrix.MSCALE_X]<mScale||scale>=1){ returnnewPointF(getWidth()/2,getHeight()/2); } floatcx=getWidth()/2; floatcy=getHeight()/2; if((getWidth()/2-values[Matrix.MTRANS_X])*scale<getWidth()/2) cx=0; if((mImageWidth*values[Matrix.MSCALE_X]+values[Matrix.MTRANS_X]) *scale<getWidth()) cx=getWidth(); returnnewPointF(cx,cy); } privatefloatcheckMaxScale(floatscale,float[]values){ if(scale*values[Matrix.MSCALE_X]>MAX_SCALE) scale=MAX_SCALE/values[Matrix.MSCALE_X]; returnscale; } privatevoidreSetMatrix(){ if(checkRest()){ mCurrentMatrix.set(mMatrix); setImageMatrix(mCurrentMatrix); }else{ float[]values=newfloat[9]; getImageMatrix().getValues(values); floatheight=mImageHeight*values[Matrix.MSCALE_Y]; if(height<getHeight()){ floattopMargin=(getHeight()-height)/2; if(topMargin!=values[Matrix.MTRANS_Y]){ mCurrentMatrix.set(getImageMatrix()); mCurrentMatrix.postTranslate(0,topMargin -values[Matrix.MTRANS_Y]); setImageMatrix(mCurrentMatrix); } } } } privatebooleancheckRest(){ float[]values=newfloat[9]; getImageMatrix().getValues(values); floatscale=values[Matrix.MSCALE_X]; returnscale<mScale; } privatevoidisMatrixEnable(){ if(getScaleType()!=ScaleType.CENTER){ setScaleType(ScaleType.MATRIX); }else{ mMode=MODE_UNABLE; } } privatefloatdistance(MotionEventevent){ floatdx=event.getX(1)-event.getX(0); floatdy=event.getY(1)-event.getY(0); return(float)Math.sqrt(dx*dx+dy*dy); } publicvoidonDoubleClick(){ floatscale=isZoomChanged()?1:DOUBLE_CLICK_SACLE; mCurrentMatrix.set(mMatrix); mCurrentMatrix.postScale(scale,scale,getWidth()/2, getHeight()/2); setImageMatrix(mCurrentMatrix); } } privateclassGestureListenerextendsSimpleOnGestureListener{ privatefinalMatrixTouchListenermTouchListener; publicGestureListener(MatrixTouchListenerlistener){ this.mTouchListener=listener; } @Override publicbooleanonDown(MotionEvente){ returntrue; } @Override publicbooleanonDoubleTap(MotionEvente){ mTouchListener.onDoubleClick(); returntrue; } @Override publicbooleanonSingleTapUp(MotionEvente){ returnsuper.onSingleTapUp(e); } @Override publicvoidonLongPress(MotionEvente){ super.onLongPress(e); } @Override publicbooleanonScroll(MotionEvente1,MotionEvente2, floatdistanceX,floatdistanceY){ returnsuper.onScroll(e1,e2,distanceX,distanceY); } @Override publicbooleanonFling(MotionEvente1,MotionEvente2,floatvelocityX, floatvelocityY){ returnsuper.onFling(e1,e2,velocityX,velocityY); } @Override publicvoidonShowPress(MotionEvente){ super.onShowPress(e); } @Override publicbooleanonDoubleTapEvent(MotionEvente){ returnsuper.onDoubleTapEvent(e); } @Override publicbooleanonSingleTapConfirmed(MotionEvente){ if(mSingleTapListener!=null) mSingleTapListener.onSingleTap(e); returnsuper.onSingleTapConfirmed(e); } } publicinterfaceOnMovingListener{ publicvoidstartDrag(); publicvoidstopDrag(); } publicinterfaceOnSingleTapListener{ publicvoidonSingleTap(MotionEvente); } }
我对其中定义OnSingleTapListener接口的方法稍作了一些修改,为onSingleTap回调方法增加了MotionEvent类型的参数,来方便我们根据用户具体的事件内容作出对应的控制。
以上就是本文的全部内容,希望对大家学习Android软件编程有所帮助。