首页 > 代码库 > bitmap使用全程记录
bitmap使用全程记录
今天做了一个简单的应用,大致是向服务器请求一张图片,然后点击跳转到另外一个界面上使得这张图片可以自由伸缩。
首先是在ActivityA中请求图片,使用Ajax请求,代码如下所示。
// 2014.5.12晚 AQuery aq = new AQuery(RepairInfoDetail.this); mViewPhotoText = (TextView) findViewById(R.id.photoText); mViewPhotoText.setText("现场照片:拍摄于" + map.get("reportTime").toString().substring(0, 10)); aq.id(R.id.inspectionPhoto).image(map.get("inspectionPhoto").toString(), true, true, 200, 0);
而后手机上会显示一个小图片,给用户看的时候反馈这个图片有点小,应该有放大功能,根据需求最终决定跳转到另一个ActivityB中。这里问题出来了:在新的界面上再次请求图片,会导致图片的重复下载,加载过程还特别慢;如果可以将bitmap这个对象直接通过bundle存储、传到另一个界面,就省了之前的问题。
之前用的方法并不是AQuery,而是流和多线程操作的方法(上一篇文章应该写过),因此bitmap可以轻松获得。但在传递bitmap的时候,发现Activity无论如何传递,都很容易报OOP的错误(Out of Memory,内存溢出),图片文件过大,即便整成流还是整成全局变量都容易出错。因此Activity传递bitmap对象这种思路被彻底否定。
通过查Android文档,AQuery已经给好了很完整有效的缓存机制,大致意思如下:如果某次请求服务器已经根据某url请求了对应的图片资源,那么在下次请求这个图片资源时,该url会自动被AQuery识别并从缓存中读取,而不是再次请求服务器。这样就不存在图片重复下载、加载过程慢的问题了。
OK,这样Activity跳转过程结束,新的Activity也同样通过AQuery得到图片并加载到了layout中的imageview控件中。问题是,如何获得bitmap对象以进一步适用图片伸缩等操作的代码?
从AQuery那段代码可以看到aq方法直接将url对应的图片文件加载到了R.id.inspectionPhoto对应的控件当中,并没有显示出现bitmap对象。找了很多种方法,最后发现aq这个方法竟然有callback!而callback恰好是bitmapAjaxCallback!好吧,复写callback函数,就可以对bitmap做任何事情了。
两段完整代码如下:
package ouc.sei.civil_defend.ui; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import com.androidquery.AQuery; import ouc.sei.civil_defend.R; import android.app.Activity; import android.app.DownloadManager.Query; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; /** * 某条维修信息细节查看 * * @author GloryZSG * */ public class RepairInfoDetail extends Activity { private TextView repairname; private TextView repairtype; private TextView repairlevel; private TextView repairtime; private TextView districtName; private ImageView mImgViewPhoto; private Bitmap mybitmap; private TextView mViewAppearance; private TextView mViewElectricity; private TextView mViewSound; private TextView mViewWorkState; private TextView mViewPhotoText; private Handler handler; private Bitmap bm; private HashMap<String,Object> map; //---------------------- private Button imageButton; @SuppressWarnings("unchecked") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.repairinfodetail); handler = new Handler(); map = new HashMap<String,Object>(); try { Bundle bundle = getIntent().getExtras(); Serializable data = http://www.mamicode.com/bundle.getSerializable("repairinfo");>以上这段中屏蔽的关于多线程和流请求的代码没有删,这只是另外一种方法。
以下是另外一个Activity。package ouc.sei.civil_defend.ui; import com.androidquery.AQuery; import com.androidquery.callback.BitmapAjaxCallback; import com.androidquery.callback.AjaxStatus; import ouc.sei.civil_defend.R; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; import android.util.DisplayMetrics; import android.util.FloatMath; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ImageView; public class RepairImage extends Activity implements OnTouchListener{ public static final int RESULT_CODE_NOFOUND = 200; Matrix matrix = new Matrix(); Matrix savedMatrix = new Matrix(); DisplayMetrics dm; ImageView imgView; Bitmap bitmap; /** 最小缩放比例*/ float minScaleR = 1.0f; /** 最大缩放比例*/ static final float MAX_SCALE = 10f; /** 初始状态*/ static final int NONE = 0; /** 拖动*/ static final int DRAG = 1; /** 缩放*/ static final int ZOOM = 2; /** 当前模式*/ int mode = NONE; PointF prev = new PointF(); PointF mid = new PointF(); float dist = 1f; private String url; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.repairimage); // 获取图片资源 Intent intent = getIntent(); url = intent.getStringExtra("bitmap"); imgView= (ImageView) findViewById(R.id.repairImageView); AQuery aq = new AQuery(RepairImage.this); aq.id(R.id.repairImageView).image(url, true, true, 400, 0,new BitmapAjaxCallback(){ @Override public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status){ bitmap=bm; imgView.setImageBitmap(bitmap); imgView.setOnTouchListener(RepairImage.this);// 设置触屏监听 dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm);// 获取分辨率 minZoom(); center(); System.out.println(matrix.toString()); imgView.setImageMatrix(matrix); } }); } public void SureOnClick(View v) { } /** * 触屏监听 */ public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { // 主点按下 case MotionEvent.ACTION_DOWN: savedMatrix.set(matrix); prev.set(event.getX(), event.getY()); mode = DRAG; break; // 副点按下 case MotionEvent.ACTION_POINTER_DOWN: dist = spacing(event); // 如果连续两点距离大于10,则判定为多点模式 if (spacing(event) > 10f) { savedMatrix.set(matrix); midPoint(mid, event); mode = ZOOM; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = NONE; //savedMatrix.set(matrix); break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { matrix.set(savedMatrix); matrix.postTranslate(event.getX() - prev.x, event.getY() - prev.y); } else if (mode == ZOOM) { float newDist = spacing(event); if (newDist > 10f) { matrix.set(savedMatrix); float tScale = newDist / dist; matrix.postScale(tScale, tScale, mid.x, mid.y); } } break; } //if(imgView) imgView.setImageMatrix(matrix); CheckView(); return true; } /** * 限制最大最小缩放比例,自动居中 */ private void CheckView() { float p[] = new float[9]; matrix.getValues(p); if (mode == ZOOM) { if (p[0] < minScaleR) { //Log.d("", "当前缩放级别:"+p[0]+",最小缩放级别:"+minScaleR); matrix.setScale(minScaleR, minScaleR); } if (p[0] > MAX_SCALE) { //Log.d("", "当前缩放级别:"+p[0]+",最大缩放级别:"+MAX_SCALE); matrix.set(savedMatrix); } } center(); } /** * 最小缩放比例,最大为100% */ private void minZoom() { minScaleR = Math.min( (float) dm.widthPixels / (float) bitmap.getWidth(), (float) dm.heightPixels / (float) bitmap.getHeight()); System.out.println(minScaleR); if (minScaleR < 1.0) { matrix.postScale(minScaleR, minScaleR); } } private void center() { center(true, true); } /** * 横向、纵向居中 */ protected void center(boolean horizontal, boolean vertical) { Matrix m = new Matrix(); m.set(matrix); RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); m.mapRect(rect); float height = rect.height(); float width = rect.width(); float deltaX = 0, deltaY = 0; if (vertical) { // 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下方留空则往下移 int screenHeight = dm.heightPixels; if (height < screenHeight) { deltaY = (screenHeight - height) / 2 - rect.top; } else if (rect.top > 0) { deltaY = -rect.top; } else if (rect.bottom < screenHeight) { deltaY = imgView.getHeight() - rect.bottom; } } if (horizontal) { int screenWidth = dm.widthPixels; if (width < screenWidth) { deltaX = (screenWidth - width) / 2 - rect.left; } else if (rect.left > 0) { deltaX = -rect.left; } else if (rect.right < screenWidth) { deltaX = screenWidth - rect.right; } } matrix.postTranslate(deltaX, deltaY); } /** * 两点的距离 */ private float spacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return FloatMath.sqrt(x * x + y * y); } /** * 两点的中点 */ private void midPoint(PointF point, MotionEvent event) { float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); point.set(x / 2, y / 2); } }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。