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软件编程有所帮助。