成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

android旋轉(zhuǎn),Android旋轉(zhuǎn)框

Android自定義控件之可平移、縮放、旋轉(zhuǎn)圖片控件

先上效果圖

創(chuàng)新互聯(lián)建站堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都做網(wǎng)站、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的清流網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

源碼

單點(diǎn)拖動(dòng)圖片對(duì)圖片進(jìn)行平移操作。雙手縮放圖片大小和旋轉(zhuǎn)圖片到一定的角度。圖片縮放的時(shí)候 不能大于最大的縮放因子和小于最小的縮放因子。大于最大縮放因子或者小于最小縮放因子需要對(duì)圖像進(jìn)行回彈。圖片旋轉(zhuǎn)的角度只能為90度的倍數(shù),不滿足90度要進(jìn)行回彈。圖片回彈要一個(gè)漸變的效果。

大體思路: 首先,Android中提供了Matrix類可以對(duì)圖像進(jìn)行處理。其次,要顯示一張圖片最容易想到的就是ImageView?;貜椧鬂u變的過程,可以通過屬性動(dòng)畫進(jìn)行設(shè)置。所以大體的思路是:繼承ImageView,重寫onTouchEvent()方法,判斷事件類型,在對(duì)應(yīng)的事件使用Matrix對(duì)圖像進(jìn)行變換。

Matrix是一個(gè)已經(jīng)封裝好的矩陣,最重要的作用就是對(duì)坐標(biāo)點(diǎn)進(jìn)行變換。

舉個(gè)栗子:

1.某個(gè)點(diǎn)(x0,y0,1)通過單位矩陣E映射得到的點(diǎn)還是(x0,y0,1)。

3.點(diǎn)(x0,y0,1)通過矩陣T映射得到的點(diǎn)就會(huì)做如下的變換

可以看到點(diǎn)(x0,y0,1)經(jīng)過T矩陣在x軸方向上平移了dx,在y軸方向上平移了dy。

通過以上的變換可以得到具體的思路: 我們維護(hù)一個(gè)圖像對(duì)應(yīng)的矩陣mCurrentMatrix,該矩陣主要是對(duì)ImageView中的圖像的各個(gè)點(diǎn)進(jìn)行映射。ImageView在容器位置擺放完成之后,置mCurrentMatrix矩陣為單位矩陣。當(dāng)onTouchEvent()方法中觸發(fā)單點(diǎn)觸控并且手指進(jìn)行平移的時(shí)候,調(diào)用矩陣mCurrentMatrix的postTranslate(dx,dy),對(duì)mCurrentMatrix進(jìn)行變換。當(dāng)手指抬起,利用變換結(jié)束后的矩陣對(duì)圖像的各個(gè)點(diǎn)進(jìn)行映射,從而得到平移變換后的圖像。同理可得,在兩只手指進(jìn)行縮放旋轉(zhuǎn)的時(shí)候,我們對(duì)矩陣mCurrentMatrix進(jìn)行各種變換,當(dāng)縮放旋轉(zhuǎn)的事件結(jié)束再利用變換完的矩陣去映射圖像的各個(gè)點(diǎn),從而得到縮放、旋轉(zhuǎn)后的圖像。

安卓自定義View進(jìn)階 - Matrix原理

安卓自定義View進(jìn)階 - Matrix詳解

首先理清事件的邏輯:

初始化圖像大小和位置

縮放圖像大小和控件大小自適應(yīng),平移圖像中心和控件中心重合

onTouchEvent()函數(shù)

平移操作

將圖像對(duì)應(yīng)的矩陣進(jìn)行變換。

縮放操作

mBoundRectF為記錄圖像邊界的矩形??s放的時(shí)候選取圖像的中心進(jìn)行縮放。

旋轉(zhuǎn)操作

旋轉(zhuǎn)的時(shí)候旋轉(zhuǎn)的旋轉(zhuǎn)中心也是圖像的中心

圖像中各個(gè)點(diǎn)的映射

調(diào)用ImageView的setImageMatrix(Matrix matrix)會(huì)讓ImageView根據(jù)設(shè)置的matrix去重新繪制圖像。

更新圖像的矩形邊界

獲得圖像的矩形,并根據(jù)矩陣映射矩形各個(gè)點(diǎn)的坐標(biāo)。

縮放回彈

旋轉(zhuǎn)回彈

一些計(jì)算方法

要求圖像的變換是一個(gè)漸變的過程,很容易想到的就是屬性動(dòng)畫。因?yàn)閷傩詣?dòng)畫本身就是對(duì)值進(jìn)行不斷set的過程。而我們維護(hù)的矩陣也是一個(gè)值,所以很自然可以想到,如果得到回彈之前的矩陣的值以及回彈之后矩陣的值,就可以根據(jù)動(dòng)畫監(jiān)聽器中動(dòng)畫當(dāng)前的系數(shù)值去改變矩陣的值。

