你的位置:首页 > 操作系统

[操作系统]ViewPager 可左右滑动和缩放的图片浏览


最近因为要做一个项目,需要使用到图片的浏览。我就自己在网上找了些资料,然后加以修改整理后出来一个demo,希望可以帮助到需要的人。同时这也是我第一个技术博客。

在做之前首先需要了解一下什么是ViewPager,怎么使用ViewPager。我这里提供一篇文章给大家  http://www.2cto.com/kf/201411/353975.html   我这里不在赘述了。

好了  了解完可以开始了

 PS  我不知道怎么制作那种动态的效果图,如果有谁知道请告诉我  我将万分感谢

 

 

 

一步一步来

 

首先先要写个布局 ViewPager的布局   activity_main.

 1 <LinearLayout ="http://schemas.android.com/apk/res/android" 2   ="http://schemas.android.com/tools" android:layout_width="match_parent" 3   android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" 4   android:paddingRight="@dimen/activity_horizontal_margin" 5   android:paddingTop="@dimen/activity_vertical_margin" 6   android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity" 7   android:orientation="vertical"> 8  9   <LinearLayout10     android:id="@+id/linearlayout"11     android:layout_width="300dp"12     android:layout_height="300dp"13     android:background="@drawable/bg_common_frames"14     android:layout_gravity="center"15     >16 17     <android.support.v4.view.ViewPager18       android:id="@+id/viewpager"19       android:layout_width="wrap_content"20       android:layout_height="wrap_content"21       android:layout_gravity="center"22       />23 24   </LinearLayout>25 26 27 28 </LinearLayout>

对应的效果是这样的 请看 有点丑 不管啦。用了一张底图  在上面代码中的 LinearLayout

 

然后是图片详情布局     image_details.

 1 <??> 2 <RelativeLayout ="http://schemas.android.com/apk/res/android" 3   android:layout_width="match_parent" 4   android:layout_height="match_parent"> 5  6   <android.support.v4.view.ViewPager 7     android:id="@+id/view_pager" 8     android:layout_width="match_parent" 9     android:layout_height="match_parent">10   </android.support.v4.view.ViewPager>11 12   <TextView13     android:id="@+id/page_text"14     android:layout_width="wrap_content"15     android:layout_height="wrap_content"16     android:layout_alignParentBottom="true"17     android:layout_centerHorizontal="true"18     android:layout_marginBottom="10dp"19     android:textColor="#fff"20     android:textSize="18sp" />21 22 </RelativeLayout>

 

最后一个布局是缩放的布局  zoom_image_layout.

1 <??>2 <com.higgs.mviewpager.ZoomImageView ="http://schemas.android.com/apk/res/android"3   android:id="@+id/zoom_image_view"4   android:layout_width="match_parent"5   android:layout_height="match_parent"6   android:background="#000000" >7 8 </com.higgs.mviewpager.ZoomImageView>

 

 

 

 

 

 

基本的布局我们完成了

 

再看代码吧

 

我这里因为迎合大部分朋友的需求 ,改成了从网络上下载图片的方式作为图片来源

先模拟一个图片URL的类

 1 package com.higgs.mviewpager; 2  3 public class Images { 4  5   public final static String[] imageUrls = new String[]{ 6       "http://img.my.csdn.net/uploads/201309/01/1378037235_3453.jpg", 7       "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg", 8       "http://img.my.csdn.net/uploads/201309/01/1378037235_9280.jpg", 9       "http://img.my.csdn.net/uploads/201309/01/1378037234_3539.jpg",10       "http://img.my.csdn.net/uploads/201309/01/1378037234_6318.jpg",11   };12 }

 

然后就是实现代码了

