1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Android中实现Bitmap在自定义View中的放大与拖动

Android中实现Bitmap在自定义View中的放大与拖动

时间:2022-09-16 11:14:42

相关推荐

Android中实现Bitmap在自定义View中的放大与拖动

一基本实现思路:

基于View类实现自定义View –MyImageView类。在使用View的Activity类中完成OnTouchListener接口,实现对MotionEvent事件的监听与处理,常见的MotionEvent事件如下:

ACTION_DOWN事件,记录平移开始点

ACTION_UP事件,结束平移事件处理

ACTION_MOVE事件,记录平移点,计算与开始点距离,实现Bitmap平移,在多点触控时候,计算两点之间的距离,实现图像放大

ACTION_POINTER_DOWN事件,计算两点之间的距离,作为初始距离,实现图像手势放大时候使用。

ACTION_POINTER_UP事件,结束两点触控放大图像处理

放大与拖动

基于单点触控实现Bitmap对象在View上的拖动、并且检测View的边缘,防止拖动过界。基于两个点触控实现Bitmap对象在View上的放大、并且检测放大倍数。基于Matrix对象实现对Bitmap在View上放大与平移变换,Matrix对象是android中实现图像几何变换的矩阵,支持平移、放大、缩小、错切、旋转等常见操作。

Bitmap对象在View中的更新与显示

通过重载onDraw方法,使用canvas实现绘制Bitmap对象、通过view.invalidate()方法实现View的刷新。

MyImageView类的重要方法说明:

initParameters()初始化所有需要用到的参数

setStartPoint()设置图像平移的开始点坐标

setMovePoint()设置图像平移的移动点坐标,然后集合开始点位置,计算它们之间的距离,从而得到Bitmap对象需要平移的两个参数值sx、sy。其中还包括保证图像不会越过View边界的检查代码。

savePreviousResult()保存当前的平移数据,下次可以继续在次基础上平移Bitmap对象。

zoomIn()根据两个点之间的欧几里德距离,通过初始距离比较,得到放大比例,实现Bitmap在View对象上的放大

Matrix中关于放大与平移的API

Matrix.postScale方法与Matrix.postTranslate方法可以不改变Bitmap对象本身实现平移与放大。

二:代码实现

自定义View类使用xml布局如下:

