在qq空间或者微信朋友圈里 看到图片总会点击图片进行查看,图片放大缩小功能包括通过手势放大缩小旋转以及双击放大缩小,并且可以左右滑动看到前一张图片或者后一张图片,需要该功能的话,这篇文章或许可以给你帮助。
众所周知,imageloader异步加载图片,不仅可以快速加载图片,而且还可以将图片保存到sdk缓存中,因此下载图片用imageloader即可,如有不懂的,可简单看下我的这篇文章http://blog.csdn.net/u012303938/article/details/46330123,scaleimageview网上流行的一个继续于imageview的封装可以放大缩小的view,viewpager是可以实现左右滑动v4jar包中的类。
demo下载地址http://download.csdn.net/detail/u012303938/8764507
本demo实现了一个简单的相册功能,点击相册,异步加载所有图片,点击图片查看,左右滑动上下张,可手势放大缩小查看的图片。
上代码
BaseAvtivity
package com.example.image; import android.app.Activity; import android.os.Bundle; import android.view.Window; public abstract class BaseActivity extends Activity{ protected void onCreate(Bundle savedInstanceState,int layoutResID) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(layoutResID); findView(); addListenr(); } public abstract void findView(); public abstract void addListenr(); }主要的mianactivti继承与baseactivity
package com.example.image; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import com.nostra13.universalimageloader.core.ImageLoader; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.GridView; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; public class MainActivity extends BaseActivity { private Button btn_dl,tv_left; private ListView lv; private Context context; private TextView tv_tt; private ArrayList<Map<String, Object>> list=new ArrayList<Map<String,Object>>(); String[] imageUrls = new String[] { "http://file.bmob.cn/M00/D9/44/oYYBAFSGZlyAXZjwAAC5ynS9Zww4985471", "http://file.bmob.cn/M00/D8/8F/oYYBAFSFh_WAB_uIAAB4PTlS6rI0966668",}; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState,R.layout.activity_main); loadData(); } private void loadData() { // TODO Auto-generated method stub for(int i=0;i<imageUrls.length;i++){ Map<String, Object> map=new HashMap<String, Object>(); map.put("text", "我的相册"+i+"张"); list.add(map); } MyAdapter adapter=new MyAdapter(); lv.setAdapter(adapter); lv.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub startActivity(new Intent(context,PhotoGlDetail.class)); } }); } @Override public void findView() { // TODO Auto-generated method stub context=this; lv=(ListView) findViewById(R.id.lv); } @Override public void addListenr() { // TODO Auto-generated method stub } private class MyAdapter extends BaseAdapter{ class HolderView { public ImageView imageView1; public TextView textView1; } public int getCount() { // TODO Auto-generated method stub return list.size(); } public Object getItem(int arg0) { // TODO Auto-generated method stub return list.get(arg0); } public long getItemId(int arg0) { // TODO Auto-generated method stub return arg0; } public View getView(int position, View converView, ViewGroup arg2) { // TODO Auto-generated method stub HolderView holderView=null; if(converView==null){ holderView=new HolderView(); converView=View.inflate(context, R.layout.photo_item, null); holderView.textView1=(TextView) converView.findViewById(R.id.textView1); holderView.imageView1=(ImageView) converView.findViewById(R.id.imageView1); converView.setTag(holderView); }else{ holderView=(HolderView) converView.getTag(); } holderView.textView1.setText(list.get(position).get("text").toString()); ImageLoader.getInstance().displayImage(imageUrls[position], holderView.imageView1); return converView; } } }Tapplication继承的application
package com.example.image; import java.io.File; import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.assist.QueueProcessingType; import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer; import com.nostra13.universalimageloader.utils.StorageUtils; import android.app.Application; import android.content.Context; public class TAppliacation extends Application{ @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); File cacheDir = StorageUtils.getOwnCacheDirectory(getApplicationContext(), "imageloader/Cache"); DisplayImageOptions defaultOptions = new DisplayImageOptions .Builder() .showImageForEmptyUri(R.drawable.ic_empty) .showImageOnFail(R.drawable.ic_error) .cacheInMemory(true) .cacheOnDisc(true) .considerExifParams(true) .build(); ImageLoaderConfiguration config = new ImageLoaderConfiguration .Builder(getApplicationContext()) .discCache(new UnlimitedDiscCache(cacheDir)) .defaultDisplayImageOptions(defaultOptions) .discCacheSize(50 * 1024 * 1024)// .discCacheFileCount(100)// .threadPriority(Thread.NORM_PRIORITY - 2) .denyCacheImageMultipleSizesInMemory() .tasksProcessingOrder(QueueProcessingType.LIFO) .writeDebugLogs() .build(); ImageLoader.getInstance().init(config); } }异步加载所有图片phtogldetail
package com.example.image; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer; /* * @author CarrayDraw * @time 2015-6-1 * 照片详细 */ public class PhotoGlDetail extends BaseActivity{ private ArrayList<Map<String, Object>> list=new ArrayList<Map<String,Object>>(); private GridView gridView1; private Context context; private ArrayList<byte[]> lbyte=new ArrayList<byte[]>(); DisplayImageOptions options; //private NormalLoadPictrue loadPictrue; public static String[] imageUrls = new String[] { "http://file.bmob.cn/M00/D8/8F/oYYBAFSFh_WAB_uIAAB4PTlS6rI0966668", "http://file.bmob.cn/M00/D7/56/oYYBAFSBhJSAIdIJAACoNxTDcM44444974", "http://file.bmob.cn/M00/D9/45/oYYBAFSGZvKAdpqWAACKHHYyClU0459660", "http://file.bmob.cn/M00/D9/45/oYYBAFSGZreAEyRSAADfcLFM62U5428980", "http://file.bmob.cn/M00/D9/44/oYYBAFSGZlyAXZjwAAC5ynS9Zww4985471", "http://file.bmob.cn/M00/D9/44/oYYBAFSGZYqAUYxAAADSNZMdbOs5036914", "http://file.bmob.cn/M00/D9/43/oYYBAFSGZRCATj2XAADDaZB1Nbo6433800", "http://file.bmob.cn/M00/D9/41/oYYBAFSGZJKAWXyDAADPOI8iH6Q3523485", "http://file.bmob.cn/M00/D8/8F/oYYBAFSFiE6AbAu2AACfguCRGHY3486277", "http://file.bmob.cn/M00/D7/57/oYYBAFSBhd-Aa1IiAAC86WAfmc89917549", "http://file.bmob.cn/M00/D7/55/oYYBAFSBgiKAC2aGAAC4We1hZmk1405980", "http://file.bmob.cn/M00/D7/56/oYYBAFSBgrmAXQ8BAAD665llCTc5545260", "http://file.bmob.cn/M00/D7/56/oYYBAFSBg-CAePQKAAC38mflwMY8903422"}; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState,R.layout.photodetail); options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.ic_launcher) .showImageForEmptyUri(R.drawable.ic_empty) .showImageOnFail(R.drawable.ic_error).cacheInMemory(true) .cacheOnDisc(true).considerExifParams(true) .displayer(new RoundedBitmapDisplayer(20)).build(); loadData(); } private void loadData() { // TODO Auto-generated method stub for(int i=0;i<imageUrls.length;i++){ Map<String, Object> map=new HashMap<String, Object>(); map.put("img", imageUrls[i]); list.add(map); } MyAdapter adapter=new MyAdapter(); gridView1.setAdapter(adapter); gridView1.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { // TODO Auto-generated method stub Intent intent=new Intent(context,HeadPortrait.class); intent.putExtra("bitmap", lbyte); intent.putExtra("pos", position); startActivity(intent); } }); } @Override public void findView() { // TODO Auto-generated method stub context=this; // loadPictrue=new NormalLoadPictrue(); gridView1=(GridView) findViewById(R.id.gridView1); } private class MyAdapter extends BaseAdapter{ class HolderView { public ImageView imageView1; } public int getCount() { // TODO Auto-generated method stub return list.size(); } public Object getItem(int arg0) { // TODO Auto-generated method stub return list.get(arg0); } public long getItemId(int arg0) { // TODO Auto-generated method stub return arg0; } public View getView(final int position, View converView, ViewGroup arg2) { // TODO Auto-generated method stub HolderView holderView=null; if(converView==null){ holderView=new HolderView(); converView=View.inflate(context,R.layout.photodetail_item, null); holderView.imageView1=(ImageView) converView.findViewById(R.id.imageView1); converView.setTag(holderView); }else{ holderView=(HolderView) converView.getTag(); } //loadPictrue.getPicture(imageUrls[position], holderView.imageView1); ImageLoader.getInstance().displayImage(imageUrls[position], holderView.imageView1,options); return converView; } } @Override public void addListenr() { // TODO Auto-generated method stub } }查看图片的类 headportrail
package com.example.image; import java.io.File; import java.util.ArrayList; import com.nostra13.universalimageloader.cache.disc.DiscCacheAware; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.DiscCacheUtil; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Environment; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; /* * @author CrrayDraw * @time 2015-6-1 * 查看图片 */ public class HeadPortrait extends Activity implements OnPageChangeListener{ private ViewPager viewPager; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.aaa); textView=(TextView) findViewById(R.id.textView); viewPager=(ViewPager) findViewById(R.id.viewPager); Intent intent = getIntent(); if (intent != null) { int currentPos=intent.getIntExtra("pos", 0); MyAdapter adapter=new MyAdapter(); viewPager.setAdapter(adapter); viewPager.setCurrentItem(currentPos); viewPager.setEnabled(false); viewPager.setOnPageChangeListener(this); textView.setText(currentPos+"/"+PhotoGlDetail.imageUrls.length); } } class MyAdapter extends PagerAdapter{ @Override public int getCount() { // TODO Auto-generated method stub return PhotoGlDetail.imageUrls.length; } @Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub View view=(View) object; container.removeView(view); } @Override public Object instantiateItem(ViewGroup container, int position) { // TODO Auto-generated method stub Bitmap bitmap =null; File file=DiscCacheUtil.findInCache(PhotoGlDetail.imageUrls[position], ImageLoader.getInstance().getDiscCache() ); if(file.exists()){ bitmap= BitmapFactory.decodeFile(file.getPath()); } if(bitmap==null){ Log.i("values", "i:"+position); bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.ic_empty); } Log.i("values", "iiiii:"+position); View view=View.inflate(HeadPortrait.this, R.layout.img_frag, null); ScaleImageView imageView=(ScaleImageView) view.findViewById(R.id.img); imageView.setImageBitmap(bitmap); container.addView(imageView); return view; } @Override public boolean isViewFromObject(View agr0, Object arg1) { // TODO Auto-generated method stub return agr0==arg1; } } public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } public void onPageSelected(int currentPos) { // TODO Auto-generated method stub textView.setText((currentPos+1)+"/"+PhotoGlDetail.imageUrls.length); } public String getpaths(String url){ String urlPath=url.substring(url.indexOf("/")+1); return url; } }网上流行的scaleimageview
package com.example.image; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ImageView; /** * 来自网络:图片缩放控件(支持缩放、拖动双击旋转)<br> * * @author kymjs (https://github.com/kymjs) */ public class ScaleImageView extends ImageView { public enum ImageState { NONE, // 初始状 DRAG, // 拖动 ZOOM, // 缩放 ROTATE, // 旋转 ZOOM_OR_ROTATE // 缩放或旋 } private ImageState mode = ImageState.NONE; static final float MAX_SCALE = 2.5f; private float imageW; // 图片宽度 private float imageH; // 图片高度 private float rotatedImageW; private float rotatedImageH; private float viewW; private float viewH; private final Matrix matrix = new Matrix(); private final Matrix savedMatrix = new Matrix(); private final PointF pA = new PointF(); private final PointF pB = new PointF(); private final PointF mid = new PointF(); private final PointF lastClickPos = new PointF(); private long lastClickTime = 0; // 上次点击时间(用于计算双击) private double rotation = 0.0; private float dist = 1f; // 两点间距 private boolean canRotate = true; // 是否启旋转图片功 private boolean canDoubleClick = true; // 是否启双击缩放功 public void setCanDoubleClick(boolean canDoubleClick) { this.canDoubleClick = canDoubleClick; } public boolean canDoubleClick() { return canDoubleClick; } public void setCanRotate(boolean canRotate) { this.canRotate = canRotate; } public boolean canRotate() { return canRotate; } public ScaleImageView(Context context) { super(context); initView(); } public ScaleImageView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public ScaleImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(); } /** * 初始化控 */ private void initView() { setScaleType(ImageView.ScaleType.MATRIX); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap(bm); setImageWidthHeight(); } @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); setImageWidthHeight(); } @Override public void setImageResource(int resId) { super.setImageResource(resId); setImageWidthHeight(); } private void setImageWidthHeight() { Drawable d = getDrawable(); if (d == null) { return; } imageW = rotatedImageW = d.getIntrinsicWidth(); imageH = rotatedImageH = d.getIntrinsicHeight(); initImage(); } /** * 图片大小改变时回 */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); viewW = w; viewH = h; if (oldw == 0) { // 如果图片还没有计算大 initImage(); } else { fixScale(); // 固定大小 fixTranslation(); setImageMatrix(matrix); } } /** * 首次加载,初始化图片控件 */ private void initImage() { if (viewW <= 0 || viewH <= 0 || imageW <= 0 || imageH <= 0) { return; } mode = ImageState.NONE; matrix.setScale(0, 0); fixScale(); fixTranslation(); setImageMatrix(matrix); } /** * 设置matrix,记录当前图片大 */ private void fixScale() { float p[] = new float[9]; matrix.getValues(p); float curScale = Math.abs(p[0]) + Math.abs(p[1]); float minScale = Math.min(viewW / rotatedImageW, viewH / rotatedImageH); if (curScale < minScale) { if (curScale > 0) { double scale = minScale / curScale; p[0] = (float) (p[0] * scale); p[1] = (float) (p[1] * scale); p[3] = (float) (p[3] * scale); p[4] = (float) (p[4] * scale); matrix.setValues(p); } else { matrix.setScale(minScale, minScale); } } } /** * 大缩放 */ private float maxPostScale() { float p[] = new float[9]; matrix.getValues(p); float curScale = Math.abs(p[0]) + Math.abs(p[1]); float minScale = Math.min(viewW / rotatedImageW, viewH / rotatedImageH); float maxScale = Math.max(minScale, MAX_SCALE); return maxScale / curScale; } /** * 移动matrix */ private void fixTranslation() { RectF rect = new RectF(0, 0, imageW, imageH); matrix.mapRect(rect); float height = rect.height(); float width = rect.width(); float deltaX = 0, deltaY = 0; if (width < viewW) { deltaX = (viewW - width) / 2 - rect.left; } else if (rect.left > 0) { deltaX = -rect.left; } else if (rect.right < viewW) { deltaX = viewW - rect.right; } if (height < viewH) { deltaY = (viewH - height) / 2 - rect.top; } else if (rect.top > 0) { deltaY = -rect.top; } else if (rect.bottom < viewH) { deltaY = viewH - rect.bottom; } matrix.postTranslate(deltaX, deltaY); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { // 主点按下 :记录当前matrix,以及初始化按下坐标、图片状 case MotionEvent.ACTION_DOWN: savedMatrix.set(matrix); pA.set(event.getX(), event.getY()); pB.set(event.getX(), event.getY()); mode = ImageState.DRAG; break; // 副点按下 :如果间距大10,记录此时matrix,以及两点的坐标、图片状 case MotionEvent.ACTION_POINTER_DOWN: if (event.getActionIndex() > 1) // 超过两个点返 break; dist = spacing(event.getX(0), event.getY(0), event.getX(1), event.getY(1)); if (dist > 10f) { // 如果连续两点距离大于10,则判定为多点模 savedMatrix.set(matrix); pA.set(event.getX(0), event.getY(0)); pB.set(event.getX(1), event.getY(1)); mid.set((event.getX(0) + event.getX(1)) / 2, (event.getY(0) + event.getY(1)) / 2); mode = ImageState.ZOOM_OR_ROTATE; } break; // 主点或负点抬 case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: if (mode == ImageState.DRAG) { if (spacing(pA.x, pA.y, pB.x, pB.y) < 50) { long now = System.currentTimeMillis(); if (now - lastClickTime < 500 && spacing(pA.x, pA.y, lastClickPos.x, lastClickPos.y) < 50) { doubleClick(pA.x, pA.y); now = 0; } lastClickPos.set(pA); lastClickTime = now; } } else if (mode == ImageState.ROTATE) { int level = (int) Math.floor((rotation + Math.PI / 4) / (Math.PI / 2)); if (level == 4) level = 0; matrix.set(savedMatrix); matrix.postRotate(90 * level, mid.x, mid.y); if (level == 1 || level == 3) { float tmp = rotatedImageW; rotatedImageW = rotatedImageH; rotatedImageH = tmp; fixScale(); } fixTranslation(); setImageMatrix(matrix); } mode = ImageState.NONE; break; // 拖动 case MotionEvent.ACTION_MOVE: if (mode == ImageState.ZOOM_OR_ROTATE) { PointF pC = new PointF(event.getX(1) - event.getX(0) + pA.x, event.getY(1) - event.getY(0) + pA.y); double a = spacing(pB.x, pB.y, pC.x, pC.y); double b = spacing(pA.x, pA.y, pC.x, pC.y); double c = spacing(pA.x, pA.y, pB.x, pB.y); if (a >= 10) { double cosB = (a * a + c * c - b * b) / (2 * a * c); double angleB = Math.acos(cosB); double PID4 = Math.PI / 4; if (angleB > PID4 && angleB < 3 * PID4) { mode = ImageState.ROTATE; rotation = 0; } else { mode = ImageState.ZOOM; } } } if (mode == ImageState.DRAG) { matrix.set(savedMatrix); pB.set(event.getX(), event.getY()); matrix.postTranslate(event.getX() - pA.x, event.getY() - pA.y); fixTranslation(); setImageMatrix(matrix); } else if (mode == ImageState.ZOOM) { float newDist = spacing(event.getX(0), event.getY(0), event.getX(1), event.getY(1)); if (newDist > 10f) { matrix.set(savedMatrix); float tScale = Math.min(newDist / dist, maxPostScale()); matrix.postScale(tScale, tScale, mid.x, mid.y); fixScale(); fixTranslation(); setImageMatrix(matrix); } } else if (mode == ImageState.ROTATE) { if (canRotate) { PointF pC = new PointF( event.getX(1) - event.getX(0) + pA.x, event.getY(1) - event.getY(0) + pA.y); double a = spacing(pB.x, pB.y, pC.x, pC.y); double b = spacing(pA.x, pA.y, pC.x, pC.y); double c = spacing(pA.x, pA.y, pB.x, pB.y); if (b > 10) { double cosA = (b * b + c * c - a * a) / (2 * b * c); double angleA = Math.acos(cosA); double ta = pB.y - pA.y; double tb = pA.x - pB.x; double tc = pB.x * pA.y - pA.x * pB.y; double td = ta * pC.x + tb * pC.y + tc; if (td > 0) { angleA = 2 * Math.PI - angleA; } rotation = angleA; matrix.set(savedMatrix); matrix.postRotate((float) (rotation * 180 / Math.PI), mid.x, mid.y); setImageMatrix(matrix); } } } break; } return true; } /** * 两点的距 */ private float spacing(float x1, float y1, float x2, float y2) { float x = x1 - x2; float y = y1 - y2; return (float) Math.sqrt(x * x + y * y); } /** * 双击时调 */ private void doubleClick(float x, float y) { if (canDoubleClick) { float p[] = new float[9]; matrix.getValues(p); float curScale = Math.abs(p[0]) + Math.abs(p[1]); float minScale = Math.min(viewW / rotatedImageW, viewH / rotatedImageH); if (curScale <= minScale + 0.01) { // 放大 float toScale = Math.max(minScale, MAX_SCALE) / curScale; matrix.postScale(toScale, toScale, x, y); } else { // 缩小 float toScale = minScale / curScale; matrix.postScale(toScale, toScale, x, y); fixTranslation(); } setImageMatrix(matrix); } } }
imageloader+scaleimageview+viewpager组合异步加载图片的图片浏览功能
原文地址:http://blog.csdn.net/u012303938/article/details/46328899