支持縮放的fresco圖片控制項 —— fresco sample: ZoomableDraweeView

来源:http://www.cnblogs.com/ibosong/archive/2017/02/25/6433386.html
-Advertisement-
Play Games

最近在實現一個類似淘寶中的評論列表的功能,其中要在列表中顯示評論圖,點擊圖片後顯示大圖進行查看,各家app幾乎都會有這樣的功能。 可以看到,一個體驗較好的查看大圖的基本功能有, 第一,左右滑動時切換圖片; 第二,雙擊或雙指縮放實現圖片的縮放; 第三,圖片放大時,滑動到邊緣繼續滑動時,切換圖片。 因為 ...


最近在實現一個類似淘寶中的評論列表的功能,其中要在列表中顯示評論圖,點擊圖片後顯示大圖進行查看,各家app幾乎都會有這樣的功能。

可以看到,一個體驗較好的查看大圖的基本功能有,

第一,左右滑動時切換圖片;

第二,雙擊或雙指縮放實現圖片的縮放;

第三,圖片放大時,滑動到邊緣繼續滑動時,切換圖片。

因為我們的app中使用了fresco庫,但fresco提供的SimpleDraweeView不支持縮放,看網上有人擴展了SimpleDraweeView,使之支持縮放。但經過漫長的調研,發現fresco近期提供了一個新的sample:ZoomableDraweeView,專門用來支持縮放,欣喜若狂的下載下來把玩了一把,發現三個需求點都滿足!可惜的是,這個控制項在細節上有幾點不滿足:雙擊後放大到最大,再雙擊後卻縮小為最小(期望恢復為正常大小),雖然最小可以設置,但這個值應該是在雙指縮小時才用到。另一點是在雙指縮小並鬆開後,圖片保持在那個縮小的尺寸(期望自動恢復為正常大小)。

查看代碼後發現需要修改幾點就可以滿足我的需求。下麵的內容主要記錄我思考問題、解決問題的思路,如果你也有類似的需求,可以直接拿代碼:https://github.com/ibosong/CommentGallery

1. 雙擊恢復正常尺寸

修改DoubleTapGestureListener 中的onDoubleTapEvent方法,因為主要修改的邏輯在雙指鬆開後,於是我們在MotionEvent.ACTION_UP的case中修改相關邏輯。首先判斷mDoubleTapScroll,即是否是雙擊後不鬆開並滑動的操作,這種操作下如果在鬆開手指時,圖片為縮小狀態,應當恢復正常大小,所以將原代碼:

if (mDoubleTapScroll) {
  float scale = calcScale(vp);
  zc.zoomToPoint(scale, mDoubleTapImagePoint, mDoubleTapViewPoint);
}

修改為:

if (mDoubleTapScroll) {
    float scale = calcScale(vp);
    if (scale < 1.0f) {
        zc.zoomToPoint(1.0f, mDoubleTapImagePoint, mDoubleTapViewPoint,
                DefaultZoomableController.LIMIT_ALL,
                DURATION_MS,
                null);
    } else {
        zc.zoomToPoint(scale, mDoubleTapImagePoint, mDoubleTapViewPoint);
    }
}

else裡面的代碼是正常雙擊後的代碼,將其中的minScale 改為1.0f即可

else {
    final float maxScale = zc.getMaxScaleFactor();
    final float minScale = zc.getMinScaleFactor();
    if (zc.getScaleFactor() < (maxScale + minScale) / 2) {
        zc.zoomToPoint(
                maxScale,
                ip,
                vp,
                DefaultZoomableController.LIMIT_ALL,
                DURATION_MS,
                null);

    } else {
        zc.zoomToPoint(
                /*minScale*/1.0f,
                ip,
                vp,
                DefaultZoomableController.LIMIT_ALL,
                DURATION_MS,
                null);
    }
}

2. 雙指縮放,處理雙指縮小圖片後鬆開手指的情況

閱讀代碼可知,ZoomableDraweeView中的onTouchEvent方法調用了DefaultZoomableController的onTouchEvent方法,這裡面通過mGestureDetector的處理,最終回調到ZoomableDraweeView中的onGestureBegin,onGestureUpdate和onGestureEnd這三個方法中。mGestureDetector的處理是在MultiPointerGestureDetector的onTouchEvent方法中。這裡面原來的按下和鬆開手指的邏輯是這樣的:

case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP: {
  // restart gesture whenever the number of pointers changes
  mNewPointerCount = getPressedPointerCount(event);
  stopGesture();
  updatePointersOnTap(event);
  if (mPointerCount > 0 && shouldStartGesture()) {
    startGesture();
  }
  break;
}
 

