生活中经常会用到图片放大和缩小,今天简单学习下.

思路:1.添加一个操作图片放大和缩小类;  2. 布局文件中引用这个自定义控件;  3. 主Activity一些修改. 代码如下:

增加图片操作类

 package com.example.imagezoomdemo;

 import java.util.Observable;
import java.util.Observer; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View; public class zoomimage extends View implements Observer { /** Paint object used when drawing bitmap. */
private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG); /** Rectangle used (and re-used) for cropping source image. */
private final Rect mRectSrc = new Rect(); /** Rectangle used (and re-used) for specifying drawing area on canvas. */
private final Rect mRectDst = new Rect(); /** Object holding aspect quotient */
private final AspectQuotient mAspectQuotient = new AspectQuotient(); /** The bitmap that we're zooming in, and drawing on the screen. */
private Bitmap mBitmap; /** State of the zoom. */
private ZoomState mState; private BasicZoomControl mZoomControl;
private BasicZoomListener mZoomListener; public zoomimage(Context context, AttributeSet attrs) {
super(context, attrs); mZoomControl = new BasicZoomControl(); mZoomListener = new BasicZoomListener();
mZoomListener.setZoomControl(mZoomControl); setZoomState(mZoomControl.getZoomState()); setOnTouchListener(mZoomListener); mZoomControl.setAspectQuotient(getAspectQuotient());
} public void zoomImage(float f, float x, float y) {
mZoomControl.zoom(f, x, y);
} public void setImage(Bitmap bitmap) {
mBitmap = bitmap; mAspectQuotient.updateAspectQuotient(getWidth(), getHeight(),
mBitmap.getWidth(), mBitmap.getHeight());
mAspectQuotient.notifyObservers(); invalidate();
} private void setZoomState(ZoomState state) {
if (mState != null) {
mState.deleteObserver(this);
} mState = state;
mState.addObserver(this); invalidate();
} private AspectQuotient getAspectQuotient() {
return mAspectQuotient;
} @Override
protected void onDraw(Canvas canvas) {
if (mBitmap != null && mState != null) { Log.d("ZoomImageView", "OnDraw"); final float aspectQuotient = mAspectQuotient.get(); final int viewWidth = getWidth();
final int viewHeight = getHeight();
final int bitmapWidth = mBitmap.getWidth();
final int bitmapHeight = mBitmap.getHeight(); Log.d("ZoomImageView", "viewWidth = " + viewWidth);
Log.d("ZoomImageView", "viewHeight = " + viewHeight);
Log.d("ZoomImageView", "bitmapWidth = " + bitmapWidth);
Log.d("ZoomImageView", "bitmapHeight = " + bitmapHeight); final float panX = mState.getPanX();
final float panY = mState.getPanY();
final float zoomX = mState.getZoomX(aspectQuotient) * viewWidth
/ bitmapWidth;
final float zoomY = mState.getZoomY(aspectQuotient) * viewHeight
/ bitmapHeight; // Setup source and destination rectangles
mRectSrc.left = (int) (panX * bitmapWidth - viewWidth / (zoomX * 2));
mRectSrc.top = (int) (panY * bitmapHeight - viewHeight
/ (zoomY * 2));
mRectSrc.right = (int) (mRectSrc.left + viewWidth / zoomX);
mRectSrc.bottom = (int) (mRectSrc.top + viewHeight / zoomY);
// mRectDst.left = getLeft();
mRectDst.left = 0;
mRectDst.top = 0;
// mRectDst.right = getRight();
mRectDst.right = getWidth();
mRectDst.bottom = getHeight(); // Adjust source rectangle so that it fits within the source image.
if (mRectSrc.left < 0) {
mRectDst.left += -mRectSrc.left * zoomX;
mRectSrc.left = 0;
}
if (mRectSrc.right > bitmapWidth) {
mRectDst.right -= (mRectSrc.right - bitmapWidth) * zoomX;
mRectSrc.right = bitmapWidth;
}
if (mRectSrc.top < 0) {
mRectDst.top += -mRectSrc.top * zoomY;
mRectSrc.top = 0;
}
if (mRectSrc.bottom > bitmapHeight) {
mRectDst.bottom -= (mRectSrc.bottom - bitmapHeight) * zoomY;
mRectSrc.bottom = bitmapHeight;
} mRectDst.left = 0;
mRectDst.top = 0;
mRectDst.right = viewWidth;
mRectDst.bottom = viewHeight; Log.d("ZoomImageView", "mRectSrc.top" + mRectSrc.top);
Log.d("ZoomImageView", "mRectSrc.bottom" + mRectSrc.bottom);
Log.d("ZoomImageView", "mRectSrc.left" + mRectSrc.left);
Log.d("ZoomImageView", "mRectSrc.right" + mRectSrc.right); Log.d("ZoomImageView", "mRectDst.top" + mRectDst.top);
Log.d("ZoomImageView", "mRectDst.bottom" + mRectDst.bottom);
Log.d("ZoomImageView", "mRectDst.left" + mRectDst.left);
Log.d("ZoomImageView", "mRectDst.right" + mRectDst.right); canvas.drawBitmap(mBitmap, mRectSrc, mRectDst, mPaint);
}
} @Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom); mAspectQuotient.updateAspectQuotient(right - left, bottom - top,
mBitmap.getWidth(), mBitmap.getHeight());
mAspectQuotient.notifyObservers();
} @Override
public void update(Observable observable, Object data) {
invalidate();
} private class BasicZoomListener implements View.OnTouchListener { /** Zoom control to manipulate */
private BasicZoomControl mZoomControl; private float mFirstX = -1;
private float mFirstY = -1;
private float mSecondX = -1;
private float mSecondY = -1; private int mOldCounts = 0; /**
* Sets the zoom control to manipulate
*
* @param control
* Zoom control
*/
public void setZoomControl(BasicZoomControl control) {
mZoomControl = control;
} public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mOldCounts = 1;
mFirstX = event.getX();
mFirstY = event.getY();
break;
case MotionEvent.ACTION_MOVE: {
float fFirstX = event.getX();
float fFirstY = event.getY(); int nCounts = event.getPointerCount(); if (1 == nCounts) {
mOldCounts = 1;
float dx = (fFirstX - mFirstX) / v.getWidth();
float dy = (fFirstY - mFirstY) / v.getHeight();
mZoomControl.pan(-dx, -dy);
} else if (1 == mOldCounts) {
mSecondX = event.getX(event.getPointerId(nCounts - 1));
mSecondY = event.getY(event.getPointerId(nCounts - 1));
mOldCounts = nCounts;
} else {
float fSecondX = event
.getX(event.getPointerId(nCounts - 1));
float fSecondY = event
.getY(event.getPointerId(nCounts - 1)); double nLengthOld = getLength(mFirstX, mFirstY, mSecondX,
mSecondY);
double nLengthNow = getLength(fFirstX, fFirstY, fSecondX,
fSecondY); float d = (float) ((nLengthNow - nLengthOld) / v.getWidth()); mZoomControl.zoom((float) Math.pow(20, d),
((fFirstX + fSecondX) / 2 / v.getWidth()),
((fFirstY + fSecondY) / 2 / v.getHeight())); mSecondX = fSecondX;
mSecondY = fSecondY;
}
mFirstX = fFirstX;
mFirstY = fFirstY; break;
} } return true;
} private double getLength(float x1, float y1, float x2, float y2) {
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
} private class BasicZoomControl implements Observer { /** Minimum zoom level limit */
private static final float MIN_ZOOM = 1; /** Maximum zoom level limit */
private static final float MAX_ZOOM = 16; /** Zoom state under control */
private final ZoomState mState = new ZoomState(); /** Object holding aspect quotient of view and content */
private AspectQuotient mAspectQuotient; /**
* Set reference object holding aspect quotient
*
* @param aspectQuotient
* Object holding aspect quotient
*/
public void setAspectQuotient(AspectQuotient aspectQuotient) {
if (mAspectQuotient != null) {
mAspectQuotient.deleteObserver(this);
} mAspectQuotient = aspectQuotient;
mAspectQuotient.addObserver(this);
} /**
* Get zoom state being controlled
*
* @return The zoom state
*/
public ZoomState getZoomState() {
return mState;
} /**
* Zoom
*
* @param f
* Factor of zoom to apply
* @param x
* X-coordinate of invariant position
* @param y
* Y-coordinate of invariant position
*/
public void zoom(float f, float x, float y) { // Log.d("Zoom", "zoom f = " + f); final float aspectQuotient = mAspectQuotient.get(); final float prevZoomX = mState.getZoomX(aspectQuotient);
final float prevZoomY = mState.getZoomY(aspectQuotient); mState.setZoom(mState.getZoom() * f);
limitZoom(); final float newZoomX = mState.getZoomX(aspectQuotient);
final float newZoomY = mState.getZoomY(aspectQuotient); // Pan to keep x and y coordinate invariant
mState.setPanX(mState.getPanX() + (x - .5f)
* (1f / prevZoomX - 1f / newZoomX));
mState.setPanY(mState.getPanY() + (y - .5f)
* (1f / prevZoomY - 1f / newZoomY)); limitPan(); mState.notifyObservers();
} /**
* Pan
*
* @param dx
* Amount to pan in x-dimension
* @param dy
* Amount to pan in y-dimension
*/
public void pan(float dx, float dy) {
final float aspectQuotient = mAspectQuotient.get(); mState.setPanX(mState.getPanX() + dx
/ mState.getZoomX(aspectQuotient));
mState.setPanY(mState.getPanY() + dy
/ mState.getZoomY(aspectQuotient)); limitPan(); mState.notifyObservers();
} /**
* Help function to figure out max delta of pan from center position.
*
* @param zoom
* Zoom value
* @return Max delta of pan
*/
private float getMaxPanDelta(float zoom) {
return Math.max(0f, .5f * ((zoom - 1) / zoom));
} /**
* Force zoom to stay within limits
*/
private void limitZoom() {
if (mState.getZoom() < MIN_ZOOM) {
mState.setZoom(MIN_ZOOM);
} else if (mState.getZoom() > MAX_ZOOM) {
mState.setZoom(MAX_ZOOM);
}
} /**
* Force pan to stay within limits
*/
private void limitPan() {
final float aspectQuotient = mAspectQuotient.get(); final float zoomX = mState.getZoomX(aspectQuotient);
final float zoomY = mState.getZoomY(aspectQuotient); final float panMinX = .5f - getMaxPanDelta(zoomX);
final float panMaxX = .5f + getMaxPanDelta(zoomX);
final float panMinY = .5f - getMaxPanDelta(zoomY);
final float panMaxY = .5f + getMaxPanDelta(zoomY); if (mState.getPanX() < panMinX) {
mState.setPanX(panMinX);
}
if (mState.getPanX() > panMaxX) {
mState.setPanX(panMaxX);
}
if (mState.getPanY() < panMinY) {
mState.setPanY(panMinY);
}
if (mState.getPanY() > panMaxY) {
mState.setPanY(panMaxY);
}
} // Observable interface implementation public void update(Observable observable, Object data) {
limitZoom();
limitPan();
}
} private class AspectQuotient extends Observable { /**
* Aspect quotient
*/
private float mAspectQuotient; // Public methods /**
* Gets aspect quotient
*
* @return The aspect quotient
*/
public float get() {
return mAspectQuotient;
} /**
* Updates and recalculates aspect quotient based on supplied view and
* content dimensions.
*
* @param viewWidth
* Width of view
* @param viewHeight
* Height of view
* @param contentWidth
* Width of content
* @param contentHeight
* Height of content
*/
public void updateAspectQuotient(float viewWidth, float viewHeight,
float contentWidth, float contentHeight) {
final float aspectQuotient = (contentWidth / contentHeight)
/ (viewWidth / viewHeight); if (aspectQuotient != mAspectQuotient) {
mAspectQuotient = aspectQuotient;
setChanged();
}
}
} private class ZoomState extends Observable {
/**
* Zoom level A value of 1.0 means the content fits the view.
*/
private float mZoom; /**
* Pan position x-coordinate X-coordinate of zoom window center
* position, relative to the width of the content.
*/
private float mPanX; /**
* Pan position y-coordinate Y-coordinate of zoom window center
* position, relative to the height of the content.
*/
private float mPanY; // Public methods /**
* Get current x-pan
*
* @return current x-pan
*/
public float getPanX() {
return mPanX;
} /**
* Get current y-pan
*
* @return Current y-pan
*/
public float getPanY() {
return mPanY;
} /**
* Get current zoom value
*
* @return Current zoom value
*/
public float getZoom() {
return mZoom;
} /**
* Help function for calculating current zoom value in x-dimension
*
* @param aspectQuotient
* (Aspect ratio content) / (Aspect ratio view)
* @return Current zoom value in x-dimension
*/
public float getZoomX(float aspectQuotient) {
return Math.min(mZoom, mZoom * aspectQuotient);
} /**
* Help function for calculating current zoom value in y-dimension
*
* @param aspectQuotient
* (Aspect ratio content) / (Aspect ratio view)
* @return Current zoom value in y-dimension
*/
public float getZoomY(float aspectQuotient) {
return Math.min(mZoom, mZoom / aspectQuotient);
} /**
* Set pan-x
*
* @param panX
* Pan-x value to set
*/
public void setPanX(float panX) {
if (panX != mPanX) {
mPanX = panX;
setChanged();
}
} /**
* Set pan-y
*
* @param panY
* Pan-y value to set
*/
public void setPanY(float panY) {
if (panY != mPanY) {
mPanY = panY;
setChanged();
}
} /**
* Set zoom
*
* @param zoom
* Zoom value to set
*/
public void setZoom(float zoom) {
if (zoom != mZoom) {
mZoom = zoom;
setChanged();
}
}
}
}

布局修改:

 <?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" > <!-- 引用自定义控件 -->
<com.example.imagezoomdemo.zoomimage
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</com.example.imagezoomdemo.zoomimage> </LinearLayout>

最后修改下Activity:

 package com.example.imagezoomdemo;

 import android.app.Activity;
import android.os.Bundle;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory; public class MainActivity extends Activity { private zoomimage zoomImg; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); zoomImg = (zoomimage) findViewById(R.id.image);
Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(),
R.drawable.aa);
zoomImg.setImage(bitmap);
} }

运行效果:

(1)原图:

(2) 放大:

(3) 缩小

41.Android之图片放大缩小学习的更多相关文章

  1. Android实现图片放大缩小

    package com.min.Test_Gallery; import android.app.Activity; import android.graphics.Bitmap; import an ...

  2. 自定义mousewheel事件,实现图片放大缩小功能实现

    本文是承接 上一篇的<自定义鼠标滚动事件>  的基础上实现的,建议大家先看一下上一篇的mousewheel的实现,再浏览下文: 上篇中我们介绍到: $element.mousewheel( ...

  3. imageView图片放大缩小及旋转

    imageView图片放大缩小及旋转 一.简介 二.方法 1)设置图片放大缩小效果 第一步:将<ImageView>标签中的android:scaleType设置为"fitCen ...

  4. 鼠标滚轮图片放大缩小功能,使用layer弹框后不起作用

    今天在项目中遇到的一个问题:点击按钮使用layer弹框弹出一张图片,需要加一个鼠标滚轮放大缩小,图片也跟着放大缩小的功能.于是在网上找了一个demo. DEMO: <!DOCTYPE html ...

  5. javascript仿新浪微博图片放大缩小及旋转效果

    javascript仿新浪微博图片放大缩小及旋转效果 经常看到新浪微博里有图片放大缩小旋转效果,感觉效果还不错,所以就想试着做一个类似的demo出来,至于旋转对于IE可以用滤镜来解决,标准的浏览器可以 ...

  6. hammer使用: 代码:捏合、捏开、图片放大 的一个手机图片“放大缩小可拖动”的小效果

    hammer.js 的使用. (手机手势插件) 捏合.捏开.图片放大 的一个手机图片“放大缩小可拖动”的小效果. 相关js 到 http://www.bootcdn.cn/  查找和下载. hamme ...

  7. vue项目 一行js代码搞定点击图片放大缩小

    一行js代码搞定xue项目需要点击图片放大缩小,其实主要用的是用到了vue:class的动态切换,内容比较简单.一开始我把维护的需求想得太复杂了,和测试小姐姐聊了一下才反应过来. 两个月不到跟了四个项 ...

  8. wpf下的图片放大缩小

    WPF下实现图片的放大缩小移动   在windows 7里面有自带的图片查看器,这个软件可以打开一张图片然后以鼠标在图片中的焦点为原点来进行缩放,并且放大后可以随意拖动.下面我们在WPF中实现这个功能 ...

  9. Android多点触摸放大缩小图片

    1.Activity package com.fit.touchimage; import android.app.Activity; import android.graphics.Bitmap; ...

