水波效果
2016-01-10 17:57
411 查看
一、水波外扩
资料来源:http://blog.csdn.net/shineflowers/article/details/47280545布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/wave1" android:layout_width="150dp" android:layout_height="150dp" android:layout_centerInParent="true" android:background="@drawable/wateout_wave" /> <ImageView android:id="@+id/wave2" android:layout_width="150dp" android:layout_height="150dp" android:layout_centerInParent="true" android:background="@drawable/wateout_wave"/> <ImageView android:id="@+id/wave3" android:layout_width="150dp" android:layout_height="150dp" android:layout_centerInParent="true" android:background="@drawable/wateout_wave" /> <ImageView android:id="@+id/btnVoice" android:layout_width="166dp" android:layout_height="166dp" android:layout_centerInParent="true" android:background="@drawable/wateout_voice" /> </RelativeLayout>
源码:
package com.example.administrator.wavetest; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.ScaleAnimation; import android.widget.ImageView; public class WaveOutActivity extends AppCompatActivity { private ImageView mNormal; private ImageView mWave1; private ImageView mWave2; private ImageView mWave3; private AnimationSet mAnimationSet1; private AnimationSet mAnimationSet2; private AnimationSet mAnimationSet3; private static final int OFFSET = 600; //每个动画的播放时间间隔 private static final int MSG_WAVE2_ANIMATION = 2; private static final int MSG_WAVE3_ANIMATION = 3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wave_out); mNormal = (ImageView) findViewById(R.id.btnVoice); mWave1 = (ImageView) findViewById(R.id.wave1); mWave2 = (ImageView) findViewById(R.id.wave2); mWave3 = (ImageView) findViewById(R.id.wave3); mAnimationSet1 = initAnimationSet(); mAnimationSet2 = initAnimationSet(); mAnimationSet3 = initAnimationSet(); mNormal.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: showWaveAnimation(); break; case MotionEvent.ACTION_UP: clearWaveAnimation(); break; case MotionEvent.ACTION_CANCEL: clearWaveAnimation(); } return true; } }); } private AnimationSet initAnimationSet() { //AnimationSet提供了一个把多个动画组合成一个组合的机制 //并可设置组中动画的时序关系,如同时播放,顺序播放等 AnimationSet as = new AnimationSet(true); //缩放动画效果 ScaleAnimation sa = new ScaleAnimation( 1f //动画起始时 X坐标上的伸缩尺寸 , 2.3f //动画结束时 X坐标上的伸缩尺寸 , 1f //动画起始时Y坐标上的伸缩尺寸 , 2.3f //动画结束时Y坐标上的伸缩尺寸 , ScaleAnimation.RELATIVE_TO_SELF //动画在X轴相对于物件位置类型:相对于自身 , 0.5f //动画相对于物件的X坐标的开始位置 , ScaleAnimation.RELATIVE_TO_SELF //动画在Y轴相对于物件位置类型:相对于自身 , 0.5f //动画相对于物件的Y坐标的开始位置 ); sa.setDuration(OFFSET * 3);//设置动画持续时间 sa.setRepeatCount(Animation.INFINITE);// 设置循环 //透明度动画效果 AlphaAnimation aa = new AlphaAnimation( 1 //动画起始时 透明度 , 0.1f //动画结束时 透明度 ); aa.setDuration(OFFSET * 3);//设置动画持续时间 aa.setRepeatCount(Animation.INFINITE);//设置循环 as.addAnimation(sa); as.addAnimation(aa); return as; } private void showWaveAnimation() { //启动动画 mWave1.startAnimation(mAnimationSet1); //一定延时后启动动画2、3 mHandler.sendEmptyMessageDelayed(MSG_WAVE2_ANIMATION, OFFSET); mHandler.sendEmptyMessageDelayed(MSG_WAVE3_ANIMATION, OFFSET * 2); } private void clearWaveAnimation() { //结束动画 mWave1.clearAnimation(); mWave2.clearAnimation(); mWave3.clearAnimation(); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_WAVE2_ANIMATION: mWave2.startAnimation(mAnimationSet2); break; case MSG_WAVE3_ANIMATION: mWave3.startAnimation(mAnimationSet3); break; } } }; }
二、正弦水波
资料来源:http://blog.csdn.net/tianjian4592/article/details/44222565源码:
package com.example.administrator.wavetest.View; import android.content.Context; import android.graphics.Canvas; import android.graphics.DrawFilter; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.util.AttributeSet; import android.view.View; import com.example.administrator.wavetest.utils.UiUtils; /** * Created by Administrator on 2016/1/8. */ public class DynamicWave extends View { // 波纹颜色 private static final int WAVE_PAINT_COLOR = 0x880000aa; // 第一条水波移动速度 private int TRANSLATE_X_SPEED_ONE = 7; // 第二条水波移动速度 private int TRANSLATE_X_SPEED_TWO = 5; // y = Asin(wx + b) + h private float STRETCH_FACTOR_A = 20; private int OFFSET_Y = 0; //周期 private float mCycleFactorW; private int mTotalWidth; private int mTotalHeight; //水波高度 private int mWaveHeight = 400; //重绘间隔时间 private int ViewTimer = 100; 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; private Context mContext; public DynamicWave(Context context, AttributeSet attrs){ super(context, attrs); mContext = context; // 将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(Paint.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] - mWaveHeight, i, mTotalHeight, mWavePaint); // 绘制第二条水波纹 canvas.drawLine(i, mTotalHeight - mResetTwoYPositions[i] - mWaveHeight, i, mTotalHeight, mWavePaint); } // 改变两条波纹的移动点 mXOneOffset += mXOffsetSpeedOne; mXTwoOffset += mXOffsetSpeedTwo; // 如果已经移动到结尾处,则重头记录 if (mXOneOffset >= mTotalWidth) { mXOneOffset = 0; } if (mXTwoOffset > mTotalWidth) { mXTwoOffset = 0; } // 引发view重绘,一般可以考虑延迟20-30ms重绘,空出时间片 postInvalidateDelayed(ViewTimer); //postInvalidate(); } @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); initData(); } private void initData(){ // 根据view总宽度得出所有对应的y值 y = Asin(wx+b)+h for (int i = 0; i < mTotalWidth; i++) { mYPositions[i] = (float) (STRETCH_FACTOR_A * Math.sin(mCycleFactorW * i) + OFFSET_Y); } } 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); } public void setTRANSLATE_X_SPEED_ONE(int speed){ TRANSLATE_X_SPEED_ONE = speed; mXOffsetSpeedOne = UiUtils.dipToPx(mContext, TRANSLATE_X_SPEED_ONE); } public void setTRANSLATE_X_SPEED_TWO(int speed){ TRANSLATE_X_SPEED_TWO = speed; mXOffsetSpeedTwo = UiUtils.dipToPx(mContext, TRANSLATE_X_SPEED_TWO); } public void setWaveheight(int height){ mWaveHeight = height; } public void setViewTimer(int time){ ViewTimer = time; } public void setSTRETCH_FACTOR_A(int a){ STRETCH_FACTOR_A = a; initData(); } public void setOFFSET_Y(int y){ OFFSET_Y = y; initData(); } }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories