Android自定义View实现可拖拽缩放的矩形框
本文实例为大家分享了Android自定义View拖拽缩放矩形框的具体代码,供大家参考,具体内容如下
在开发项目中,需要一个矩形框来实现截屏功能,并且还需要可以任意拖拽和缩放,这就需要自定义View来实现了,具体功能如下:
1.自定义View
packagecom.xinrui.screenshot.view; importandroid.content.Context; importandroid.graphics.Canvas; importandroid.graphics.Color; importandroid.graphics.Paint; importandroid.graphics.RectF; importandroid.support.annotation.Nullable; importandroid.util.AttributeSet; importandroid.util.Log; importandroid.util.TypedValue; importandroid.view.MotionEvent; importandroid.view.View; publicclassCropRectViewextendsView{ //绘制损害框和损害名称 privatePaintmPaint; privateRectFmRectF; //边缘字体 //privateBorderedTextmBorderedText; //标题或名字 privateStringmTitle; //概率 privatefloatmConfidence; //矩形框corner的角度:直角、圆角 privateintmCornerAngle; //直角默认 publicstaticfinalintRIGHT_CORNER=0; //圆角 publicstaticfinalintROUND_CORNER=1; //RemoveRect privateintMODE; privatestaticfinalintMODE_OUTSIDE=0x000000aa;/*170*/ privatestaticfinalintMODE_INSIDE=0x000000bb;/*187*/ privatestaticfinalintMODE_POINT=0X000000cc;/*204*/ privatestaticfinalintMODE_ILLEGAL=0X000000dd;/*221*/ privatefloatstartX;/*startXlocation*/ privatefloatstartY;/*startYlocation*/ privatefloatendX;/*endXlocation*/ privatefloatendY;/*endYlocation*/ privatefloatcurrentX;/*Xcoordinatevalueswhilefingerpress*/ privatefloatcurrentY;/*Ycoordinatevalueswhilefingerpress*/ privatefloatmemoryX;/*thelasttimethecoordinatevaluesofX*/ privatefloatmemoryY;/*thelasttimethecoordinatevaluesofY*/ privatefloatmCoverWidth;/*widthofselectionbox*/ privatefloatmCoverHeight;/*heightofselectionbox*/ privatestaticfinalintACCURACY=100;/*touchaccuracy*/ privateintpointPosition;/*vertexofarectangle*/ privatestaticfinalfloatminWidth=100.0f;/*theminimumwidthoftherectangle*/ privatestaticfinalfloatminHeight=200.0f;/*theminimumheightoftherectangle*/ privateonLocationListenermLocationListener;/*listentotheRect*/ privatestaticfinalfloatEDGE_WIDTH=1.8f; publicMoveAndCropRectView(Contextcontext){ this(context,null); } publicMoveAndCropRectView(Contextcontext,@NullableAttributeSetattrs){ this(context,attrs,0); } publicMoveAndCropRectView(Contextcontext,@NullableAttributeSetattrs,intdefStyleAttr){ super(context,attrs,defStyleAttr); initDatas(context); } privatevoidinitDatas(Contextcontext){ mPaint=newPaint(); mRectF=newRectF(); //画笔设置空心 mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.WHITE); mPaint.setStrokeWidth(2); mPaint.setAntiAlias(true); //floattextSizePx=TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, //18.0f,context.getResources().getDisplayMetrics()); //mBorderedText=newBorderedText(textSizePx); currentX=0; currentY=0; } privatebooleanfirstDraw=true; @Override protectedvoidonDraw(Canvascanvas){ super.onDraw(canvas); //switch(mCornerAngle){ //caseRIGHT_CORNER://绘制损害框(直角矩形框) //drawRect(canvas); //break; //caseROUND_CORNER://绘制损害框(圆角矩形框) //drawRoundRect(canvas); //break; //} if(firstDraw){ firstDraw=false; startX=mRectF.left; startY=mRectF.top; endX=mRectF.right; endY=mRectF.bottom; mCoverWidth=mRectF.width(); mCoverHeight=mRectF.height(); } if(mLocationListener!=null){ mLocationListener.locationRect(startX,startY,endX,endY); } //LogUtils.d("onDraw--startX:"+startX); canvas.drawLine(startX-EDGE_WIDTH,startY-EDGE_WIDTH, endX+EDGE_WIDTH,startY-EDGE_WIDTH,mPaint);/*top上边框-*/ canvas.drawLine(startX-EDGE_WIDTH,endY+EDGE_WIDTH, endX+EDGE_WIDTH,endY+EDGE_WIDTH,mPaint);/*bottom-*/ canvas.drawLine(startX-EDGE_WIDTH,startY-EDGE_WIDTH, startX-EDGE_WIDTH,endY+EDGE_WIDTH,mPaint);/*left|*/ canvas.drawLine(endX+EDGE_WIDTH,startY-EDGE_WIDTH, endX+EDGE_WIDTH,endY+EDGE_WIDTH,mPaint);/*right|*/ //绘制名称和概率 //finalStringlabelString= //!TextUtils.isEmpty(mTitle) //?String.format("%s%.2f",mTitle,(100*mConfidence)) //:String.format("%.2f",(100*mConfidence)); // ////在直角矩形框上写字 //mBorderedText.drawText(canvas, //startX, //startY,labelString+"%", //mPaint); } @SuppressWarnings("NullableProblems") @Override publicbooleanonTouchEvent(MotionEventevent){ switch(event.getAction()){ caseMotionEvent.ACTION_DOWN: memoryX=event.getX(); memoryY=event.getY(); checkMode(memoryX,memoryY); break; caseMotionEvent.ACTION_MOVE:{ currentX=event.getX(); currentY=event.getY(); switch(MODE){ caseMODE_ILLEGAL: recoverFromIllegal(currentX,currentY); postInvalidate(); break; caseMODE_OUTSIDE: //donothing; break; caseMODE_INSIDE://拖动 moveByTouch(currentX,currentY); postInvalidate(); break; default: /*MODE_POINT*/ moveByPoint(currentX,currentY); postInvalidate(); break; } } break; caseMotionEvent.ACTION_UP: //mPaint.setColor(getContext().getResources().getColor(R.color.orange)); postInvalidate(); break; default: break; } returntrue; } /*点击顶点附近时的缩放处理*/ @SuppressWarnings("SuspiciousNameCombination") privatevoidmoveByPoint(floatbx,floatby){ //LogUtils.d("moveByPoint"); switch(pointPosition){ case0:/*left-up*/ mCoverWidth=Math.abs(endX-bx); mCoverHeight=Math.abs(endY-by); //noinspectionSuspiciousNameCombination if(!checkLegalRect(mCoverWidth,mCoverHeight)){ MODE=MODE_ILLEGAL; }else{ refreshLocation(bx,by,endX,endY); } break; case1:/*right-up*/ mCoverWidth=Math.abs(bx-startX); mCoverHeight=Math.abs(endY-by); if(!checkLegalRect(mCoverWidth,mCoverHeight)){ MODE=MODE_ILLEGAL; }else{ refreshLocation(startX,by,bx,endY); } break; case2:/*left-down*/ mCoverWidth=Math.abs(endX-bx); mCoverHeight=Math.abs(by-startY); if(!checkLegalRect(mCoverWidth,mCoverHeight)){ MODE=MODE_ILLEGAL; }else{ refreshLocation(bx,startY,endX,by); } break; case3:/*right-down*/ mCoverWidth=Math.abs(bx-startX); mCoverHeight=Math.abs(by-startY); if(!checkLegalRect(mCoverWidth,mCoverHeight)){ MODE=MODE_ILLEGAL; }else{ refreshLocation(startX,startY,bx,by); } break; default: break; } } /*刷新矩形的坐标*/ privatevoidrefreshLocation(floatisx,floatisy,floatiex,floatiey){ this.startX=isx; this.startY=isy; this.endX=iex; this.endY=iey; mCoverWidth=endX-startX; mCoverHeight=endY-startY; } /*检测矩形是否达到最小值*/ privatebooleancheckLegalRect(floatcHeight,floatcWidth){ return(cHeight>minHeight&&cWidth>minWidth); } /*从非法状态恢复,这里处理的是达到最小值后能拉伸放大*/ privatevoidrecoverFromIllegal(floatrx,floatry){ if((rx>startX&&ry>startY)&&(rxstartX&&cx startY&&cy =1920){ endX=1920; startX=endX-mCoverWidth; } if(endY>=1080){ endY=1080; startY=endY-mCoverHeight; } memoryX=mx; memoryY=my; } /*判断点(inX,inY)是否靠近矩形的4个顶点*/ privateintnearbyPoint(floatfloatX,floatfloatY){ if((Math.abs(startX-floatX)<=ACCURACY&&(Math.abs(floatY-startY)<=ACCURACY))){/*left-upangle*/ pointPosition=0; return0; } if((Math.abs(endX-floatX)<=ACCURACY&&(Math.abs(floatY-startY)<=ACCURACY))){/*right-upangle*/ pointPosition=1; return1; } if((Math.abs(startX-floatX)<=ACCURACY&&(Math.abs(floatY-endY)<=ACCURACY))){/*left-downangle*/ pointPosition=2; return2; } if((Math.abs(endX-floatX)<=ACCURACY&&(Math.abs(floatY-endY)<=ACCURACY))){/*right-downangle*/ pointPosition=3; return3; } pointPosition=100; return100; } //设置矩形框 publicvoidsetRectF(RectFrectf){ this.mRectF=rectf; } publicvoidsetTitle(Stringtitle){ mTitle=title; } publicvoidsetConfidence(floatconfidence){ mConfidence=confidence; } publicvoidsetCornerAngle(intcornerAngle){ this.mCornerAngle=cornerAngle; } //绘制损害框(直角矩形框) privatevoiddrawRect(Canvascanvas){ canvas.drawRect(mRectF,mPaint); //绘制名称和概率 //finalStringlabelString= //!TextUtils.isEmpty(mTitle) //?String.format("%s%.2f",mTitle,(100*mConfidence)) //:String.format("%.2f",(100*mConfidence)); //在直角矩形框上写字 //mBorderedText.drawText(canvas, //mRectF.left, //mRectF.top,labelString+"%", //mPaint); } //绘制损害框(圆角矩形框) privatevoiddrawRoundRect(Canvascanvas){ floatcornerSize=Math.min(mRectF.width(),mRectF.height())/8.0f; canvas.drawRoundRect(mRectF,cornerSize,cornerSize,mPaint); //绘制名称和概率 //finalStringlabelString= //!TextUtils.isEmpty(mTitle) //?String.format("%s%.2f",mTitle,(100*mConfidence)) //:String.format("%.2f",(100*mConfidence)); //在圆角矩形框上写字 //mBorderedText.drawText(canvas, //mRectF.left+cornerSize, //mRectF.top,labelString+"%", //mPaint); } publicvoidsetLocationListener(onLocationListenermLocationListener){ this.mLocationListener=mLocationListener; } publicinterfaceonLocationListener{ voidlocationRect(floatstartX,floatstartY,floatendX,floatendY); } }
2.Activity里的应用
packagecom.xinrui.screenshot; importandroid.app.Activity; importandroid.graphics.RectF; importandroid.os.Bundle; importandroid.util.Log; importandroid.widget.RelativeLayout; importcom.xinrui.screenshot.view.CropRectView; publicclassMainActivityextendsActivity{ privateRelativeLayoutmain_area; CropRectViewcropRectView; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initview(); } privatevoidinitview(){ main_area=(RelativeLayout)findViewById(R.id.main_area); cropRectView=(CropRectView)findViewById(R.id.main_img); RectFrectF=newRectF(660,240,1260,840); cropRectView.setRectF(rectF); cropRectView.setLocationListener(newCropRectView.onLocationListener(){ @Override publicvoidlocationRect(floatstartX,floatstartY,floatendX,floatendY){ Log.e("MainActivity","[startX:("+startX+")--startY:("+startY+")--endX:("+endX+")--endY:("+endY+")]"); } }); } }
3.activity_main.xml
大功告成。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。