亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android實現圖片在屏幕內縮放和移動效果

2019-10-21 21:25:50
字體:
來源:轉載
供稿:網友

通常我們遇到的圖片縮放需求,都是圖片基于屏幕自適應后,進行縮放和移動,且圖片最小只能是自適應的大小。最近遇到一個需求,要求圖片只能在屏幕內縮放和移動,不能超出屏幕。

一、需求

在屏幕中加載一張圖片,圖片可以手勢縮放移動。但是圖片最大只能縮放到屏幕大小,也只允許在屏幕內移動??梢詮南到y中讀取圖片(通過絕對路徑),也可以從資源文件中讀取圖片。

Android,圖片,屏幕,縮放,移動

二、自定義ZoomImageView

屏幕內手勢縮放圖片與普通的圖片縮放相比,比較麻煩的是,需要計算圖片的精確位置。不同于普通縮放的圖片充滿屏幕,屏內縮放的圖片只占據屏幕的一部分,我們需要判斷手指是否點在圖片內,才能進行各種操作。

/** * 判斷手指是否點在圖片內(單指) */ private void isClickInImage(){ if (translationX <= mFirstX && mFirstX <= (translationX + currentW)  && translationY <= mFirstY && mFirstY <= (translationY + currentH)){  isClickInImage = true; }else {  isClickInImage = false; } }  /** * 判斷手指是否點在圖片內(雙指) * 只要有一只手指在圖片內就為true * @param event */ private void isClickInImage(MotionEvent event){ if (translationX <= event.getX(0) && event.getX(0) <= (translationX + currentW)  && translationY <= event.getY(0) && event.getY(0) <= (translationY + currentH)){  isClickInImage = true; }else if (translationX <= event.getX(1) && event.getX(1) <= (translationX + currentW)  && translationY <= event.getY(1) && event.getY(1) <= (translationY + currentH)){  isClickInImage = true; }else {  isClickInImage = false; } }

其他的各種操作,之于縮放,移動,邊界檢查等,和普通的圖片縮放沒有太多區別。完整代碼如下:

