在android 中。有各種各樣的drawable。其中,比較常用的drawable有一個LayerDrawable,對應的xml標簽為layerlist。里面可以按照先后順序,放置一個個i的item。就像這樣:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item >
<shape android:shape="rectangle">
<solid android:color="#ff8800"></solid>
</shape>
</item>
<item >
<shape android:shape="oval">
<solid android:color="#ff0088"></solid>
<corners android:radius="5px"/>
</shape>
</item>
</layer-list>
然后以它為background 應用到view上面,以textview為例,得到的結果是這樣。
這里我設置了textview的寬度與高度都相等,所以顯示出了一個正方形里面套了一個圓形。如果寬高改為自適應的話就是長方形加橢圓了。
下面開始說明我要討論的重點。之前看到過幾篇博客,為了實現提示引導信息,要展示一個提示框,里面還有個小三角形的小尾巴。大概是這個樣子。
這里主要用了layerlist實現了下面那個三角形,然后讓這個三角形相對上面的textview做相應的偏移,就達到了以上的效果。其實實現這個效果的方法還有許多種,如.9圖片,或者干脆做一個普通的圖片,或者通過canvas在畫布上面繪制一個Path等。這里咱們就說說用相對簡單有效的layerlist怎么實現,以及實現它的原理。
上面的三角形實現部分代碼如下。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate android:pivotX="135%"
android:pivotY="15%"
android:fromDegrees="45">
<shape android:shape="rectangle">
<solid android:color="#ff8800"></solid>
</shape>
</rotate>
</item>
</layer-list>
在這里,你看到了layerlist標簽下面只有一個item,沒錯,因為實現這個效果沒有用到層疊。只用一個rotate標簽做了旋轉操作,里面包裹了一個shape標簽,這個shape標簽是一個矩形類型的。
我們觀察rotate標簽的其他幾個屬性。感覺到這幾個屬性莫名其妙。但是確實實現了由矩形旋轉成為三角形的效果。為了能弄清問題,我先解釋一下具體屬性的意思,pivotX,旋轉中心的x坐標,用百分比表示,原點在左上角,總的寬高都由具體的view決定。pivotY,旋轉中心的y坐標。fromDegrees,要旋轉的角度。這里應該注意,相對應的有個toDegree,不過這里用不上。因為這兩個屬性都是在rotate animation里面能夠用上,設置開始旋轉的角度,結束旋轉的角度,這里,咱們的layerlist是靜態的,所以只取得fromDegree就夠了,后面跟上要旋轉的角度,整數就按照Direction.CW旋轉,也就是順時針旋轉,負數就按照Direction.CCW逆時針旋轉。
下面印證一下我們的觀點,
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="45">
<shape android:shape="rectangle">
<solid android:color="#ff8800"></solid>
</shape>
</rotate>
</item>
</layer-list>
將旋轉中心設置為自己的寬高中心點,由此順時針旋轉45度。將會得到一個這樣的圖形。
為什么會得到一個正八邊形呢?乍一看感覺理解不透,可仔細一想,這不是旋轉以后被正方形邊界給截取了么?截取了旋轉后正方形的四個角,我們看不見邊界外面了。不就成了正八邊形了么?(其實他是有邊界的,邊界就是你給這個view指定的寬高所圍成的正方形。)
這里我們清楚了原理,下面我們就按照我們的要求對矩形做旋轉吧!要知道,旋轉中心也有可能在矩形之外哦,就比如最開始那個倒置的三角形。它的旋轉中心超過了它自己的范圍。為了達到更好的展示效果,我們用canvas把邊框還有旋轉中心畫出來,讓我們有更直觀的認識。
自定義一個view復寫onDraw方法,下面只展示onDraw方法里面的代碼。
1,寬高充滿全屏,translate canvas 畫布圓點。使畫出的內容盡量在中間。
2,畫出一個寬高都為300像素的正方形。
3,再用同樣的矩形畫在新建的空bitmap上面。然后用Matrix繞旋轉中心旋轉這個矩形,模擬最開始的,旋轉中心,x坐標3001.35=405,y坐標 3000.15=45。順時針旋轉45度。
4,將這個旋轉過后的bitmap畫到畫布上面看效果。用到
canvas.drawBitmap(bitmap,matrix,null),最后一個paint參數這里沒有用,可傳空。
canvas.translate(500,300);
Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setColor(Color.rgb(0xff,00,00));
canvas.drawRect(0,0,300,300,paint);
Bitmap bitmap=Bitmap.createBitmap(300,300,Bitmap.Config.ARGB_8888);
Canvas bc=new Canvas(bitmap);
paint.setColor(Color.rgb(0x00,0x55,00));
bc.drawRect(0,0,300,300,paint);
Matrix matrix=new Matrix();
matrix.setRotate(45,405,45);
canvas.drawBitmap(bitmap,matrix,null);
paint.setStrokeWidth(10);
canvas.drawPoint(405,45,paint);
paint.setStrokeWidth(1);
paint.setTextSize(30);
canvas.drawText("(405,45) 旋轉中心,旋轉度數 CW 45度",405,45,paint);
canvas.drawText("(0,0) 原點",0,0,paint);
上面的代碼不難理解,運行后得到下面的效果。
看到結果,紅的的正方形,繞着旋轉中新(405,45)順時針旋轉了45度后,恰到好處的成了一個被紅色矩形截取得到的我們想要的三角形。
最后補充一下。我們知道,旋轉一個圖片,無非就是一個圖形的所有點繞着旋轉中心畫圓弧。如下圖,旋轉中心圖示:
所以,知道了旋轉開始位置,旋轉結束位置,這樣就變成了求旋轉中心的坐標。也就是在前后圖片上各區對應的兩個點,連接,作垂線。相交的那個點。