- 一 - 水波纹过渡特效(首页)
- 二 - ViewPager 渲染背景颜色渐变(引导页)
- 三 - 自定义不一样的 Toast
- 四 - APP 主页框架 TabHost 绑定 ViewPager 的替换者 TabLayout
- 五 - 自定义圆形头像和仿 MIUI 卸载动画 - 粒子爆炸
- 六 - 仿 QQ 聊天撒花特效,无形装逼,最为致命
- 七 - 飞机升空特效,一键清理缓存,灵活运用动画会有不一样的感受
- 八 - 实现心型起泡飞舞的特效,让你的 APP 瞬间暖心
- 九 - 仿微信雷达搜索好友特效,逻辑清晰实现简单
- 十 - 点击水波纹效果实现,逻辑清晰实现简单
- 十一 - 仿水波纹流量球进度条控制器,实现高端大气的主流特效
- 十二 - 仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的 View
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
一 - 水波纹过渡特效(首页)
也是今天看到的一个特效,感觉挺漂亮的,最近也一直在筹划一个 APP,就想把他当做 APP 的首页,然后加些处理,关于首页 APP 的特效等我完工了再贴出来吧,现在先把这个特效给分享出来,只是稍微改动了一点点而已。
先看效果图:
我们先创建一个 UIUtils,转换一些单位
package com.lgl.test;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;
public class UiUtils {
static public int getScreenWidthPixels(Context context) {
DisplayMetrics dm = new DisplayMetrics();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
.getMetrics(dm);
return dm.widthPixels;
}
static public int dipToPx(Context context, int dip) {
return (int) (dip * getScreenDensity(context) + 0.5f);
}
static public float getScreenDensity(Context context) {
try {
DisplayMetrics dm = new DisplayMetrics();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
.getMetrics(dm);
return dm.density;
} catch (Exception e) {
return DisplayMetrics.DENSITY_DEFAULT;
}
}
}
然后写一个 WaterRippleView 类继承 View
package com.lgl.test;
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 WaterRippleView 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 WaterRippleView(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 的在屏幕的位置,大家可以改成一个变量,然后动态改变这个变量,从而形成波纹上升下降效果
// 绘制第一条水波纹
canvas.drawLine(i, mTotalHeight - mResetOneYPositions[i] - 400, i,
mTotalHeight, mWavePaint);
// 绘制第二条水波纹
canvas.drawLine(i, mTotalHeight - mResetTwoYPositions[i] - 400, i,
mTotalHeight, mWavePaint);
}
// 改变两条波纹的移动点
mXOneOffset += mXOffsetSpeedOne;
mXTwoOffset += mXOffsetSpeedTwo;
// 如果已经移动到结尾处,则重头记录
if (mXOneOffset >= mTotalWidth) {
mXOneOffset = 0;
}
if (mXTwoOffset > mTotalWidth) {
mXTwoOffset = 0;
}
// 引发 view 重绘,一般可以考虑延迟 20-30ms 重绘,空出时间片
postInvalidate();
}
private void resetPositonY() {
// mXOneOffset 代表当前第一条水波纹要移动的距离
int yOneInterval = mYPositions.length - mXOneOffset;
// 使用 System.arraycopy 方式重新填充第一条波纹的数据
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);
// 根据 view 总宽度得出所有对应的 y 值
for (int i = 0; i < mTotalWidth; i++) {
mYPositions[i] = (float) (STRETCH_FACTOR_A
* Math.sin(mCycleFactorW * i) + OFFSET_Y);
}
}
}
然后你就可以绑定在布局上就可以使用了
<com.lgl.test.WaterRippleView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
是不是感觉特效还可以
Demo 下载地址: http://download.csdn.net/detail/qq_26787115/9384803
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论