认识事物都遵循由简入繁的顺序,下面我们想实现一个控件或者一个布局的缩放,先从简单的例子开始吧,我们就以缩放图片做入门。
效果图:
一、要求
利用ScaleGestureDetector这个类实现图片缩放。
二、代码
public class MainActivity extends ActionBarActivity {
private SurfaceView mSurfaceView = null;
private SurfaceHolder mSurfaceHolder = null;
private ScaleGestureDetector mScaleGestureDetector = null;
private Bitmap mBitmap = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) this.findViewById(R.id.surfaceview);
mSurfaceHolder = mSurfaceView.getHolder();
mScaleGestureDetector = new ScaleGestureDetector(this,
new ScaleGestureListener());
mSurfaceView.post(new Runnable() {
@Override
public void run() {
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.guanmjie);
// 锁定整个SurfaceView
Canvas mCanvas = mSurfaceHolder.lockCanvas();
// 画图
mCanvas.drawBitmap(mBitmap, 0f, 0f, null);
// 绘制完成,提交修改
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
// 重新锁一次
mSurfaceHolder.lockCanvas(new Rect(0, 0, 0, 0));
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 返回给ScaleGestureDetector来处理
return mScaleGestureDetector.onTouchEvent(event);
}
public class ScaleGestureListener implements
ScaleGestureDetector.OnScaleGestureListener {
private float scale;
private float preScale = 1;// 默认前一次缩放比例为1
@Override
public boolean onScale(ScaleGestureDetector detector) {
// TODO Auto-generated method stub
Matrix mMatrix = new Matrix();
float previousSpan = detector.getPreviousSpan();
float currentSpan = detector.getCurrentSpan();
if (currentSpan < previousSpan) {
// 缩小
// scale = preScale-detector.getScaleFactor()/3;
scale = preScale - (previousSpan - currentSpan) / 1000;
} else {
// 放大
// scale = preScale+detector.getScaleFactor()/3;
scale = preScale + (currentSpan - previousSpan) / 1000;
}
mMatrix.setScale(scale, scale);
// 锁定整个SurfaceView
Canvas mCanvas = mSurfaceHolder.lockCanvas();
// 清屏
mCanvas.drawColor(Color.BLACK);
// 画缩放后的图
mCanvas.drawBitmap(mBitmap, mMatrix, null);
// 绘制完成,提交修改
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
// 重新锁一次
mSurfaceHolder.lockCanvas(new Rect(0, 0, 0, 0));
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
return false;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
// 一定要返回true才会进入onScale()这个函数
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
preScale = scale;//记住本次的缩放后的图片比例
}
}
}
activity_main.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<SurfaceView
android:id="@+id/surfaceview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
总结:本例利用了matrix和canvas,对图片进行缩放;本demo还可以改造,不需matrix和canvas,在获得scale值之后对其他控件等缩放都可以!功能强大!而且简单明了,完全无bug!
下面是一个功能强大的改造的例子:
可以实现以下需求:
1.两个手指进行缩放布局
2.所有子控件也随着缩放,
3.子控件该有的功能不能丢失(像button有可被点击的功能,缩放后不能丢失该功能)
要实现这几点功能,可以参考:
缩放系列(二):所有子控件也随着缩放、手势缩放、多点触控layout
源码地址: https://github.com/Jszgw/BitmapScale