随机推荐

  1. Codeforces Round #267 Div2 C George and Job --DP

    题意:把长度为n的序列分成k个m长的连续小序列,这些连续小序列的和最大是多少. 解法:显然DP. 定义: dp[i][j] 为前 i 个元素分成j个m端,且 i 是第j个的末尾的最大和. 那么有: d ...

  2. java 21 - 3 字符输入流

    所谓的输入流,就是读取文件中的数据 同样的,字符输入流InputStreamReader 4个构造方法,不过2个比较常用: 构造方法: A:InputStreamReader(InputStream ...

  3. Android SQLite (二) 基本用法

    在Android开发中SQLite起着很重要的作用,网上SQLite的教程有很多很多,不过那些教程大多数都讲得不是很全面.本人总结了一些SQLite的常用的方法,借着论坛的大赛,跟大家分享分享的. 一 ...

  4. PHP安装memcache扩展接口步骤

    1.将php_memcache.dll文件保存到php的应用程序扩展ext目录中 2.在php.ini配置文件添加扩展的位置,加入一行extension=php_memcache.dll 3.重新启动 ...

  5. S2--《深入.NET平台和C#编程》

    第一章    深入.NET框架 1.1  Microsoft  .NET框架概述 .NET框架的优势 * 提供了一个面向对象的编程环境,完全支持面向对象编程,.NET 框架提高了软件的可复用性,可扩展 ...

  6. 022医疗项目-模块二:药品目录的导入导出-对XSSF导出excel类进行封装

    资源全部来源于传智播客. 好的架构师写的程序,就算给刚入门的新手看,新手一看就知道怎么去用.所以我们要对XSSF导出excel类进行封装.这是架构师的工作,但我们也要知道. 我们写一个封装类: 这个类 ...

  7. MySQL基础 - 编码设置

    刚开始工作的时候,在工作中遇到的与数据库相关的问题,多半跟编码有关,总结一下数据库编码的设置. 字符集 查看数据库支持的字符集: mysql> SHOW CHARACTER SET; 从图中可以 ...

  8. Oracle数据库,数字强制显示2位小数(转)

    Oracle数据库,数字强制显示2位小数 在银行.财务等对数字要求敏感的系统中,数字的显示一般有着严格的要求.今遇到一个需求,如题,要求将数字以两位小数的格式显示,如果没有小数,则强制显示为0.例如: ...

  9. VBS操作Excel常见方法

    VBS操作Excel常见方法 作者: 字体:[增加 减小] 类型:转载 时间:2009-11-13我要评论 VBS控制Excel常见方法,需要的朋友可以参考下. dim oExcel,oWb,oShe ...

  10. 用CNTK搞深度学习 (二) 训练基于RNN的自然语言模型 ( language model )

    前一篇文章  用 CNTK 搞深度学习 (一) 入门    介绍了用CNTK构建简单前向神经网络的例子.现在假设读者已经懂得了使用CNTK的基本方法.现在我们做一个稍微复杂一点,也是自然语言挖掘中很火 ...