今天刚学了Gesture手势~就根据书中的例子跟着写了一个“根据手势来进行图片缩放”的例子来巩固知识。
大致步骤:
1. 创建 Activity并且实现OnGestureListener接口
2. 定义手势检测器实例等。
3. 实现Activity的onTouchEvent()方法,将触控事件交给手势检测器来处理
4. 给Activity的ImageView组件设置一张图片
5. 实现OnGestureListener的onFling(...)方法,根据手势的速度计算出缩放比,给Activity换上根据缩放后的图
注:例子来自《Android讲义》
代码:GestureZoom.java
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.widget.ImageView;
import cn.jamkong.helloworld.R;
/**
* 手势缩放图片
* @author JamKong
*
*/
public class GestureZoom extends Activity implements OnGestureListener {
GestureDetector detector;// 定义手势检测器实例
Bitmap bitmap;// 初始的图片资源
ImageView imgView;
int width, height;// 定义图片的宽、高
float currentScale = 1;// 记录当前缩放比
Matrix matrix;// 控制图片缩放的Matrix对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gesturezoom_activity);
// 创建手势检测器
detector = new GestureDetector(this, this);
matrix = new Matrix();
imgView = (ImageView) findViewById(R.id.gesturezoom_imgview);
// 获取被缩放的源图片
bitmap = BitmapFactory.decodeResource(this.getResources(),
R.drawable.school);
// 获得位图宽
width = bitmap.getWidth();
// 获得位图高
height = bitmap.getHeight();
// 设置ImageView初始化时显示的图片
imgView.setImageBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.school));//①
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 将该Activity的触控事件交给了GestureDetector处理
return detector.onTouchEvent(event);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
velocityX = velocityX > 4000 ? 4000 : velocityX;
velocityX = velocityX < -4000 ? -4000 : velocityX;
// 根据手势的速度来计算缩放比,如果velocityX>0,放大图片,否则缩小
currentScale += currentScale * velocityX / 4000.0f;
// 保证currentSale不会等于 0
currentScale = currentScale > 0.01 ? currentScale : 0.01f;
// 重置Matrix
matrix.reset();
// 缩放Matrix
matrix.setScale(currentScale, currentScale, 160, 200);
BitmapDrawable bitmapDrawable = (BitmapDrawable) imgView.getDrawable();
// 如果图片还未回收,先强制回收该图片
if (!bitmapDrawable.getBitmap().isRecycled()) {<span style="white-space:pre"> </span>//②
bitmapDrawable.getBitmap().recycle();
}
// 根据原始位图和Matrix创建新图片
Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0, 0, width, height,matrix, true);//③
// 显示新的位图
imgView.setImageBitmap(bitmap2);
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
}
gesturezoom_activity.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/gesturezoom_imgview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
结束~
在完成上面的例子之前(上面的代码是没问题)发生一个异常:“Canvas: trying to use a recycled bitmap android.graphics.Bitmap@4a132730”异常
该异常的意思就是:“你试图使用一个被回收的bitmap”。
后来发现是上面代码中标注着“①”处imgView.setImageBitmap()方法写成了如下形式:
imgView.setImageBitmap(bitmap);
bitmap在后来的“②”处我把它给回收了,但是在“③”处却又对它进行引用,所以就报出了上面的“你试图使用一个被回收的bitmap”异常。
那么解决这个问题也很简单,那就是给“①”或“③”创建一个Bitmap便可。
在这个例子中bitmap变量、width、height一开始就是准备给“③”使用的,因为“③”处每次手势进行操作的时候都会调用,所以如果在“③”处每次调用的时候都重新创建一个Bitmap的话,就有点消耗性能~而“①”处只是初始化的时候进行调用一次而已,所以让它直接创建一个便可~
-----唉、每次都写不出自己真实想表达的东西~今天便先这样吧~