说一下思路, 先获取ViewPager 然后往ViewPager 添加图片,但是图片是网络上的 所以要先下载后在添加进去,这里处于防止加载比较多的图片时造成OOM问题 所以引入了 LruCache 类缓存技术。先讲下载的图片存入手机里并缓存下来,一为了节省用户的数据流量,二为了之后的加载速度。有了缓冲下次就不用在重复去网络上下载了。  代码如下

 1 package com.higgs.mviewpager; 2  3 import android.app.Activity; 4 import android.content.Intent; 5 import android.graphics.Bitmap; 6 import android.graphics.BitmapFactory; 7 import android.os.AsyncTask; 8 import android.os.Bundle; 9 import android.os.Environment; 10 import android.support.v4.view.PagerAdapter; 11 import android.support.v4.view.ViewPager; 12 import android.util.Log; 13 import android.view.View; 14 import android.view.ViewGroup; 15 import android.widget.ImageView; 16 import android.widget.Toast; 17  18 import java.io.BufferedInputStream; 19 import java.io.BufferedOutputStream; 20 import java.io.BufferedReader; 21 import java.io.File; 22 import java.io.FileOutputStream; 23 import java.io.IOException; 24 import java.io.InputStream; 25 import java.io.InputStreamReader; 26 import java.net.HttpURLConnection; 27 import java.net.URL; 28 import java.util.ArrayList; 29  30  31 public class MainActivity extends Activity { 32  33   private static final String TAG = "MainActivity"; 34   private ImageLoader imageLoader = ImageLoader.getInstance(); //获取图片进行管理的工具类实例。 35  36   private ViewPager viewpager; 37   private ArrayList<View> viewList; 38 //  private ImageView imageView1; 39 //  private ImageView imageView2; 40 //  private ImageView imageView3; 41   @Override 42   protected void onCreate(Bundle savedInstanceState) { 43     super.onCreate(savedInstanceState); 44     setContentView(R.layout.activity_main); 45     initView(); 46   } 47  48  49   private void initView() { 50     viewpager = (ViewPager) findViewById(R.id.viewpager); //获取viewpager 51     viewList = new ArrayList<View>();  //保存view,用于PagerAdapter 52     for(int i = 0; i<Images.imageUrls.length; i++){ 53       new DownLoadPic().execute(i);//图片有几张就下载几张 54     } 55  56  57  58 // 59 //    imageView1 = new ImageView(this); 60 //    imageView2 = new ImageView(this); 61 //    imageView3 = new ImageView(this); 62 //    imageView1.setImageResource(R.drawable.b); 63 //    imageView2.setImageResource(R.drawable.c); 64 //    imageView3.setImageResource(R.drawable.d); 65 // 66 //    viewList.add(imageView1); 67 //    viewList.add(imageView2); 68 //    viewList.add(imageView3); 69  70     viewpager.setAdapter(pagerAdapter); //加入适配器 71     Log.e("TAG1", "" + viewList.size()); 72  73   } 74  75  76   /** 77    * 图片异步下载内部类 78   */ 79  80   class DownLoadPic extends AsyncTask<Integer,Void,Bitmap>{ 81  82     /** 83      * 记录每个图片对应的位置 84     */ 85     private int mposition; 86  87     @Override 88     protected Bitmap doInBackground(Integer... params) { 89  90       mposition = params[0];//获取传过来的图片position (下标) 91       String strurl = Images.imageUrls[mposition]; //通过下标获得图片URL 92       File imageFile = new File(getImagePath(strurl)); //获取图片在本地手机中的位置路径 93       if (!imageFile.exists()) { //判断是否存在手机里 94         doPost(strurl);//如果没有就下载图片 95       } 96       if (strurl != null) { 97         Bitmap bitmap = ImageLoader.decodeSampledBitmapFromResource(imageFile.getPath(), 98             290); //压缩图片 我这里写的是290 99         if (bitmap != null) {100           imageLoader.addBitmapToMemoryCache(strurl, bitmap); //将图片加入缓冲 LruCache中101           return bitmap;102         }103       }104 105 106       return null;107     }108 109     @Override110     protected void onPostExecute(Bitmap o) {111       ImageView imageView = new ImageView(MainActivity.this);112       imageView.setImageBitmap(o);113       imageView.setOnClickListener(new View.OnClickListener() {114         @Override115         public void onClick(View v) {116 117           Intent intent = new Intent(MainActivity.this, ImageDetailsActivity.class);//打开图片详情类118           intent.putExtra("image_position", mposition);119           MainActivity.this.startActivity(intent);120         }121       });122 123       viewList.add(imageView);124       pagerAdapter.notifyDataSetChanged(); //这句话一定不能少 ,不然会有异常125       Log.e("TAG2", "" + viewList.size());126 127 128     }129 130 131   }132 133   /**134    * ViewPager的适配器 重写下面几个方法就可以了135   */136 137   PagerAdapter pagerAdapter = new PagerAdapter() {138 139     @Override140     public int getCount() {141 142       return viewList.size();143     }144 145     @Override146     public boolean isViewFromObject(View view, Object object) {147       return view == object;148     }149 150     @Override151     public void destroyItem(ViewGroup container, int position,152                 Object object) {153       container.removeView(viewList.get(position));154 155     }156 157     @Override158     public int getItemPosition(Object object) {159 160       return super.getItemPosition(object);161     }162 163     @Override164     public Object instantiateItem(ViewGroup container, int position) {165       container.addView(viewList.get(position));166       return viewList.get(position);167     }168 169   };170 171 172   /**173    * 下载图片方法 并将图片缓冲至手机指定位置中174    * @param urlstr 图片URL175   */176   public void doPost(String urlstr){177     if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {178       Log.d("TAG", "monted sdcard");179     } else {180       Log.d("TAG", "has no sdcard");181     }182     HttpURLConnection con = null;183     FileOutputStream fos = null;184     BufferedOutputStream bos = null;185     BufferedInputStream bis = null;186     File imageFile = null;187     try {188       URL url = new URL(urlstr);189       con = (HttpURLConnection) url.openConnection();190       con.setConnectTimeout(5 * 1000);191       con.setReadTimeout(15 * 1000);192       con.setDoInput(true);193       con.setDoOutput(true);194       bis = new BufferedInputStream(con.getInputStream());195       imageFile = new File(getImagePath(urlstr));196       fos = new FileOutputStream(imageFile);197       bos = new BufferedOutputStream(fos);198       byte[] b = new byte[1024];199       int length;200       while ((length = bis.read(b)) != -1) {// 写入手机中201         bos.write(b, 0, length);202         bos.flush();203       }204     } catch (Exception e) {205       e.printStackTrace();206     } finally {207       try {208         if (bis != null) {209           bis.close();210         }211         if (bos != null) {212           bos.close();213         }214         if (con != null) {215           con.disconnect();216         }217       } catch (IOException e) {218         e.printStackTrace();219       }220     }221     if (imageFile != null) {222       Bitmap bitmap = ImageLoader.decodeSampledBitmapFromResource(imageFile.getPath(),223           290);224       if (bitmap != null) {225         imageLoader.addBitmapToMemoryCache(urlstr, bitmap);226       }227     }228   }229 230   /**231    * 获取图片的本地存储路径。232    *233    * @param imageUrl234    *      图片的URL地址。235    * @return 图片的本地存储路径。236   */237   private String getImagePath(String imageUrl) {238     int lastSlashIndex = imageUrl.lastIndexOf("/");239     String imageName = imageUrl.substring(lastSlashIndex + 1);240     String imageDir = Environment.getExternalStorageDirectory().getPath()241         + "/pwxceshibao/";242     File file = new File(imageDir);243     if (!file.exists()) {244       file.mkdirs();245     }246     String imagePath = imageDir + imageName;247     return imagePath;248   }249 250 }

 

下面是几个工具类。是我从网上找的。个人觉得非常有用。所以就拿过来了。注意了,下面几个工具类都用上了,所以不能少哦

在这里要感谢 http://blog.csdn.net/sziicool/article/details/18728187  博主,我是站在他的肩膀上修改的。

 

 

第一个是查看大图类  就是图片详情类

 1 package com.higgs.mviewpager; 2  3 import android.app.Activity; 4 import android.graphics.Bitmap; 5 import android.graphics.BitmapFactory; 6 import android.os.Bundle; 7 import android.os.Environment; 8 import android.support.v4.view.PagerAdapter; 9 import android.support.v4.view.ViewPager; 10 import android.support.v4.view.ViewPager.OnPageChangeListener; 11 import android.view.LayoutInflater; 12 import android.view.View; 13 import android.view.ViewGroup; 14 import android.view.Window; 15 import android.widget.TextView; 16  17 import java.io.File; 18  19 /** 20  * 查看大图的Activity界面。 21  *  22  * @author guolin 23 */ 24 public class ImageDetailsActivity extends Activity implements 25     OnPageChangeListener { 26  27   /** 28    * 用于管理图片的滑动 29   */ 30   private ViewPager viewPager; 31  32   /** 33    * 显示当前图片的页数 34   */ 35   private TextView pageText; 36  37   @Override 38   protected void onCreate(Bundle savedInstanceState) { 39     super.onCreate(savedInstanceState); 40     requestWindowFeature(Window.FEATURE_NO_TITLE); 41     setContentView(R.layout.image_details); 42     int imagePosition = getIntent().getIntExtra("image_position", 0); 43     pageText = (TextView) findViewById(R.id.page_text); 44     viewPager = (ViewPager) findViewById(R.id.view_pager); 45     ViewPagerAdapter adapter = new ViewPagerAdapter(); 46     viewPager.setAdapter(adapter); 47     viewPager.setCurrentItem(imagePosition); 48     viewPager.setOnPageChangeListener(this); 49     viewPager.setEnabled(false); 50     // 设定当前的页数和总页数 51     pageText.setText((imagePosition + 1) + "/" + Images.imageUrls.length); 52   } 53  54   /** 55    * ViewPager的适配器 56    *  57    * @author guolin 58   */ 59   class ViewPagerAdapter extends PagerAdapter { 60  61     @Override 62     public Object instantiateItem(ViewGroup container, int position) { 63       String imagePath = getImagePath(Images.imageUrls[position]); 64       Bitmap bitmap = BitmapFactory.decodeFile(imagePath); 65       if (bitmap == null) { 66         bitmap = BitmapFactory.decodeResource(getResources(), 67             R.drawable.empty_photo); 68       } 69       View view = LayoutInflater.from(ImageDetailsActivity.this).inflate( 70           R.layout.zoom_image_layout, null); 71       ZoomImageView zoomImageView = (ZoomImageView) view 72           .findViewById(R.id.zoom_image_view); 73       zoomImageView.setImageBitmap(bitmap); 74       container.addView(view); 75       return view; 76     } 77  78     @Override 79     public int getCount() { 80       return Images.imageUrls.length; 81     } 82  83     @Override 84     public boolean isViewFromObject(View arg0, Object arg1) { 85       return arg0 == arg1; 86     } 87  88     @Override 89     public void destroyItem(ViewGroup container, int position, Object object) { 90       View view = (View) object; 91       container.removeView(view); 92     } 93  94   } 95  96   /** 97    * 获取图片的本地存储路径。 98    *  99    * @param imageUrl100    *      图片的URL地址。101    * @return 图片的本地存储路径。102   */103   private String getImagePath(String imageUrl) {104     int lastSlashIndex = imageUrl.lastIndexOf("/");105     String imageName = imageUrl.substring(lastSlashIndex + 1);106     String imageDir = Environment.getExternalStorageDirectory().getPath()107         + "/pwxceshibao/";108     File file = new File(imageDir);109     if (!file.exists()) {110       file.mkdirs();111     }112     String imagePath = imageDir + imageName;113     return imagePath;114   }115 116   @Override117   public void onPageScrollStateChanged(int arg0) {118 119   }120 121   @Override122   public void onPageScrolled(int arg0, float arg1, int arg2) {123 124   }125 126   @Override127   public void onPageSelected(int currentPage) {128     // 每当页数发生改变时重新设定一遍当前的页数和总页数129     pageText.setText((currentPage + 1) + "/" + Images.imageUrls.length);130   }131 132 }

第二个是图片缩放工具类

 1 package com.higgs.mviewpager; 2  3 import android.content.Context; 4 import android.graphics.Bitmap; 5 import android.graphics.Canvas; 6 import android.graphics.Matrix; 7 import android.util.AttributeSet; 8 import android.view.MotionEvent; 9 import android.view.View; 10  11 /** 12  * 自定义的ImageView控制,可对图片进行多点触控缩放和拖动 13  *  14  * @author guolin 15 */ 16 public class ZoomImageView extends View { 17  18   /** 19    * 初始化状态常量 20   */ 21   public static final int STATUS_INIT = 1; 22  23   /** 24    * 图片放大状态常量 25   */ 26   public static final int STATUS_ZOOM_OUT = 2; 27  28   /** 29    * 图片缩小状态常量 30   */ 31   public static final int STATUS_ZOOM_IN = 3; 32  33   /** 34    * 图片拖动状态常量 35   */ 36   public static final int STATUS_MOVE = 4; 37  38   /** 39    * 用于对图片进行移动和缩放变换的矩阵 40   */ 41   private Matrix matrix = new Matrix(); 42  43   /** 44    * 待展示的Bitmap对象 45   */ 46   private Bitmap sourceBitmap; 47  48   /** 49    * 记录当前操作的状态,可选值为STATUS_INIT、STATUS_ZOOM_OUT、STATUS_ZOOM_IN和STATUS_MOVE 50   */ 51   private int currentStatus; 52  53   /** 54    * ZoomImageView控件的宽度 55   */ 56   private int width; 57  58   /** 59    * ZoomImageView控件的高度 60   */ 61   private int height; 62  63   /** 64    * 记录两指同时放在屏幕上时,中心点的横坐标值 65   */ 66   private float centerPointX; 67  68   /** 69    * 记录两指同时放在屏幕上时,中心点的纵坐标值 70   */ 71   private float centerPointY; 72  73   /** 74    * 记录当前图片的宽度,图片被缩放时,这个值会一起变动 75   */ 76   private float currentBitmapWidth; 77  78   /** 79    * 记录当前图片的高度,图片被缩放时,这个值会一起变动 80   */ 81   private float currentBitmapHeight; 82  83   /** 84    * 记录上次手指移动时的横坐标 85   */ 86   private float lastXMove = -1; 87  88   /** 89    * 记录上次手指移动时的纵坐标 90   */ 91   private float lastYMove = -1; 92  93   /** 94    * 记录手指在横坐标方向上的移动距离 95   */ 96   private float movedDistanceX; 97  98   /** 99    * 记录手指在纵坐标方向上的移动距离100   */101   private float movedDistanceY;102 103   /**104    * 记录图片在矩阵上的横向偏移值105   */106   private float totalTranslateX;107 108   /**109    * 记录图片在矩阵上的纵向偏移值110   */111   private float totalTranslateY;112 113   /**114    * 记录图片在矩阵上的总缩放比例115   */116   private float totalRatio;117 118   /**119    * 记录手指移动的距离所造成的缩放比例120   */121   private float scaledRatio;122 123   /**124    * 记录图片初始化时的缩放比例125   */126   private float initRatio;127 128   /**129    * 记录上次两指之间的距离130   */131   private double lastFingerDis;132 133   /**134    * ZoomImageView构造函数,将当前操作状态设为STATUS_INIT。135    * 136    * @param context137    * @param attrs138   */139   public ZoomImageView(Context context, AttributeSet attrs) {140     super(context, attrs);141     currentStatus = STATUS_INIT;142   }143 144   /**145    * 将待展示的图片设置进来。146    * 147    * @param bitmap148    *      待展示的Bitmap对象149   */150   public void setImageBitmap(Bitmap bitmap) {151     sourceBitmap = bitmap;152     invalidate();153   }154 155   @Override156   protected void onLayout(boolean changed, int left, int top, int right,157       int bottom) {158     super.onLayout(changed, left, top, right, bottom);159     if (changed) {160       // 分别获取到ZoomImageView的宽度和高度161       width = getWidth();162       height = getHeight();163     }164   }165 166   @Override167   public boolean onTouchEvent(MotionEvent event) {168     if (initRatio == totalRatio) {169       getParent().requestDisallowInterceptTouchEvent(false);170     } else {171       getParent().requestDisallowInterceptTouchEvent(true);172     }173     switch (event.getActionMasked()) {174     case MotionEvent.ACTION_POINTER_DOWN:175       if (event.getPointerCount() == 2) {176         // 当有两个手指按在屏幕上时,计算两指之间的距离177         lastFingerDis = distanceBetweenFingers(event);178       }179       break;180     case MotionEvent.ACTION_CANCEL:181     case MotionEvent.ACTION_MOVE:182       if (event.getPointerCount() == 1) {183         // 只有单指按在屏幕上移动时,为拖动状态184         float xMove = event.getX();185         float yMove = event.getY();186         if (lastXMove == -1 && lastYMove == -1) {187           lastXMove = xMove;188           lastYMove = yMove;189         }190         currentStatus = STATUS_MOVE;191         movedDistanceX = xMove - lastXMove;192         movedDistanceY = yMove - lastYMove;193         // 进行边界检查,不允许将图片拖出边界194         if (totalTranslateX + movedDistanceX > 0) {195           movedDistanceX = 0;196         } else if (width - (totalTranslateX + movedDistanceX) > currentBitmapWidth) {197           movedDistanceX = 0;198         }199         if (totalTranslateY + movedDistanceY > 0) {200           movedDistanceY = 0;201         } else if (height - (totalTranslateY + movedDistanceY) > currentBitmapHeight) {202           movedDistanceY = 0;203         }204         // 调用onDraw()方法绘制图片205         invalidate();206         lastXMove = xMove;207         lastYMove = yMove;208       } else if (event.getPointerCount() == 2) {209         // 有两个手指按在屏幕上移动时,为缩放状态210         centerPointBetweenFingers(event);211         double fingerDis = distanceBetweenFingers(event);212         if (fingerDis > lastFingerDis) {213           currentStatus = STATUS_ZOOM_OUT;214         } else {215           currentStatus = STATUS_ZOOM_IN;216         }217         // 进行缩放倍数检查,最大只允许将图片放大4倍,最小可以缩小到初始化比例218         if ((currentStatus == STATUS_ZOOM_OUT && totalRatio < 4 * initRatio)219             || (currentStatus == STATUS_ZOOM_IN && totalRatio > initRatio)) {220           scaledRatio = (float) (fingerDis / lastFingerDis);221           totalRatio = totalRatio * scaledRatio;222           if (totalRatio > 4 * initRatio) {223             totalRatio = 4 * initRatio;224           } else if (totalRatio < initRatio) {225             totalRatio = initRatio;226           }227           // 调用onDraw()方法绘制图片228           invalidate();229           lastFingerDis = fingerDis;230         }231       }232       break;233     case MotionEvent.ACTION_POINTER_UP:234       if (event.getPointerCount() == 2) {235         // 手指离开屏幕时将临时值还原236         lastXMove = -1;237         lastYMove = -1;238       }239       break;240     case MotionEvent.ACTION_UP:241       // 手指离开屏幕时将临时值还原242       lastXMove = -1;243       lastYMove = -1;244       break;245     default:246       break;247     }248     return true;249   }250 251   /**252    * 根据currentStatus的值来决定对图片进行什么样的绘制操作。253   */254   @Override255   protected void onDraw(Canvas canvas) {256     super.onDraw(canvas);257     switch (currentStatus) {258     case STATUS_ZOOM_OUT:259     case STATUS_ZOOM_IN:260       zoom(canvas);261       break;262     case STATUS_MOVE:263       move(canvas);264       break;265     case STATUS_INIT:266       initBitmap(canvas);267     default:268       if (sourceBitmap != null) {269         canvas.drawBitmap(sourceBitmap, matrix, null);270       }271       break;272     }273   }274 275   /**276    * 对图片进行缩放处理。277    * 278    * @param canvas279   */280   private void zoom(Canvas canvas) {281     matrix.reset();282     // 将图片按总缩放比例进行缩放283     matrix.postScale(totalRatio, totalRatio);284     float scaledWidth = sourceBitmap.getWidth() * totalRatio;285     float scaledHeight = sourceBitmap.getHeight() * totalRatio;286     float translateX = 0f;287     float translateY = 0f;288     // 如果当前图片宽度小于屏幕宽度,则按屏幕中心的横坐标进行水平缩放。否则按两指的中心点的横坐标进行水平缩放289     if (currentBitmapWidth < width) {290       translateX = (width - scaledWidth) / 2f;291     } else {292       translateX = totalTranslateX * scaledRatio + centerPointX293           * (1 - scaledRatio);294       // 进行边界检查,保证图片缩放后在水平方向上不会偏移出屏幕295       if (translateX > 0) {296         translateX = 0;297       } else if (width - translateX > scaledWidth) {298         translateX = width - scaledWidth;299       }300     }301     // 如果当前图片高度小于屏幕高度,则按屏幕中心的纵坐标进行垂直缩放。否则按两指的中心点的纵坐标进行垂直缩放302     if (currentBitmapHeight < height) {303       translateY = (height - scaledHeight) / 2f;304     } else {305       translateY = totalTranslateY * scaledRatio + centerPointY306           * (1 - scaledRatio);307       // 进行边界检查,保证图片缩放后在垂直方向上不会偏移出屏幕308       if (translateY > 0) {309         translateY = 0;310       } else if (height - translateY > scaledHeight) {311         translateY = height - scaledHeight;312       }313     }314     // 缩放后对图片进行偏移,以保证缩放后中心点位置不变315     matrix.postTranslate(translateX, translateY);316     totalTranslateX = translateX;317     totalTranslateY = translateY;318     currentBitmapWidth = scaledWidth;319     currentBitmapHeight = scaledHeight;320     canvas.drawBitmap(sourceBitmap, matrix, null);321   }322 323   /**324    * 对图片进行平移处理325    * 326    * @param canvas327   */328   private void move(Canvas canvas) {329     matrix.reset();330     // 根据手指移动的距离计算出总偏移值331     float translateX = totalTranslateX + movedDistanceX;332     float translateY = totalTranslateY + movedDistanceY;333     // 先按照已有的缩放比例对图片进行缩放334     matrix.postScale(totalRatio, totalRatio);335     // 再根据移动距离进行偏移336     matrix.postTranslate(translateX, translateY);337     totalTranslateX = translateX;338     totalTranslateY = translateY;339     canvas.drawBitmap(sourceBitmap, matrix, null);340   }341 342   /**343    * 对图片进行初始化操作,包括让图片居中,以及当图片大于屏幕宽高时对图片进行压缩。344    * 345    * @param canvas346   */347   private void initBitmap(Canvas canvas) {348     if (sourceBitmap != null) {349       matrix.reset();350       int bitmapWidth = sourceBitmap.getWidth();351       int bitmapHeight = sourceBitmap.getHeight();352       if (bitmapWidth > width || bitmapHeight > height) {353         if (bitmapWidth - width > bitmapHeight - height) {354           // 当图片宽度大于屏幕宽度时,将图片等比例压缩,使它可以完全显示出来355           float ratio = width / (bitmapWidth * 1.0f);356           matrix.postScale(ratio, ratio);357           float translateY = (height - (bitmapHeight * ratio)) / 2f;358           // 在纵坐标方向上进行偏移,以保证图片居中显示359           matrix.postTranslate(0, translateY);360           totalTranslateY = translateY;361           totalRatio = initRatio = ratio;362         } else {363           // 当图片高度大于屏幕高度时,将图片等比例压缩,使它可以完全显示出来364           float ratio = height / (bitmapHeight * 1.0f);365           matrix.postScale(ratio, ratio);366           float translateX = (width - (bitmapWidth * ratio)) / 2f;367           // 在横坐标方向上进行偏移,以保证图片居中显示368           matrix.postTranslate(translateX, 0);369           totalTranslateX = translateX;370           totalRatio = initRatio = ratio;371         }372         currentBitmapWidth = bitmapWidth * initRatio;373         currentBitmapHeight = bitmapHeight * initRatio;374       } else {375         // 当图片的宽高都小于屏幕宽高时,直接让图片居中显示376         float translateX = (width - sourceBitmap.getWidth()) / 2f;377         float translateY = (height - sourceBitmap.getHeight()) / 2f;378         matrix.postTranslate(translateX, translateY);379         totalTranslateX = translateX;380         totalTranslateY = translateY;381         totalRatio = initRatio = 1f;382         currentBitmapWidth = bitmapWidth;383         currentBitmapHeight = bitmapHeight;384       }385       canvas.drawBitmap(sourceBitmap, matrix, null);386     }387   }388 389   /**390    * 计算两个手指之间的距离。391    * 392    * @param event393    * @return 两个手指之间的距离394   */395   private double distanceBetweenFingers(MotionEvent event) {396     float disX = Math.abs(event.getX(0) - event.getX(1));397     float disY = Math.abs(event.getY(0) - event.getY(1));398     return Math.sqrt(disX * disX + disY * disY);399   }400 401   /**402    * 计算两个手指之间中心点的坐标。403    * 404    * @param event405   */406   private void centerPointBetweenFingers(MotionEvent event) {407     float xPoint0 = event.getX(0);408     float yPoint0 = event.getY(0);409     float xPoint1 = event.getX(1);410     float yPoint1 = event.getY(1);411     centerPointX = (xPoint0 + xPoint1) / 2;412     centerPointY = (yPoint0 + yPoint1) / 2;413   }414 415 }

最后一个是图片管理工具类  也是缓存核心类   这个就是上面提到的防止加载过多的图片时产生OOM

 1 package com.higgs.mviewpager; 2  3 import android.graphics.Bitmap; 4 import android.graphics.BitmapFactory; 5 import android.util.LruCache; 6  7 /** 8  * 对图片进行管理的工具类。 9  *  10  * @author Tony 11 */ 12 public class ImageLoader { 13  14   /** 15    * 图片缓存技术的核心类,用于缓存所有下载好的图片,在程序内存达到设定值时会将最少最近使用的图片移除掉。 16   */ 17   private static LruCache<String, Bitmap> mMemoryCache; 18  19   /** 20    * ImageLoader的实例。 21   */ 22   private static ImageLoader mImageLoader; 23  24   private ImageLoader() { 25     // 获取应用程序最大可用内存 26     int maxMemory = (int) Runtime.getRuntime().maxMemory(); 27     int cacheSize = maxMemory / 8; 28     // 设置图片缓存大小为程序最大可用内存的1/8 29     mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 30       @Override 31       protected int sizeOf(String key, Bitmap bitmap) { 32         return bitmap.getByteCount(); 33       } 34     }; 35   } 36  37   /** 38    * 获取ImageLoader的实例。 39    *  40    * @return ImageLoader的实例。 41   */ 42   public static ImageLoader getInstance() { 43     if (mImageLoader == null) { 44       mImageLoader = new ImageLoader(); 45     } 46     return mImageLoader; 47   } 48  49   /** 50    * 将一张图片存储到LruCache中。 51    *  52    * @param key 53    *      LruCache的键,这里传入图片的URL地址。 54    * @param bitmap 55    *      LruCache的键,这里传入从网络上下载的Bitmap对象。 56   */ 57   public void addBitmapToMemoryCache(String key, Bitmap bitmap) { 58     if (getBitmapFromMemoryCache(key) == null) { 59       mMemoryCache.put(key, bitmap); 60     } 61   } 62  63   /** 64    * 从LruCache中获取一张图片,如果不存在就返回null。 65    *  66    * @param key 67    *      LruCache的键,这里传入图片的URL地址。 68    * @return 对应传入键的Bitmap对象,或者null。 69   */ 70   public Bitmap getBitmapFromMemoryCache(String key) { 71     return mMemoryCache.get(key); 72   } 73  74   public static int calculateInSampleSize(BitmapFactory.Options options, 75       int reqWidth) { 76     // 源图片的宽度 77     final int width = options.outWidth; 78     int inSampleSize = 1; 79     if (width > reqWidth) { 80       // 计算出实际宽度和目标宽度的比率 81       final int widthRatio = Math.round((float) width / (float) reqWidth); 82       inSampleSize = widthRatio; 83     } 84     return inSampleSize; 85   } 86  87   public static Bitmap decodeSampledBitmapFromResource(String pathName, 88       int reqWidth) { 89     // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小 90     final BitmapFactory.Options options = new BitmapFactory.Options(); 91     options.inJustDecodeBounds = true; 92     BitmapFactory.decodeFile(pathName, options); 93     // 调用上面定义的方法计算inSampleSize值 94     options.inSampleSize = calculateInSampleSize(options, reqWidth); 95     // 使用获取到的inSampleSize值再次解析图片 96     options.inJustDecodeBounds = false; 97     return BitmapFactory.decodeFile(pathName, options); 98   } 99 100 }

 

 

 

好了  大家照着自己做做就可以出来效果了,因为我已经把全部的源码贴出来了,如果你懒得连代码都不想敲。我觉得此文章对你没有什么作用。只有自己敲了就理解了

第一次写博客,感觉思路很乱,很多都没有讲明白。一个是时间不够,二是关键点都有注释,代码都贴上来了。共勉~~~~