ViewPager 可左右滑動和縮放的圖片瀏覽


最近因為要做一個項目,需要使用到圖片的瀏覽。我就自己在網上找了些資料,然后加以修改整理后出來一個demo,希望可以幫助到需要的人。同時這也是我第一個技術博客。

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

好了  了解完可以開始了

 PS  我不知道怎么制作那種動態的效果圖,如果有誰知道請告訴我  我將萬分感謝

 

 

 

一步一步來

 

首先先要寫個布局 ViewPager的布局   activity_main.xml

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="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     <LinearLayout
10         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.ViewPager
18             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.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="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     <TextView
13         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.xml

1 <?xml version="1.0" encoding="utf-8"?>
2 <com.higgs.mviewpager.ZoomImageView xmlns:android="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         @Override
110         protected void onPostExecute(Bitmap o) {
111             ImageView imageView = new ImageView(MainActivity.this);
112             imageView.setImageBitmap(o);
113             imageView.setOnClickListener(new View.OnClickListener() {
114                 @Override
115                 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         @Override
140         public int getCount() {
141 
142             return viewList.size();
143         }
144 
145         @Override
146         public boolean isViewFromObject(View view, Object object) {
147             return view == object;
148         }
149 
150         @Override
151         public void destroyItem(ViewGroup container, int position,
152                                 Object object) {
153             container.removeView(viewList.get(position));
154 
155         }
156 
157         @Override
158         public int getItemPosition(Object object) {
159 
160             return super.getItemPosition(object);
161         }
162 
163         @Override
164         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  圖片URL
175      */
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 imageUrl
234      *            圖片的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 imageUrl
100      *            圖片的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     @Override
117     public void onPageScrollStateChanged(int arg0) {
118 
119     }
120 
121     @Override
122     public void onPageScrolled(int arg0, float arg1, int arg2) {
123 
124     }
125 
126     @Override
127     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 context
137      * @param attrs
138      */
139     public ZoomImageView(Context context, AttributeSet attrs) {
140         super(context, attrs);
141         currentStatus = STATUS_INIT;
142     }
143 
144     /**
145      * 將待展示的圖片設置進來。
146      * 
147      * @param bitmap
148      *            待展示的Bitmap對象
149      */
150     public void setImageBitmap(Bitmap bitmap) {
151         sourceBitmap = bitmap;
152         invalidate();
153     }
154 
155     @Override
156     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     @Override
167     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     @Override
255     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 canvas
279      */
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 + centerPointX
293                     * (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 + centerPointY
306                     * (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 canvas
327      */
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 canvas
346      */
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 event
393      * @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 event
405      */
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 }

 

 

 

好了  大家照着自己做做就可以出來效果了,因為我已經把全部的源碼貼出來了,如果你懶得連代碼都不想敲。我覺得此文章對你沒有什么作用。只有自己敲了就理解了

第一次寫博客,感覺思路很亂,很多都沒有講明白。一個是時間不夠,二是關鍵點都有注釋,代碼都貼上來了。共勉~~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM