水波紋效果:
公司主營業(yè)務:成都網(wǎng)站建設、網(wǎng)站設計、移動網(wǎng)站開發(fā)等業(yè)務。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)是一支青春激揚、勤奮敬業(yè)、活力青春激揚、勤奮敬業(yè)、活力澎湃、和諧高效的團隊。公司秉承以“開放、自由、嚴謹、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出達茂旗免費做網(wǎng)站回饋大家。
1.標準正余弦水波紋;
2.非標準圓形液柱水波紋;
雖說都是水波紋,但兩者在實現(xiàn)上差異是比較大的,一個通過正余弦函數(shù)模擬水波紋效果,另外一個會運用到圖像的混合模式(PorterDuffXfermode);
先看效果:
自定義View根據(jù)實際情況可以選擇繼承自View、TextView、ImageView或其他
這次的實現(xiàn)我們都選擇繼承view,在實現(xiàn)的過程中我們需要關注如下幾個方法:
1.onMeasure():最先回調,用于控件的測量;
2.onSizeChanged():在onMeasure后面回調,可以拿到view的寬高等數(shù)據(jù),在橫豎屏切換時也會回調;
3.onDraw():真正的繪制部分,繪制的代碼都寫到這里面;
既然如此,我們先復寫這三個方法,然后來實現(xiàn)如上兩個效果;
一:標準正余弦水波紋
這種水波紋可以用具體函數(shù)模擬出具體的軌跡,所以思路基本如下:
1.確定水波函數(shù)方程
2.根據(jù)函數(shù)方程得出每一個波紋上點的坐標;
3.將水波進行平移,即將水波上的點不斷的移動;
4.不斷的重新繪制,生成動態(tài)水波紋;
有了上面的思路,我們一步一步進行實現(xiàn):
正余弦函數(shù)方程為:
y?=?Asin(wx+b)+h?,這個公式里:w影響周期,A影響振幅,h影響y位置,b為初相;
根據(jù)上面的方程選取自己覺得中意的波紋效果,確定對應參數(shù)的取值;
然后根據(jù)確定好的方程得出所有的方程上y的數(shù)值,并將所有y值保存在數(shù)組里:
//?將周期定為view總寬度??
mCycleFactorW?=?(float)?(2?*?Math.PI?/?mTotalWidth);??
//?根據(jù)view總寬度得出所有對應的y值??
for?(int?i?=?0;?i??mTotalWidth;?i++)?{??
mYPositions[i]?=?(float)?(STRETCH_FACTOR_A?*?Math.sin(mCycleFactorW?*?i)?+?OFFSET_Y);??
}??
根據(jù)得出的所有y值,則可以在onDraw中通過如下代碼繪制兩條靜態(tài)波紋:
for?(int?i?=?0;?i??mTotalWidth;?i++)?{??
//?減400只是為了控制波紋繪制的y的在屏幕的位置,大家可以改成一個變量,然后動態(tài)改變這個變量,從而形成波紋上升下降效果??
//?繪制第一條水波紋??
canvas.drawLine(i,?mTotalHeight?-?mResetOneYPositions[i]?-?400,?i,??
mTotalHeight,??
mWavePaint);??
//?繪制第二條水波紋??
canvas.drawLine(i,?mTotalHeight?-?mResetTwoYPositions[i]?-?400,?i,??
mTotalHeight,??
mWavePaint);??
}??
這種方式類似于數(shù)學里面的細分法,一條波紋,如果橫向以一個像素點為單位進行細分,則形成view總寬度條直線,并且每條直線的起點和終點我們都能知道,在此基礎上我們只需要循環(huán)繪制出所有細分出來的直線(直線都是縱向的),則形成了一條靜態(tài)的水波紋;
接下來我們讓水波紋動起來,之前用了一個數(shù)組保存了所有的y值點,有兩條水波紋,再利用兩個同樣大小的數(shù)組來保存兩條波紋的y值數(shù)據(jù),并不斷的去改變這兩個數(shù)組中的數(shù)據(jù):
private?void?resetPositonY()?{??
//?mXOneOffset代表當前第一條水波紋要移動的距離??
int?yOneInterval?=?mYPositions.length?-?mXOneOffset;??
//?使用System.arraycopy方式重新填充第一條波紋的數(shù)據(jù)??
System.arraycopy(mYPositions,?mXOneOffset,?mResetOneYPositions,?0,?yOneInterval);??
System.arraycopy(mYPositions,?0,?mResetOneYPositions,?yOneInterval,?mXOneOffset);??
int?yTwoInterval?=?mYPositions.length?-?mXTwoOffset;??
System.arraycopy(mYPositions,?mXTwoOffset,?mResetTwoYPositions,?0,??
yTwoInterval);??
System.arraycopy(mYPositions,?0,?mResetTwoYPositions,?yTwoInterval,?mXTwoOffset);??
}??
如此下來只要不斷的改變這兩個數(shù)組的數(shù)據(jù),然后不斷刷新,即可生成動態(tài)水波紋了;
刷新可以調用invalidate()或postInvalidate(),區(qū)別在于后者可以在子線程中更新UI
整體代碼如下:
package?com.csdn.csdnblog2.ui;
import?com.csdn.csdnblog2.utils.UiUtils;
import?android.content.Context;
import?android.graphics.Canvas;
import?android.graphics.DrawFilter;
import?android.graphics.Paint;
import?android.graphics.Paint.Style;
import?android.graphics.PaintFlagsDrawFilter;
import?android.util.AttributeSet;
import?android.view.View;
public?class?DynamicWave?extends?View?{
//?波紋顏色
private?static?final?int?WAVE_PAINT_COLOR?=?0x880000aa;
//?y?=?Asin(wx+b)+h
private?static?final?float?STRETCH_FACTOR_A?=?20;
private?static?final?int?OFFSET_Y?=?0;
//?第一條水波移動速度
private?static?final?int?TRANSLATE_X_SPEED_ONE?=?7;
//?第二條水波移動速度
private?static?final?int?TRANSLATE_X_SPEED_TWO?=?5;
private?float?mCycleFactorW;
private?int?mTotalWidth,?mTotalHeight;
private?float[]?mYPositions;
private?float[]?mResetOneYPositions;
private?float[]?mResetTwoYPositions;
private?int?mXOffsetSpeedOne;
private?int?mXOffsetSpeedTwo;
private?int?mXOneOffset;
private?int?mXTwoOffset;
private?Paint?mWavePaint;
private?DrawFilter?mDrawFilter;
public?DynamicWave(Context?context,?AttributeSet?attrs)?{
super(context,?attrs);
//?將dp轉化為px,用于控制不同分辨率上移動速度基本一致
mXOffsetSpeedOne?=?UiUtils.dipToPx(context,?TRANSLATE_X_SPEED_ONE);
mXOffsetSpeedTwo?=?UiUtils.dipToPx(context,?TRANSLATE_X_SPEED_TWO);
//?初始繪制波紋的畫筆
mWavePaint?=?new?Paint();
//?去除畫筆鋸齒
mWavePaint.setAntiAlias(true);
//?設置風格為實線
mWavePaint.setStyle(Style.FILL);
//?設置畫筆顏色
mWavePaint.setColor(WAVE_PAINT_COLOR);
mDrawFilter?=?new?PaintFlagsDrawFilter(0,?Paint.ANTI_ALIAS_FLAG?|?Paint.FILTER_BITMAP_FLAG);
}
@Override
protected?void?onDraw(Canvas?canvas)?{
super.onDraw(canvas);
//?從canvas層面去除繪制時鋸齒
canvas.setDrawFilter(mDrawFilter);
resetPositonY();
for?(int?i?=?0;?i??mTotalWidth;?i++)?{
//?減400只是為了控制波紋繪制的y的在屏幕的位置,大家可以改成一個變量,然后動態(tài)改變這個變量,從而形成波紋上升下降效果
//?繪制第一條水波紋
canvas.drawLine(i,?mTotalHeight?-?mResetOneYPositions[i]?-?400,?i,
mTotalHeight,
mWavePaint);
//?繪制第二條水波紋
canvas.drawLine(i,?mTotalHeight?-?mResetTwoYPositions[i]?-?400,?i,
mTotalHeight,
mWavePaint);
}
//?改變兩條波紋的移動點
mXOneOffset?+=?mXOffsetSpeedOne;
mXTwoOffset?+=?mXOffsetSpeedTwo;
//?如果已經(jīng)移動到結尾處,則重頭記錄
if?(mXOneOffset?=?mTotalWidth)?{
mXOneOffset?=?0;
}
if?(mXTwoOffset??mTotalWidth)?{
mXTwoOffset?=?0;
}
//?引發(fā)view重繪,一般可以考慮延遲20-30ms重繪,空出時間片
postInvalidate();
}
private?void?resetPositonY()?{
//?mXOneOffset代表當前第一條水波紋要移動的距離
int?yOneInterval?=?mYPositions.length?-?mXOneOffset;
//?使用System.arraycopy方式重新填充第一條波紋的數(shù)據(jù)
System.arraycopy(mYPositions,?mXOneOffset,?mResetOneYPositions,?0,?yOneInterval);
System.arraycopy(mYPositions,?0,?mResetOneYPositions,?yOneInterval,?mXOneOffset);
int?yTwoInterval?=?mYPositions.length?-?mXTwoOffset;
System.arraycopy(mYPositions,?mXTwoOffset,?mResetTwoYPositions,?0,
yTwoInterval);
System.arraycopy(mYPositions,?0,?mResetTwoYPositions,?yTwoInterval,?mXTwoOffset);
}
@Override
protected?void?onSizeChanged(int?w,?int?h,?int?oldw,?int?oldh)?{
super.onSizeChanged(w,?h,?oldw,?oldh);
//?記錄下view的寬高
mTotalWidth?=?w;
mTotalHeight?=?h;
//?用于保存原始波紋的y值
mYPositions?=?new?float[mTotalWidth];
//?用于保存波紋一的y值
mResetOneYPositions?=?new?float[mTotalWidth];
//?用于保存波紋二的y值
mResetTwoYPositions?=?new?float[mTotalWidth];
//?將周期定為view總寬度
mCycleFactorW?=?(float)?(2?*?Math.PI?/?mTotalWidth);
//?根據(jù)view總寬度得出所有對應的y值
for?(int?i?=?0;?i??mTotalWidth;?i++)?{
mYPositions[i]?=?(float)?(STRETCH_FACTOR_A?*?Math.sin(mCycleFactorW?*?i)?+?OFFSET_Y);
}
}
}
二:非標準圓形液柱水波紋
前面的波形使用函數(shù)模擬,這個我們換種方式,采用圖進行實現(xiàn),先用PS整張不像波紋的波紋圖;
為了銜接緊密,首尾都比較平,并高度一致;
思路:
1.使用一個圓形圖作為遮罩過濾波形圖;
2.平移波紋圖,即不斷改變繪制的波紋圖的區(qū)域,即srcRect;
3.當一個周期繪制完,則從波紋圖的最前面重新計算;??
全部代碼如下
//?初始化bitmap
private?void?initBitmap()?{
mSrcBitmap?=?((BitmapDrawable)?getResources)
.getBitmap();
mMaskBitmap?=?((BitmapDrawable)?getResources().getDrawable(
R.drawable.circle_500))
.getBitmap();
}
//?初始化畫筆paint
private?void?initPaint()?{
mBitmapPaint?=?new?Paint();
//?防抖動
mBitmapPaint.setDither(true);
//?開啟圖像過濾
mBitmapPaint.setFilterBitmap(true);
mPicPaint?=?new?Paint(Paint.ANTI_ALIAS_FLAG);
mPicPaint.setDither(true);
mPicPaint.setColor(Color.RED);
}
@Override
protected?void?onSizeChanged(int?w,?int?h,?int?oldw,?int?oldh)?{
super.onSizeChanged(w,?h,?oldw,?oldh);
mTotalWidth?=?w;
mTotalHeight?=?h;
mCenterX?=?mTotalWidth?/?2;
mCenterY?=?mTotalHeight?/?2;
mSrcRect?=?new?Rect();
mDestRect?=?new?Rect(0,?0,?mTotalWidth,?mTotalHeight);
int?maskWidth?=?mMaskBitmap.getWidth();
int?maskHeight?=?mMaskBitmap.getHeight();
mMaskSrcRect?=?new?Rect(0,?0,?maskWidth,?maskHeight);
mMaskDestRect?=?new?Rect(0,?0,?mTotalWidth,?mTotalHeight);
}
}
某個方法沒被用到,就會變?yōu)榛疑?,且?guī)в胁ɡ司€。 方法名字不符合英文命名標準,比如DeDao()的方法,去掉的方法就是用個英文單詞代替
要確定你的MainActivity是存在包名那個路徑下嗎,前面那個“點”的意思就是省略了包名
恰恰相反,是你的JDK版本太高,Android要求java編譯器(也是javac, java)版本為5.0,或6.0(其實也就是1.5或1.6)。
還有一點需要知道的是,接口實現(xiàn)的時候,在方法名前加@Override,只是JDK版本在1.6及以上才可用。
所以,綜上所述,你應該選擇JDK 1.6,方法如下:
Eclipe 中點擊Windows-Preference-Java-Compiler
在Compiler Compliance level中選擇1.6
當然,前提是你已經(jīng)安裝了JDK 1.6
1、點擊 File – Settings
2、在?Settings?中左邊的搜索框輸入?inspection?選中后再右邊的輸入框中輸入?typo
可以看到下方? typo ?選項中的勾號,把它去掉就可以取消掉? typo ?的波浪線提示了