本系列是為新手準備的自定義view練習項目(大牛請無視),相信在學習過程中,想學自定義view又無從下手,不知道做什么。本系列為新手提供了一系列自定義view的簡單實例。看過理解之后,自己實現,相信會有很大提高。
轉載請注明本篇出處:http://blog.csdn.net/wingichoy/article/details/50460213
繼續來本系列的第二篇,啟發是吃口香糖看到了包裝紙,覺得挺好看,就想畫一個出來#職業病#,本次的目標是做一個波浪形狀的view,可以是尖角,也可以是圓角。
那么老規矩,上效果圖:

聰明的你一眼就看出來了,不就是個矩形加好多三角嘛。答對了,就是這么簡單,事不宜遲,快拿起武器動手練一練。畢竟程序員的秘訣就是“無他,唯手熟爾”。
首先,新建一個類 起名為WaveView 繼承自View,重寫他的構造方法,在第三個構造方法里獲取自定義屬性。
~~~
public WaveView(Context context) {
this(context, null);
}
public WaveView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.WaveView,defStyleAttr,0);
mWaveCount = a.getInt(R.styleable.WaveView_waveCount,10);
mWaveWidth = a.getInt(R.styleable.WaveView_waveWidth,20);
mMode = a.getInteger(R.styleable.WaveView_mode,-2);
mColor = a.getColor(R.styleable.WaveView_android_color,Color.parseColor("#2C97DE"));
}
~~~
自定義屬性如下 attr.xml:
~~~
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="WaveView">
<attr name="waveCount" format="integer"/>
<attr name="waveWidth" format="integer"/>
<attr name="android:color"/>
<attr name="mode" >
<enum name = "circle" value="-1"/>
<enum name = "triangle" value = "-2"/>
</attr>
</declare-styleable>
</resources>
~~~
這些都沒有什么好說的,你一定已經輕車熟路。
然后重寫他的onMeasure() ?來告訴系統這個view有多大。
~~~
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//矩形寬度為view的80%
if (widthMode == MeasureSpec.EXACTLY) {
mWidth = widthSize;
mRectWidth = (float) (mWidth * 0.8);
//如果是wrap_content 直接給一個定值
}else if(widthMode == MeasureSpec.AT_MOST){
mWidth = PxUtils.dpToPx(300,mContext);
mRectWidth = (float) (mWidth * 0.8);
}
//矩形高度為view的80%
if (heightMode == MeasureSpec.EXACTLY) {
mHeight = heightSize;
mRectHeight = (float) (mHeight * 0.8);
//如果是wrap_content 直接給一個定值
}else if(heightMode == MeasureSpec.AT_MOST){
mHeight = PxUtils.dpToPx(200,mContext);
mRectHeight = (float) (mHeight * 0.8);
}
setMeasuredDimension(mWidth, mHeight);
}
~~~
準備工作大致已經完成,接下來開始繪圖。首先 畫一個矩形。
這個矩形讓他處于view的中間,看圖:

由圖可知, 矩形的左上坐標為 padding ,padding 矩形的右下坐標為padding +mRectWidth, padding + mRectHeight?
其中padding 為 (mWidth - mRectWidth)/2 ? 注意這里只是左右padding 為了簡易 就不計算上下padding了。
所以我們先將矩形繪制出來,如下圖: ? 可以看到左右padding是相等的,上下不等,這是因為上面只計算了左右padding

~~~
protected void onDraw(Canvas canvas) {
Paint p = new Paint();
p.setColor(mColor);
//計算每個三角形的高
mWaveHeight = mRectHeight / mWaveCount;
//繪制矩形
//計算padding
float padding = ((mWidth - mRectWidth) / 2);
canvas.drawRect(padding, padding, mRectWidth + padding, mRectHeight + padding, p);
~~~
繪制矩形完畢,需要來一個判斷,判斷當前模式是圓角還是尖角
~~~
if(mMode == MODE_TRIANGLE) {}else{}
~~~
我們首先來繪制尖角,還記得上一篇泡泡窗的那個三角嗎,我們只要畫多次不就形成波浪了嗎,所以用循環就可以搞定。坐標計算如下:

矩形的右上角暫定為 StartX,StartY ? ?三角形的寬度為 mWaveWidth ?高度為 mWaveHeight ?那么還是用path來畫,首先將path MoveTo startX,startY 然后計算得出各個坐標,在用一個i來代表第幾個三角形來做循環,代碼如下:
~~~
if(mMode == MODE_TRIANGLE) {
//繪制右邊的波浪
float startX = padding + mRectWidth;
float startY = padding;
Path path = new Path();
path.moveTo(startX, startY);
for (int i = 0; i < mWaveCount; i++) {
path.lineTo(startX + mWaveWidth, startY + i * mWaveHeight + (mWaveHeight / 2));
path.lineTo(startX, startY + mWaveHeight * (i + 1));
}
path.close();
canvas.drawPath(path, p);
~~~
只要把上面的坐標帶入進去即可,那么左邊的波浪只是改變了一個x坐標的加減值,也很簡單。
~~~
//繪制左邊的波浪
startX = padding;
startY = padding;
path.moveTo(startX, startY);
for (int i = 0; i < mWaveCount; i++) {
path.lineTo(startX - mWaveWidth, startY + i * mWaveHeight + (mWaveHeight / 2));
path.lineTo(startX, startY + mWaveHeight * (i + 1));
}
path.close();
canvas.drawPath(path, p);
~~~
這樣便完成了整個波浪view的繪制。本篇就到此結束了。
別急,我沒忘圓形模式,這里給大家留個家庭作業,大家下去根據這個思路自己把圓形波浪畫出來吧~ 畢竟只有多練,才能提高
本項目github地址:[點擊打開鏈接](https://github.com/githubwing/WaveView)?,求關注,求評論,求star
- 前言
- android自定義viewgroup初步之一----抽屜菜單
- Android 自定義view --圓形百分比(進度條)
- Android 自定義View -- 簡約的折線圖
- 新手自定義view練習實例之(一) 泡泡彈窗
- 新手自定義view練習實例之(二) 波浪view
- 手把手帶你畫一個 時尚儀表盤 Android 自定義View
- 手把手帶你畫一個動態錯誤提示 Android自定義view
- 手把手帶你做一個超炫酷loading成功動畫view Android自定義view
- 關于Android自定義view 你所需要知道的基本函數
- Android自定義view進階-- 神奇的貝塞爾曲線
- wing帶你玩轉自定義view系列(1) 仿360內存清理效果
- wing帶你玩轉自定義view系列(2) 簡單模仿qq未讀消息去除效果
- wing帶你玩轉自定義view系列(3)模仿微信下拉眼睛
- 手把手教你畫一個 逼格滿滿圓形水波紋loadingview Android
- 有坑?? 為何wing墜入PorterDuffXferMode的萬丈深淵(PorterDuffXferMode深入試驗)
- 手把手帶你畫一個漂亮蜂窩view Android自定義view
- 一個炫字都不夠??!!!手把手帶你打造3D自定義view
- 恭喜發財! -- 手把手教你仿造一個qq下拉搶紅包 Android自定義view