[html]view plaincopy<RelativeLayoutxmlns:android="/apk/res/android" xmlns:tools="/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <com.example.matrixdemo.MyImageView android:id="@+id/myView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="@string/hello_world"/> </RelativeLayout> 自定义View实现代码如下:[java]view plaincopypackagecom.example.matrixdemo; importandroid.content.Context; importandroid.graphics.Bitmap; importandroid.graphics.Canvas; importandroid.graphics.Color; importandroid.graphics.Matrix; importandroid.graphics.Paint; importandroid.graphics.Paint.Style; importandroid.graphics.Point; importandroid.graphics.Rect; importandroid.util.AttributeSet; importandroid.view.View; publicclassMyImageViewextendsView{ privatePaintmPaint; privateBitmapbitmap; privateMatrixmatrix; //平移开始点与移动点 privatePointstartPoint; privatePointmovePoint; privatefloatinitDistance; //记录当前平移距离 privateintsx; privateintsy; //保存平移状态 privateintoldsx; privateintoldsy; //scalerate privatefloatwidthRate; privatefloatheightRate; publicMyImageView(Contextcontext){ super(context); } publicMyImageView(Contextcontext,AttributeSetattrs){ super(context,attrs); } publicvoidsetBitmap(Bitmapbitmap){ this.bitmap=bitmap; } privatevoidinitParameters(){ //初始化画笔 mPaint=newPaint(); mPaint.setColor(Color.BLACK); matrix=newMatrix(); if(bitmap!=null) { floatiw=bitmap.getWidth(); floatih=bitmap.getHeight(); floatwidth=this.getWidth(); floatheight=this.getHeight(); //初始放缩比率 widthRate=width/iw; heightRate=height/ih; } sx=0; sy=0; oldsx=0; oldsy=0; } publicvoidsetStartPoint(PointstartPoint){ this.startPoint=startPoint; } publicvoidsetInitDistance(floatinitDistance){ this.initDistance=initDistance; } publicvoidzoomIn(floatdistance) { floatrate=distance/this.initDistance; floatiw=bitmap.getWidth(); floatih=bitmap.getHeight(); floatwidth=this.getWidth(); floatheight=this.getHeight(); //getscalerate widthRate=(width/iw)*rate; heightRate=(height/ih)*rate; //makeitsameasviewsize floatiwr=(width/iw); floatihr=(height/ih); if(iwr>=widthRate) { widthRate=(width/iw); } if(ihr>=heightRate) { heightRate=(height/ih); } //gotocenter oldsx=(int)((width-widthRate*iw)/2); oldsy=(int)((height-heightRate*ih)/2); } publicvoidsetMovePoint(PointmovePoint){ this.movePoint=movePoint; sx=this.movePoint.x-this.startPoint.x; sy=this.movePoint.y-this.startPoint.y; floatiw=bitmap.getWidth(); floatih=bitmap.getHeight(); //检测边缘 intdeltax=(int)((widthRate*iw)-this.getWidth()); intdeltay=(int)((heightRate*ih)-this.getHeight()); if((sx+this.oldsx)>=0) { this.oldsx=0; sx=0; } elseif((sx+this.oldsx)<=-deltax) { this.oldsx=-deltax; sx=0; } if((sy+this.oldsy)>=0) { this.oldsy=0; this.sy=0; } elseif((sy+this.oldsy)<=-deltay) { this.oldsy=-deltay; this.sy=0; } floatwidth=this.getWidth(); //初始放缩比率 floatiwr=width/iw; if(iwr==widthRate) { sx=0; sy=0; oldsx=0; oldsy=0; } } publicvoidsavePreviousResult() { this.oldsx=this.sx+this.oldsx; this.oldsy=this.sy+this.oldsy; //zero sx=0; sy=0; } @Override protectedvoidonDraw(Canvascanvas){ if(matrix==null) { initParameters(); } if(bitmap!=null) { matrix.reset(); matrix.postScale(widthRate,heightRate); matrix.postTranslate(oldsx+sx,oldsy+sy); canvas.drawBitmap(bitmap,matrix,mPaint); } else { //fillrect Rectrect=newRect(0,0,getWidth(),getHeight()); mPaint.setAntiAlias(true); mPaint.setColor(Color.BLACK); mPaint.setStyle(Style.FILL_AND_STROKE); canvas.drawRect(rect,mPaint); } } } Activity类中实现对View的OnTouchListener监听与MotionEvent事件处理的代码如下:[java]view plaincopypackagecom.example.matrixdemo; importandroid.app.Activity; importandroid.graphics.Bitmap; importandroid.graphics.BitmapFactory; importandroid.graphics.Point; importandroid.os.Bundle; importandroid.util.Log; importandroid.view.Menu; importandroid.view.MotionEvent; importandroid.view.View; importandroid.view.View.OnTouchListener; publicclassMainActivityextendsActivityimplementsOnTouchListener{ publicstaticfinalintSCALE_MODE=4; publicstaticfinalintTRANSLATION_MODE=2; publicstaticfinalintNULL_MODE=1; privateMyImageViewmyView; privateintmode; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startMyImageView(); } privatevoidstartMyImageView(){ myView=(MyImageView)this.findViewById(R.id.myView); Bitmapbitmap=BitmapFactory.decodeResource(this.getResources(), R.drawable.flower_001); myView.setBitmap(bitmap); myView.setOnTouchListener(this); myView.invalidate(); } @Override publicbooleanonCreateOptionsMenu(Menumenu){ getMenuInflater().inflate(R.menu.main,menu); returntrue; } @Override publicbooleanonTouch(Viewview,MotionEventevent){ Log.i("touchevent","touchx="+event.getX()); switch(MotionEvent.ACTION_MASK&event.getAction()) { caseMotionEvent.ACTION_DOWN: mode=TRANSLATION_MODE; myView.setStartPoint(newPoint((int)event.getX(),(int)event.getY())); break; caseMotionEvent.ACTION_POINTER_UP: caseMotionEvent.ACTION_OUTSIDE: caseMotionEvent.ACTION_UP: mode=NULL_MODE; myView.savePreviousResult(); break; caseMotionEvent.ACTION_POINTER_DOWN: mode=SCALE_MODE; myView.setInitDistance(calculateDistance(event)); break; caseMotionEvent.ACTION_MOVE: if(mode==SCALE_MODE) { floatdis=calculateDistance(event); myView.zoomIn(dis); } elseif(mode==TRANSLATION_MODE) { myView.setMovePoint(newPoint((int)event.getX(),(int)event.getY())); } else { Log.i("unknowmodetag","donothing......"); } break; } myView.invalidate(); returntrue; } privatefloatcalculateDistance(MotionEventevent){ floatdx=event.getX(0)-event.getX(1); floatdy=event.getY(0)-event.getY(1); floatdistance=(float)Math.sqrt(dx*dx+dy*dy); returndistance; } } 三:运行效果如下

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。