對(duì)animator對(duì)象設(shè)置完監(jiān)聽器之后,就可以在手指抬起的時(shí)候調(diào)用屬性動(dòng)畫的start()方法開啟動(dòng)畫。

自定義可平移、縮放、旋轉(zhuǎn)的控件主要點(diǎn)有兩個(gè)方面:一是onTouchEvent()中判斷平移、旋轉(zhuǎn)、縮放的觸發(fā)條件,平移位移量、縮放比例因子、旋轉(zhuǎn)角度的計(jì)算。二是Matrix矩陣的應(yīng)用。

Android 橫屏旋轉(zhuǎn)180°監(jiān)聽方式

橫屏180°旋轉(zhuǎn)系統(tǒng)不會(huì)回調(diào)到到 onConfigurationChanged() ,只能使用其他的方案,目前有2個(gè)方案

1、使用 OrientationEventListener 監(jiān)聽屏幕的旋轉(zhuǎn),里面本質(zhì)使用的是 TYPE_ACCELEROMETER 傳感器,具體如下:

開啟調(diào)用 mOrientationListener. enable() , 關(guān)閉調(diào)用 mOrientationListener. disable() ;這種方式對(duì)性能消耗比較大, 但是可以獲取到手機(jī)當(dāng)前的角度

2、使用監(jiān)聽 DisplayManager 方式,手機(jī)切換方向會(huì)導(dǎo)致UI 顯示的改變,所以會(huì)回調(diào)到這里

這種方式不會(huì)耗性能

如何在啟動(dòng)時(shí)讓android系統(tǒng)屏幕旋轉(zhuǎn)90度

 設(shè)備平放,屏幕朝正上方。以下四個(gè)常量分別代表:

private static final int ROTATION_0 = 0;//初始情況。這個(gè)時(shí)候設(shè)備是橫屏還是豎屏與硬件設(shè)備安裝時(shí)默認(rèn)的顯示方向有關(guān)。

private static final int ROTATION_90 = 1;//設(shè)置屏幕方向自動(dòng)旋轉(zhuǎn)后,右側(cè)翻起側(cè)立時(shí),屏幕會(huì)旋轉(zhuǎn)到這個(gè)方向。

private static final int ROTATION_270 = 2;//設(shè)置屏幕方向自動(dòng)旋轉(zhuǎn)后,左側(cè)翻起度側(cè)立時(shí),屏幕會(huì)旋轉(zhuǎn)到這個(gè)方向。

private static final int ROTATION_180 = 3;//設(shè)置屏幕方向自動(dòng)旋轉(zhuǎn)后,屏幕底部側(cè)立時(shí),屏幕會(huì)旋轉(zhuǎn)到這個(gè)方向。

再看兩個(gè)數(shù)組:

view plain

private static final int[][][] THRESHOLDS_WITH_180 = new int[][][] {

{{60, 165}, {165, 195}, {195, 300}},

{{0, 30}, {165, 195}, {195, 315}, {315, 360}},

{{0, 45}, {45, 165}, {165, 195}, {330, 360}},

{{0, 45}, {45, 135}, {225, 315}, {315, 360}},

};

private static final int[][] ROTATE_TO_WITH_180 = new int[][] {

{ROTATION_90, ROTATION_180, ROTATION_270},

{ROTATION_0, ROTATION_180, ROTATION_90, ROTATION_0},

{ROTATION_0, ROTATION_270, ROTATION_180, ROTATION_0},

{ROTATION_0, ROTATION_90, ROTATION_270, ROTATION_0},

};

當(dāng)前屏幕旋轉(zhuǎn)方向?yàn)镽OTATION_0時(shí),取int[][] threshold=THRESHOLDS_WITH_180[0];

當(dāng)前屏幕旋轉(zhuǎn)方向?yàn)镽OTATION_90時(shí),取int[][] threshold=THRESHOLDS_WITH_180[1];

當(dāng)前屏幕旋轉(zhuǎn)方向?yàn)镽OTATION_270時(shí),取int[][] threshold=THRESHOLDS_WITH_180[2];

當(dāng)前屏幕旋轉(zhuǎn)方向?yàn)镽OTATION_180時(shí),取int[][] threshold=THRESHOLDS_WITH_180[3];

其中,threshold中的每一個(gè)元素由兩個(gè)值構(gòu)成,用來表示一個(gè)范圍。