每次在MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP情況下執行相同的動作:先stopGesture,然後startGesture,即先觸發onGestureEnd,然後觸發onGestureBegin。顯然這樣的處理是不合邏輯的,為什麼在手指按下的時候要觸發onGestureEnd?於是我們將代碼修改為:

case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
    mNewPointerCount = getPressedPointerCount(event);
    updatePointersOnTap(event);
    if (mPointerCount > 0 && shouldStartGesture()) {
        startGesture();
    }
    break;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP: {
    mNewPointerCount = getPressedPointerCount(event);
updatePointersOnTap(event); stopGesture();
break; }

在手指按下的時候觸發onGestureBegin,手指抬起的時候觸發onGestureEnd。這時候我們只要在DefaultZoomableController中的onGestureEnd方法中處理鬆開手指的情況:如果圖片被縮小,則通過調用zoomToPoint方法將圖片恢復正常大小。

@Override

public void onGestureEnd(TransformGestureDetector detector) {
    FLog.v(TAG, "onGestureEnd");
    // When the image was zoomed in, releasing the fingers will restore the size of image.
    if (getScaleFactor() < 1.0f) {
        zoomToPoint(1.0f, new PointF(0.f, 0.f), new PointF(0.f, 0.f));
    }
}

這裡onGestureUpdate方法里的邏輯也要改一下,不要再調用mGestureDetector.restartGesture()。

@Override
public void onGestureUpdate(TransformGestureDetector detector) { FLog.v(TAG, "onGestureUpdate"); boolean transformCorrected = calculateGestureTransform(mActiveTransform, LIMIT_ALL); onTransformChanged();   // if (transformCorrected) {   // mGestureDetector.restartGesture();   // } // A transformation happened, but was it without correction?
  mWasTransformCorrected = transformCorrected; }

這樣實現,操作起來比較生硬,恢復大小的時候沒有動畫。

於是我們將onGestureEnd中的處理移至AbstractAnimatedZoomableController中,並將zoomToPoint修改為另一個實現了動畫的重載的方法:

@Override
public void onGestureEnd(TransformGestureDetector detector) {
    // When the image was zoomed in, releasing the fingers will restore the size of image.
    if (getScaleFactor() < 1.0f) {
        zoomToPoint(1.0f, new PointF(0.f, 0.f), new PointF(0.f, 0.f), LIMIT_ALL, 300, null);
    }
}

這樣我們的改造就全部完成了,安裝體驗一下。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 第一部分 HTML 第一章 職業規劃和前景 職業方向規劃定位: web前端開發工程師 web網站架構師 自己創業 轉崗管理或其他 web前端開發的前景展望: 未來IT行業企業需求最多的人才 結合最新的html5搶占移動端的市場 自己創業做老闆 隨著互聯網的普及web開發成為企業的寵兒和核心 web職 ...
  • 俗話說的好,框架是服務與大家的,包含的功能比較多,代碼多。在現在追求速度的年代。應該根據自己的需求去封裝自己所需要的組件。 下邊就給大家介紹一下自己封裝的一個小彈框組件,不依賴與jQuery,代碼少,適用於一般移動端小項目。 這個插件名稱:MobileUi 包含功能:彈框,正在載入,tips1.5秒 ...
  • 不用JavaScript也能實現閱讀進度條 看圖說話 直接上代碼 ...
  • ▓▓▓▓▓▓ 大致介紹 JavaScript的簡單數據類型包括:Undefined、Null、Boolean、Number、String。JavaScript中這五種基本數據類型不是對象,其他所有值都是對象。其中還有一些對象子類型,通常被稱為內置對象(引用類型) 1、Object 2、Array 3 ...
  • 1.window常用的屬性: ①history ②location 2.history對象的方法: ①back() ②forward() ③go() 3.location對象的屬性: ①host() ②hostname() ③href() 4.location對象的方法: ①reload() ②re ...
  • Xamarin.Forms研究了好一段時間了,最近一直在學習中,想嘗試一下調用其他的SDK,就如騰訊地圖SDK(申請容易)。 完成此次項目得感謝以下鏈接: http://www.cnblogs.com/jtang/p/4698496.html 其他文檔參考: 騰訊地圖SDK(安卓)文檔 這裡面有詳細 ...
  • 序言 開始開發應用號之前,先看看官方公佈的「小程式」教程吧!(以下內容來自微信官方公佈的「小程式」開髮指南) 本文檔將帶你一步步創建完成一個微信小程式,並可以在手機上體驗該小程式的實際效果。這個小程式的首頁將會顯示歡迎語以及當前用戶的微信頭像,點擊頭像,可以在新開的頁面中查看當前小程式的啟動日誌。 ...
  • public void httpget(String uri){ HttpURLConnection connection = null; FileOutputStream fos = null; File fie = new File("/sdcard/W_Local_Data/LiveVideo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...