package com.uni.myapplication; import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Matrix;import android.graphics.Paint;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View; import java.io.File; /** * Created by newcboy on 2018/3/9. */ public class ZoomImageView extends View {  public static final int IMAGE_MAX_SIZE = 1000;//加載圖片允許的最大size,單位kb private float minimal = 100.0f;  private float screenW;//屏幕寬度 private float screenH;//屏幕高度  //單指按下的坐標 private float mFirstX = 0.0f; private float mFirstY = 0.0f;  //單指離開的坐標 private float lastMoveX =-1f; private float lastMoveY =-1f;  //兩指的中點坐標 private float centPointX; private float centPointY;  //圖片的繪制坐標 private float translationX = 0.0f; private float translationY = 0.0f;  //圖片的原始寬高 private float primaryW; private float primaryH;  //圖片當前寬高 private float currentW; private float currentH;  private float scale = 1.0f; private float maxScale, minScale; private Bitmap bitmap; private Matrix matrix;  private int mLocker = 0; private float fingerDistance = 0.0f;  private boolean isLoaded = false; private boolean isClickInImage = false;  public ZoomImageView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); }   /** * 從資源文件中讀取圖片 * @param context * @param imageId */ public void setResourceBitmap(Context context, int imageId){ bitmap = BitmapFactory.decodeResource(context.getResources(), imageId); isLoaded = true; primaryW = bitmap.getWidth(); primaryH = bitmap.getHeight(); matrix = new Matrix(); }  /** * 根據路徑添加圖片 * @param path * @param scale */ public void setImagePathBitmap(String path, float scale){ this.scale = scale; setImageBitmap(path); }  private void setImageBitmap(String path){ File file = new File(path); if (file.exists()){  isLoaded = true;  bitmap = ImageLoadUtils.getImageLoadBitmap(path, IMAGE_MAX_SIZE);  primaryW = bitmap.getWidth();  primaryH = bitmap.getHeight();  matrix = new Matrix(); }else {  isLoaded = false; } }  @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (changed){  screenW = getWidth();  screenH = getHeight();  translationX = (screenW - bitmap.getWidth() * scale)/ 2;  translationY = (screenH - bitmap.getHeight() * scale) / 2;  setMaxMinScale(); } }  /** * */ private void setMaxMinScale(){ float xScale, yScale;  xScale = minimal / primaryW; yScale = minimal / primaryH; minScale = xScale > yScale ? xScale : yScale;  xScale = primaryW / screenW; yScale = primaryH / screenH; if (xScale > 1 || yScale > 1 ) {  if (xScale > yScale) {  maxScale = 1/xScale;  }else {  maxScale = 1/yScale;  } }else {  if (xScale > yScale) {  maxScale = 1/xScale;  }else {  maxScale = 1/yScale;  } } if (isScaleError()){  restoreAction(); } }  @Override public boolean onTouchEvent(MotionEvent event) { if (!isLoaded){  return true; } switch (event.getActionMasked()){  case MotionEvent.ACTION_DOWN:  mFirstX = event.getX();  mFirstY = event.getY();  isClickInImage();  break;  case MotionEvent.ACTION_POINTER_DOWN:  fingerDistance = getFingerDistance(event);  isClickInImage(event);  break;  case MotionEvent.ACTION_MOVE:  float fingerNum = event.getPointerCount();  if (fingerNum == 1 && mLocker == 0 && isClickInImage){   movingAction(event);  }else if (fingerNum == 2 && isClickInImage){   zoomAction(event);  }  break;  case MotionEvent.ACTION_POINTER_UP:  mLocker = 1;  if (isScaleError()){   translationX = (event.getX(1) + event.getX(0)) / 2;   translationY = (event.getY(1) + event.getY(0)) / 2;  }  break;  case MotionEvent.ACTION_UP:  lastMoveX = -1;  lastMoveY = -1;  mLocker = 0;  if (isScaleError()){   restoreAction();  }  break; } return true; }   /** * 移動操作 * @param event */ private void movingAction(MotionEvent event){ float moveX = event.getX(); float moveY = event.getY(); if (lastMoveX == -1 || lastMoveY == -1) {  lastMoveX = moveX;  lastMoveY = moveY; } float moveDistanceX = moveX - lastMoveX; float moveDistanceY = moveY - lastMoveY; translationX = translationX + moveDistanceX; translationY = translationY + moveDistanceY; lastMoveX = moveX; lastMoveY = moveY; invalidate(); }  /** * 縮放操作 * @param event */ private void zoomAction(MotionEvent event){ midPoint(event); float currentDistance = getFingerDistance(event); if (Math.abs(currentDistance - fingerDistance) > 1f) {  float moveScale = currentDistance / fingerDistance;  scale = scale * moveScale;  translationX = translationX * moveScale + centPointX * (1-moveScale);  translationY = translationY * moveScale + centPointY * (1-moveScale);  fingerDistance = currentDistance;  invalidate(); } }  /** * 圖片恢復到指定大小 */ private void restoreAction(){ if (scale < minScale){  scale = minScale; }else if (scale > maxScale){  scale = maxScale; } translationX = translationX - bitmap.getWidth()*scale / 2; translationY = translationY - bitmap.getHeight()*scale / 2; invalidate(); }   /** * 判斷手指是否點在圖片內(單指) */ private void isClickInImage(){ if (translationX <= mFirstX && mFirstX <= (translationX + currentW)  && translationY <= mFirstY && mFirstY <= (translationY + currentH)){  isClickInImage = true; }else {  isClickInImage = false; } }  /** * 判斷手指是否點在圖片內(雙指) * 只要有一只手指在圖片內就為true * @param event */ private void isClickInImage(MotionEvent event){ if (translationX <= event.getX(0) && event.getX(0) <= (translationX + currentW)  && translationY <= event.getY(0) && event.getY(0) <= (translationY + currentH)){  isClickInImage = true; }else if (translationX <= event.getX(1) && event.getX(1) <= (translationX + currentW)  && translationY <= event.getY(1) && event.getY(1) <= (translationY + currentH)){  isClickInImage = true; }else {  isClickInImage = false; } }   /** * 獲取兩指間的距離 * @param event * @return */ private float getFingerDistance(MotionEvent event){ float x = event.getX(1) - event.getX(0); float y = event.getY(1) - event.getY(0); return (float) Math.sqrt(x * x + y * y); }  /** * 判斷圖片大小是否符合要求 * @return */ private boolean isScaleError(){ if (scale > maxScale  || scale < minScale){  return true; } return false; }   /** * 獲取兩指間的中點坐標 * @param event */ private void midPoint(MotionEvent event){ centPointX = (event.getX(1) + event.getX(0))/2; centPointY = (event.getY(1) + event.getY(0))/2; }  @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (isLoaded){  imageZoomView(canvas); } }  private void imageZoomView(Canvas canvas){ currentW = primaryW * scale; currentH = primaryH * scale; matrix.reset(); matrix.postScale(scale, scale);//x軸y軸縮放 peripheryJudge(); matrix.postTranslate(translationX, translationY);//中點坐標移動 canvas.drawBitmap(bitmap, matrix, null); }  /** * 圖片邊界檢查 * (只在屏幕內) */ private void peripheryJudge(){ if (translationX < 0){  translationX = 0; } if (translationY < 0){  translationY = 0; } if ((translationX + currentW) > screenW){  translationX = screenW - currentW; } if ((translationY + currentH) > screenH){  translationY = screenH - currentH; } } }

實際上,用Bitmap繪制圖片時,可以通過Paint設置圖片透明度。

Paint paint = new Paint();paint.setStyle( Paint.Style.STROKE);paint.setAlpha(150);

在setAlpha()中傳入一個0~255的整數。數字越大,透明度越低。

然后在繪制圖片時

canvas.drawBitmap(bitmap, matrix, paint);

三、ImageLoadUtils圖片加載類

這個類是對傳入的圖片進行壓縮處理的類,在應用從系統中讀取圖片時用到。在寫這個類時,發現一些和網上說法不一樣的地方。

options.inSampleSize這個屬性,網上的說法是必須是2的冪次方,但實際上,我的驗證結果是所有的整數都可以。

這里采用的壓縮方法是,獲取系統剩余內存和圖片大小,然后將圖片壓縮到合適的大小。

package com.uni.myapplication; import android.app.ActivityManager;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BitmapFactory.Options;import android.net.Uri; import java.io.File;import java.io.FileInputStream; /** * 圖片加載工具類 * * Created by newcboy on 2018/1/25. */ public class ImageLoadUtils {  /** * 原圖加載,根據傳入的指定圖片大小。 * @param imagePath * @param maxSize * @return */ public static Bitmap getImageLoadBitmap(String imagePath, int maxSize){ int fileSize = 1; Bitmap bitmap = null; int simpleSize = 1; File file = new File(imagePath); if (file.exists()) {  Uri imageUri = Uri.parse(imagePath);  try {  fileSize = (int) (getFileSize(file) / 1024);  } catch (Exception e) {  e.printStackTrace();  }  Options options = new Options();  if (fileSize > maxSize){  for (simpleSize = 2; fileSize>= maxSize; simpleSize++){   fileSize = fileSize / simpleSize;  }  }  options.inSampleSize = simpleSize;  bitmap = BitmapFactory.decodeFile(imageUri.getPath(), options); } return bitmap; }   /** * 獲取指定文件的大小 * @param file * @return * @throws Exception */ public static long getFileSize(File file) throws Exception{ if(file == null) {  return 0; } long size = 0; if(file.exists()) {  FileInputStream mInputStream = new FileInputStream(file);  size = mInputStream.available(); } return size; }   /** * 獲取手機運行內存 * @param context * @return */ public static long getTotalMemorySize(Context context){ long size = 0; ActivityManager activityManager = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();//outInfo對象里面包含了內存相關的信息 activityManager.getMemoryInfo(outInfo);//把內存相關的信息傳遞到outInfo里面C++思想 //size = outInfo.totalMem; //總內存 size = outInfo.availMem; //剩余內存 return (size/1024/1024); } }

四、調用

使用方法和通常的控件差不多,只是多了一個設置圖片的方法。

1.在布局文件中添加布局。

<com.uni.myapplication.ZoomImageView android:id="@+id/zoom_image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" />

2.在代碼中調用

zoomImageView = (ZoomImageView) findViewById(R.id.zoom_image_view);zoomImageView.setImagePathBitmap(MainActivity.this, imagePath, 1.0f);zoomImageView.setResourceBitmap(MainActivity.this, R.mipmap.ic_launcher);

其中setImagePathBitmap()是從系統中讀取圖片加載的方法,setResourceBitmap()是從資源文件中讀取圖片的方法。
當然,從系統讀取圖片需要添加讀寫權限,這個不能忘了。而且6.0以上的系統需要動態獲取權限。動態獲取權限的方法這里就不介紹了,網上有很詳細的說明。

五、最終效果

Android,圖片,屏幕,縮放,移動

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美在线视频导航| 欧美成人精品影院| 国产精品手机播放| 久久久久久久久电影| 成人xvideos免费视频| 国产免费一区二区三区在线观看| 最近2019年好看中文字幕视频| 欧美一区二区大胆人体摄影专业网站| 中文字幕久久久| 91精品久久久久久久久| 亚洲精品日韩丝袜精品| 九九视频这里只有精品| 日韩在线视频观看| 亚洲嫩模很污视频| 欧美裸体xxxxx| 欧美性感美女h网站在线观看免费| 黑人巨大精品欧美一区免费视频| 久久久久久久爱| 69av视频在线播放| 亚洲精品福利免费在线观看| 国产精选久久久久久| 韩国19禁主播vip福利视频| 欧美另类精品xxxx孕妇| 国产视频综合在线| 亚洲在线视频福利| 日韩亚洲一区二区| 日韩精品免费一线在线观看| 97精品一区二区三区| 国产精品久久久久高潮| 国产噜噜噜噜久久久久久久久| 韩国国内大量揄拍精品视频| 国产精品久久久久久搜索| 97免费在线视频| 久久久免费av| 中文字幕亚洲欧美在线| 成人网在线免费看| 久久成人亚洲精品| 亚洲免费视频在线观看| 久久久久久噜噜噜久久久精品| 欧美日韩午夜激情| 亚洲福利精品在线| 久久久久久91| 91久久精品国产91久久| 欧美激情日韩图片| 国产成人精品在线观看| 国产精品盗摄久久久| 亚洲欧洲黄色网| 久久九九全国免费精品观看| 欧美成人亚洲成人日韩成人| 北条麻妃一区二区在线观看| 久久久久亚洲精品成人网小说| 久久精品99久久香蕉国产色戒| 亚洲xxxx妇黄裸体| 午夜精品一区二区三区在线| 91高清免费视频| 欧美日韩高清区| 欧美在线免费看| 精品国产一区二区三区久久久| 亚洲色图13p| 久久综合免费视频| 欧美成在线观看| 国产精品第10页| 国产成人欧美在线观看| 日韩天堂在线视频| 8x海外华人永久免费日韩内陆视频| 亚洲天堂久久av| 国内伊人久久久久久网站视频| 性欧美xxxx| 另类专区欧美制服同性| 国产欧美一区二区白浆黑人| 色先锋资源久久综合5566| 国产精品白嫩美女在线观看| 疯狂欧美牲乱大交777| 色综合久久88| 91网站在线免费观看| 国产日本欧美一区二区三区| 亚洲午夜性刺激影院| 欧美激情网站在线观看| 久久久久久久久久久人体| 欧美久久久精品| 国产精品久久久久9999| 欧美日韩在线视频观看| 韩国福利视频一区| www.亚洲一区| 国产成人精品午夜| 91精品国产综合久久香蕉的用户体验| 亚洲欧洲第一视频| 国产精品成人一区二区| 国产精品久久久久久久久粉嫩av| 欧美一区二粉嫩精品国产一线天| 国产精品中文在线| 精品亚洲男同gayvideo网站| 亚洲精品美女视频| 亚洲曰本av电影| 亚洲精品av在线| 久久久中精品2020中文| 热99精品只有里视频精品| 国产精品最新在线观看| 国产精品精品视频一区二区三区| 欧美日韩国产一区在线| 另类图片亚洲另类| 欧美在线视频在线播放完整版免费观看| 亚洲少妇激情视频| 国产大片精品免费永久看nba| 日韩成人在线观看| 亚洲欧美在线磁力| 欧美日韩性视频在线| 亚洲第一综合天堂另类专| 91系列在线播放| 欧美一级电影免费在线观看| 欧美日韩国产一区二区三区| 91色视频在线导航| 欧美性猛交xxxx黑人猛交| 欧美日韩国产影院| 久99久在线视频| 久久综合88中文色鬼| 日韩av不卡在线| 国产精品久久久久久久一区探花| 亚洲美女免费精品视频在线观看| 欧美性xxxxx极品| 欧美孕妇与黑人孕交| 欧美中文在线视频| 久久久久久久久久国产| 国产91精品视频在线观看| 日韩精品免费电影| 欧美激情亚洲综合一区| 久久国产加勒比精品无码| 91视频国产高清| 欧美日韩中文字幕| 亚洲欧美精品suv| 亚洲精品国产精品国自产在线| 91精品久久久久久| 国产精品永久免费在线| 中文字幕视频在线免费欧美日韩综合在线看| 国产精品视频免费在线| 国产精品网红直播| 国产日产欧美精品| 久久久久久97| 久久久在线视频| 九九热99久久久国产盗摄| 久久久人成影片一区二区三区观看| 亚洲成人av在线| 亚洲成人网av| 97在线视频免费看| 国产综合在线观看视频| 欧美裸体xxxx| 国产欧美va欧美va香蕉在线| 欧美猛交免费看| 亚洲国产精品久久久久久| 九九热视频这里只有精品| 97热在线精品视频在线观看| 成人av番号网| 久久久久久国产三级电影| 日韩在线免费高清视频| xvideos亚洲人网站| 欧美精品999| 欧美激情视频一区| 日韩av在线播放资源| 精品一区电影国产| 日韩精品中文在线观看| 国产精品国产自产拍高清av水多| 日韩在线精品一区| 亚洲免费av片| 国产精品96久久久久久又黄又硬|