WindowOrientationListener會(huì)注冊(cè)一個(gè)Accelerator類型的SensorEventListener,當(dāng)有新的SensorEvent產(chǎn)生時(shí),調(diào)用filterOrientation產(chǎn)生一個(gè)int orientation值。這個(gè)值會(huì)在threshold的各個(gè)元素表示的范圍中匹配,看會(huì)落在哪個(gè)范圍。假設(shè)當(dāng)前屏幕方向?yàn)镽OTATION_0,那么threshold={{60, 165}, {165, 195}, {195, 300}},假設(shè)這個(gè)時(shí)候把屏幕左側(cè)翻起90度。filterOrientation計(jì)算出的orientation值落在了第三個(gè)元素范圍內(nèi),那么去ROTATE_TO_WITH_180中尋找與它對(duì)應(yīng)的值,發(fā)現(xiàn)是ROTATION_270,那么就把當(dāng)前屏幕旋轉(zhuǎn)方向改變?yōu)?70度。threshold的取值就變成了THRESHOLDS_WITH_180[2]。當(dāng)把屏幕再次放平時(shí),filterOrientation計(jì)算出的orientation值會(huì)落在第一個(gè)元素表示的范圍內(nèi)。去ROTATE_TO_WITH_180中尋找與它對(duì)應(yīng)的值,發(fā)現(xiàn)是ROTATION_0,那么當(dāng)前屏幕旋轉(zhuǎn)方向被改變?yōu)?度。

還有一個(gè)變量比較重要,mAllow180Rotation,這個(gè)變量設(shè)置為false時(shí),就不使用THRESHOLDS_WITH_180和ROTATE_TO_WITH_180這一對(duì)數(shù)組來做上面這些變的了,就使用THRESHOLDS和ROTATE_TO。

其實(shí),我研究了半天也沒有搞清filterOrientation的算法以及THRESHOLDS_WITH_180和THRESHOLDS這兩個(gè)數(shù)組里面的每個(gè)數(shù)字代表的具體意義。最后只搞清了上面的這個(gè)流程,還有ROTATION_0, ROTATION_90, ROTATION_270, ROTATION_180這四個(gè)角度分別代表哪四個(gè)方向。但這足以應(yīng)付我們要做的事情了。

比如,我想讓屏幕最多只旋轉(zhuǎn)90度和180度,不讓它有旋轉(zhuǎn)270度的機(jī)會(huì)。那就把ROTATE_TO_WITH_180里面的ROTATION_270全部變成90度。這樣,應(yīng)該旋轉(zhuǎn)到270度時(shí),就會(huì)旋轉(zhuǎn)到90度了。如果不想讓屏幕旋轉(zhuǎn),把所有值都改成ROTATION_0就可以了。

再深入挖掘一下這個(gè)話題

PhonwWindowManager是唯一實(shí)現(xiàn)WindowOrientationListener接口的類,它管理著整個(gè)設(shè)備界面的顯示。當(dāng)PhonwWindowManager通過WindowOrientationListener知道屏幕方向發(fā)生旋轉(zhuǎn)時(shí),會(huì)告訴WindowManagerService:

mWindowManager.setRotation(rotation, false, mFancyRotationAnimation);

而WindowManagerService得到這個(gè)通知后,會(huì)做兩個(gè)比較重要的事情:

1、Surface.setOrientation(0, rotation, animFlags);

2、mRotationWatchers.get(i).onRotationChanged(rotation);

我們知道,每個(gè)Activity都有一個(gè)View樹,每個(gè)View樹都是繪畫在一個(gè)Surface上面的。通過上面這兩步,先把Surface給旋轉(zhuǎn)了,再告訴Activity重新繪制View樹,就完了整個(gè)屏幕的旋轉(zhuǎn)。

當(dāng)前文章:android旋轉(zhuǎn),Android旋轉(zhuǎn)框
轉(zhuǎn)載來于:http://jinyejixie.com/article14/dsecdge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、建站公司、電子商務(wù)、品牌網(wǎng)站制作、網(wǎng)站排名、動(dòng)態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司
班戈县| 隆林| 邢台县| 原阳县| 赫章县| 扎赉特旗| 宁夏| 叶城县| 东城区| 叶城县| 建德市| 依兰县| 罗城| 海口市| 永丰县| 云林县| 彩票| 咸宁市| 乐亭县| 大悟县| 河津市| 来宾市| 苍南县| 景东| 德州市| 邯郸县| 沽源县| 惠安县| 武穴市| 措勤县| 拉孜县| 珲春市| 咸阳市| 邮箱| 许昌市| 巴东县| 东兴市| 长垣县| 得荣县| 保靖县| 万安县|