一因谎、小紅書(shū)縮放圖片效果
? ? ? ?效果:在列表上雙指觸摸某個(gè)ImageView后,可直接對(duì)其進(jìn)行手勢(shì)縮放的效果肴敛,并且縮放的View可全屏延伸至狀態(tài)欄缰猴,相比先點(diǎn)擊圖片進(jìn)入大圖頁(yè)再對(duì)圖片進(jìn)行雙指縮放的流程更加直接高效。如下視頻效果:
但通過(guò)以上視頻可發(fā)現(xiàn)小紅書(shū)一些異常交互問(wèn)題:
1. 縮放中心不是觸摸時(shí)兩指中心喊递,而是圖片中心随闪,達(dá)不到指哪縮哪的效果;
2. 松開(kāi)雙指骚勘,半透明背景沒(méi)有隨圖片縮小而變透明铐伴,而是圖片縮放到正常大小后突現(xiàn)變?yōu)橥该鳎?/p>
3. 松開(kāi)雙指,圖片縮放到正常大小時(shí)俏讹,(大概率)偶現(xiàn)突然變黑閃一下当宴;
4. 雙指縮放圖片圖片的過(guò)程中,背景下層還能觸發(fā)觸摸效果(如點(diǎn)底層頭像會(huì)進(jìn)個(gè)人頁(yè))泽疆。
5. 不能縮放視頻或其他View
以上問(wèn)題給小紅書(shū)持續(xù)反饋了1年多一直沒(méi)有得到解決户矢,所以索性自己高仿一個(gè),并且已經(jīng)在公司數(shù)百萬(wàn)DAU的項(xiàng)目中上線(xiàn)驗(yàn)證過(guò)于微,有需要的可放心拿去用逗嫡。
二、仿照的效果
1.雙指觸摸可指哪縮哪株依,縮放中心點(diǎn)為觸摸時(shí)雙指中心點(diǎn)驱证,而非圖片中心點(diǎn);
2.支持縮放任何View(將要縮放的View放在TouchToScaleLayout即可)恋腕;
3.松開(kāi)雙指抹锄,半透明背景隨回彈動(dòng)畫(huà)逐漸變透明;
三荠藤、相關(guān)代碼
Github鏈接:https://github.com/axkza/TouchToScaleLayout
APK地址:https://xkz-1252121784.cos.ap-chengdu.myqcloud.com/TouchToScaleLayout.apk
用法:在需要雙指觸摸縮放的View外層嵌套TouchToScaleLayout即可伙单,布局如下:
四、實(shí)現(xiàn)思路
以上代碼非常簡(jiǎn)單哈肖,下面就大概講一下思路:
如何將列表中觸摸到的View顯示到列表的上層吻育,并且可以拖動(dòng)延伸到狀態(tài)欄?
雙指觸摸該View時(shí):
- 記錄該View的寬高并通過(guò)getLocationOnScreen() 獲取其相對(duì)屏幕頂點(diǎn)的top和left淤井,用于確定View的位置布疼;
- 將該View從父布局中removeView;
-?new一個(gè)沉浸式的dialog币狠,結(jié)合上面獲取到的寬高和top游两、left,將該View addView到Dialog中顯示漩绵;(也可addView到DecorView中贱案,都是為了是能將該View平移的顯示到原本UI的上層,并且可延伸到狀態(tài)欄的效果)
如何實(shí)現(xiàn)指哪縮哪的效果止吐?
1.雙指觸摸該View時(shí):
-?記錄【首次觸摸時(shí)雙指距離】宝踪、【首次觸摸屏幕時(shí)兩指中心點(diǎn)的x坐標(biāo)】侨糟、【首次觸摸屏幕時(shí)兩指中心點(diǎn)的y坐標(biāo)】
2.ACTION_MOVE時(shí):
計(jì)算以下數(shù)值,用于縮放和位移肴沫,達(dá)到指哪縮哪的效果:
- 縮放比 = (當(dāng)前雙指距離 - 首次觸摸時(shí)雙指距離) /?首次觸摸時(shí)雙指距離
- 縮放中心點(diǎn) (0,0)
- leftMargin = 當(dāng)前兩指中心點(diǎn)的x坐標(biāo) - 首次觸摸屏幕時(shí)兩指中心點(diǎn)的x坐標(biāo) * 縮放比 + 首次觸摸時(shí)的原始leftMargin
- topMargin = 當(dāng)前兩指中心點(diǎn)的y坐標(biāo) - 首次觸摸屏幕時(shí)兩指中心點(diǎn)的y坐標(biāo) * 縮放比 + 首次觸摸時(shí)的原始leftMargin
雙指觸摸后粟害,如何解決和父控件滑動(dòng)沖突的問(wèn)題?
-?雙指觸摸該View時(shí)颤芬,調(diào)用requestDisallowInterceptTouchEvent(true)屏蔽父布局的事件攔截悲幅;
- 手指抬起時(shí),調(diào)用requestDisallowInterceptTouchEvent(false)恢復(fù)父布局的事件攔截