android 水纹上涨与水滴滴下效果

这两天项目比较紧,本来打算完成以后再写博客的,今天终于实现了一个炫的功能,怀着激动的心情,趁热打铁,把项目经验记录一下,效果图如下: 
这里写图片描述 
对功能的几点说明: 
1.圆形边框旋转 
2.水纹上涨 
3.水滴滴下 
4.方向始终朝向重力 
先分析一下思路,首先旋转比较好实现,只需要旋转动画就可以了,第二个水纹效果,参考了一篇博客,http://www.jianshu.com/p/e711e22e053e 
在源码基础上进行了修改。第三个水滴滴下效果,参考了这个源码: https://github.com/recruit-lifestyle/WaveSwipeRefreshLayout 
并且根据功能在源码基础上进行了修改,第四个方向始终朝向重力方向,需要判断重力方向,然后根据角度旋转图片,感谢这篇博客,里边角度的换算非常有用, http://www.cnblogs.com/bpasser/archive/2011/10/17/2214517.html 
现在就一步一步实现这个功能吧

布局文件

现在先把这块功能的布局文件贴上,所有操作都在这个布局上进行。


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="3"
        android:gravity="center"
        android:orientation="vertical">

        <FrameLayout
            android:id="@+id/id_framelayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:background="@mipmap/wave_default">

            <ImageView
                android:id="@+id/id_imageRota"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="@mipmap/wave_1" />
            <jp.co.recruit_lifestyle.android.widget.WaveSwipeRefreshLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/main_swipe"
                android:layout_gravity="center"
                >
                <View
                    android:layout_width="1dp"
                    android:layout_height="1dp"
                    />
            </jp.co.recruit_lifestyle.android.widget.WaveSwipeRefreshLayout>
                <com.gelitenight.waveview.library.WaveView
                    android:id="@+id/wave"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center" />



            <TextView
                android:id="@+id/id_textViewProgress"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:textSize="40sp"
                android:textColor="#5aa828"
                android:textStyle="bold"/>
        </FrameLayout>
    </LinearLayout>

先解释一下布局,两张图片:wave_default, 
wave_1 
这里写图片描述 
首先使用FrameLayout布局,将两个图片重叠,对wave_1进行旋转操作,实现动画。WaveSwipeRefreshLayout控件是水滴效果,因为不允许布局内为空,所以设置一个view,WaveView则是水滴效果,id_textViewProgress是水滴上写的进度数字,说明一下,这里都写成自适应的,wrap_content,具体宽高则在代码中进行控制。

旋转图片的实现

这个比较简单,只需要给view进行旋转动画的操作就可以了,贴一下这部分功能的代码

 final RotateAnimation ra = new RotateAnimation(0, 359, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        ra.setDuration(1000);
        ra.setRepeatCount(-1);
        //匀速
        LinearInterpolator lin = new LinearInterpolator();
        ra.setInterpolator(lin);
        imageViewRota.startAnimation(ra);

我这里设置了匀速旋转

水波效果的实现

这个需要导入第三方库,导入方法我就不说了,然后在源代码基础上进行修改,具体的效果是这样的,这里写图片描述颜色和透明度之类的,在源代码中进行修改,修改的部分比较多,我把修改后的源码贴一下

public class WaveView extends View {
    /**
     * +------------------------+
     * |<--wave length->        |______
     * |   /          |   /   |  |
     * |  /           |  /    | amplitude
     * | /            | /     |  |
     * |/             |/      |__|____
     * |              /        |  |
     * |             /         |  |
     * |            /          |  |
     * |           /           | water level
     * |                        |  |
     * |                        |  |
     * +------------------------+__|____
     */
    private static final float DEFAULT_AMPLITUDE_RATIO = 0.05f;
    private static final float DEFAULT_WATER_LEVEL_RATIO = 0.5f;
    private static final float DEFAULT_WAVE_LENGTH_RATIO = 1.0f;
    private static final float DEFAULT_WAVE_SHIFT_RATIO = 0.0f;

    public static final int DEFAULT_BEHIND_WAVE_COLOR = Color.parseColor("#addef8");
    public static final int DEFAULT_FRONT_WAVE_COLOR = Color.parseColor("#addef8");
    public static final ShapeType DEFAULT_WAVE_SHAPE = ShapeType.CIRCLE;

    public enum ShapeType {
        CIRCLE,
        SQUARE
    }

    // if true, the shader will display the wave
    private boolean mShowWave;

    // shader containing repeated waves
    private BitmapShader mWaveShader;
    // shader matrix
    private Matrix mShaderMatrix;
    // paint to draw wave
    private Paint mViewPaint;
    // paint to draw border
    private Paint mBorderPaint;

    private float mDefaultAmplitude;
    private float mDefaultWaterLevel;
    private float mDefaultWaveLength;
    private double mDefaultAngularFrequency;

    private float mAmplitudeRatio = DEFAULT_AMPLITUDE_RATIO;
    private float mWaveLengthRatio = DEFAULT_WAVE_LENGTH_RATIO;
    private float mWaterLevelRatio = DEFAULT_WATER_LEVEL_RATIO;
    private float mWaveShiftRatio = DEFAULT_WAVE_SHIFT_RATIO;

    private int mBehindWaveColor = DEFAULT_BEHIND_WAVE_COLOR;
    private int mFrontWaveColor = DEFAULT_FRONT_WAVE_COLOR;
    private ShapeType mShapeType = DEFAULT_WAVE_SHAPE;

    public WaveView(Context context) {
        super(context);
        init();
    }

    public WaveView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public WaveView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        mShaderMatrix = new Matrix();
        mViewPaint = new Paint();
        mViewPaint.setAntiAlias(true);
    }

    public float getWaveShiftRatio() {
        return mWaveShiftRatio;
    }

    /**
     * Shift the wave horizontally according to <code>waveShiftRatio</code>.
     *
     * @param waveShiftRatio Should be 0 ~ 1. Default to be 0.
     *                       <br/>Result of waveShiftRatio multiples width of WaveView is the length to shift.
     */
    public void setWaveShiftRatio(float waveShiftRatio) {
        if (mWaveShiftRatio != waveShiftRatio) {
            mWaveShiftRatio = waveShiftRatio;
            invalidate();
        }
    }

    public float getWaterLevelRatio() {
        return mWaterLevelRatio;
    }

    /**
     * Set water level according to <code>waterLevelRatio</code>.
     *
     * @param waterLevelRatio Should be 0 ~ 1. Default to be 0.5.
     *                        <br/>Ratio of water level to WaveView height.
     */
    public void setWaterLevelRatio(float waterLevelRatio){

        if (mWaterLevelRatio != waterLevelRatio) {
            mWaterLevelRatio = waterLevelRatio;
            invalidate();
        }
    }

    public float getAmplitudeRatio() {
        return mAmplitudeRatio;
    }

    /**
     * Set vertical size of wave according to <code>amplitudeRatio</code>
     *
     * @param amplitudeRatio Default to be 0.05. Result of amplitudeRatio + waterLevelRatio should be less than 1.
     *                       <br/>Ratio of amplitude to height of WaveView.
     */
    public void setAmplitudeRatio(float amplitudeRatio) {
        if (mAmplitudeRatio != amplitudeRatio) {
            mAmplitudeRatio = amplitudeRatio;
            invalidate();
        }
    }

    public float getWaveLengthRatio() {
        return mWaveLengthRatio;
    }

    /**
     * Set horizontal size of wave according to <code>waveLengthRatio</code>
     *
     * @param waveLengthRatio Default to be 1.
     *                        <br/>Ratio of wave length to width of WaveView.
     */
    public void setWaveLengthRatio(float waveLengthRatio) {
        mWaveLengthRatio = waveLengthRatio;
    }

    public boolean isShowWave() {
        return mShowWave;
    }

    public void setShowWave(boolean showWave) {
        mShowWave = showWave;
    }

    public void setBorder(int width, int color) {
        if (mBorderPaint == null) {
            mBorderPaint = new Paint();
            mBorderPaint.setAntiAlias(true);
            mBorderPaint.setStyle(Style.STROKE);
        }
        mBorderPaint.setColor(color);
        mBorderPaint.setStrokeWidth(width);

        invalidate();
    }

    public void setWaveColor(int behindWaveColor, int frontWaveColor) {
        mBehindWaveColor = behindWaveColor;
        mFrontWaveColor = frontWaveColor;

        // need to recreate shader when color changed
        mWaveShader = null;
        createShader();
        invalidate();
    }

    public void setShapeType(ShapeType shapeType) {
        mShapeType = shapeType;
        invalidate();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        createShader();
    }

    /**
     * Create the shader with default waves which repeat horizontally, and clamp vertically
     */
    private void createShader() {
        mDefaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / getWidth();
        mDefaultAmplitude = getHeight() * DEFAULT_AMPLITUDE_RATIO;
        mDefaultWaterLevel = getHeight() * DEFAULT_WATER_LEVEL_RATIO;
        mDefaultWaveLength = getWidth();

        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);

        Paint wavePaint = new Paint();
        wavePaint.setStrokeWidth(2);
        wavePaint.setAntiAlias(true);
        wavePaint.setAlpha(178);
        // Draw default waves into the bitmap
        // y=Asin(ωx+φ)+h
        final int endX = getWidth() + 1;
        final int endY = getHeight() + 1;

        float[] waveY = new float[endX];

        wavePaint.setColor(mBehindWaveColor);
        wavePaint.setAlpha(127);
        for (int beginX = 0; beginX < endX; beginX++) {
            double wx = beginX * mDefaultAngularFrequency;
            float beginY = (float) (mDefaultWaterLevel + mDefaultAmplitude * Math.sin(wx));
            canvas.drawLine(beginX, beginY, beginX, endY, wavePaint);

            waveY[beginX] = beginY;
        }

        wavePaint.setColor(mFrontWaveColor);
        final int wave2Shift = (int) (mDefaultWaveLength / 4);
        for (int beginX = 0; beginX < endX; beginX++) {
            canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint);
        }

        // use the bitamp to create the shader
        mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        mViewPaint.setShader(mWaveShader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // modify paint shader according to mShowWave state
        if (mShowWave && mWaveShader != null) {
            // first call after mShowWave, assign it to our paint
            if (mViewPaint.getShader() == null) {
                mViewPaint.setShader(mWaveShader);
            }

            // sacle shader according to mWaveLengthRatio and mAmplitudeRatio
            // this decides the size(mWaveLengthRatio for width, mAmplitudeRatio for height) of waves
            mShaderMatrix.setScale(
                mWaveLengthRatio / DEFAULT_WAVE_LENGTH_RATIO,
                mAmplitudeRatio / DEFAULT_AMPLITUDE_RATIO,
                0,
                mDefaultWaterLevel);
            // translate shader according to mWaveShiftRatio and mWaterLevelRatio
            // this decides the start position(mWaveShiftRatio for x, mWaterLevelRatio for y) of waves
            mShaderMatrix.postTranslate(
                mWaveShiftRatio * getWidth(),
                (DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * getHeight());

            // assign matrix to invalidate the shader
            mWaveShader.setLocalMatrix(mShaderMatrix);

            float borderWidth = mBorderPaint == null ? 0f : mBorderPaint.getStrokeWidth();
            switch (mShapeType) {
                case CIRCLE:
                    if (borderWidth > 0) {
                        canvas.drawCircle(getWidth() / 2f, getHeight() / 2f,
                            (getWidth() - borderWidth) / 2f - 1f, mBorderPaint);
                    }
                    float radius = getWidth() / 2f - borderWidth;
                    canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, mViewPaint);
                    break;
                case SQUARE:
                    if (borderWidth > 0) {
                        canvas.drawRect(
                            borderWidth / 2f,
                            borderWidth / 2f,
                            getWidth() - borderWidth / 2f - 0.5f,
                            getHeight() - borderWidth / 2f - 0.5f,
                            mBorderPaint);
                    }
                    canvas.drawRect(borderWidth, borderWidth, getWidth() - borderWidth,
                        getHeight() - borderWidth, mViewPaint);
                    break;
            }
        } else {
            mViewPaint.setShader(null);
        }
    }
}

还有这个waterHelper类,对不需要的功能进行了注释

public class WaveHelper {
    private WaveView mWaveView;

    private AnimatorSet mAnimatorSet;
    List<Animator> animators = new ArrayList<>();
    public WaveHelper(WaveView waveView) {
        mWaveView = waveView;
        initAnimation();
    }

    public void start() {
        mWaveView.setShowWave(true);
        if (mAnimatorSet != null) {
            mAnimatorSet.start();
        }
    }

    private void initAnimation() {


        // horizontal animation.
        // wave waves infinitely.
        ObjectAnimator waveShiftAnim = ObjectAnimator.ofFloat(
                mWaveView, "waveShiftRatio", 0f, 1f);
        waveShiftAnim.setRepeatCount(ValueAnimator.INFINITE);
        waveShiftAnim.setDuration(1000);
        waveShiftAnim.setInterpolator(new LinearInterpolator());
        animators.add(waveShiftAnim);

     /*   // vertical animation.
        // 水位从0到设置的水位高度
        ObjectAnimator waterLevelAnim = ObjectAnimator.ofFloat(
                mWaveView, "waterLevelRatio", 0f, waterLevel);
        waterLevelAnim.setDuration(10000);
        waterLevelAnim.setInterpolator(new DecelerateInterpolator());
        animators.add(waterLevelAnim);*/

        // amplitude animation.
        // wave grows big then grows small, repeatedly
 /*       ObjectAnimator amplitudeAnim = ObjectAnimator.ofFloat(
                mWaveView, "amplitudeRatio", 0.0001f, 0.05f);
        amplitudeAnim.setRepeatCount(ValueAnimator.INFINITE);
        amplitudeAnim.setRepeatMode(ValueAnimator.REVERSE);
        amplitudeAnim.setDuration(5000);
        amplitudeAnim.setInterpolator(new LinearInterpolator());
        animators.add(amplitudeAnim);*/

        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(animators);

    }

    public void cancel() {
        if (mAnimatorSet != null) {
//            mAnimatorSet.cancel();
            mAnimatorSet.end();
        }
    }
}

在我代码中对这个类的引用

  //手机屏幕密度
    private float density;
     private int chargingProgress = 0;
    private float currentDegree = 0f;
    //重力感应,让水滴效果不随着屏幕旋转变化

    private FrameLayout frameLayoutWater;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 0x123) {
                if (chargingProgress <= 100) {
            textViewProgress.setText(chargingProgress + "%");
                    float level = chargingProgress / 100.0f;
                    waveView.setWaterLevelRatio(level);
                    chargingProgress++;

                }
            }
        }
    };
        @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
 density = getActivity().getResources().getDisplayMetrics().density;
   //水纹效果
        waveView = (WaveView) view.findViewById(R.id.wave);
        Bitmap bitmapWave = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.wave_1);

        //代码设置控件宽高,不超过默认图片
        ViewGroup.LayoutParams lp;
        lp = waveView.getLayoutParams();
        lp.width = bitmapWave.getWidth() - (int) (30 * density);
        lp.height = bitmapWave.getHeight() - (int) (30 * density);
        waveView.setLayoutParams(lp);
         waveView.setBorder(mBorderWidth, mBorderColor);
        waveView.setWaterLevelRatio(0);

        mWaveHelper = new WaveHelper(waveView);
          Button button = (Button) view.findViewById(R.id.id_buttonWave);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mWaveHelper.start();
                final Timer timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        handler.sendEmptyMessage(0x123);
                        if (chargingProgress >= 100) {
                            timer.cancel();
                        }
                    }
                }, 0, 1000);
            }
        });
        }
    @Override
    public void onPause() {
        super.onPause();
        mWaveHelper.cancel();
    }

这个需要解释一下,我没有在布局中将控件宽高写死,怕影响到自适应,想了个办法,就是以背景图片的宽高在代码中进行设置控件的宽高,需要用到手机屏幕的密度density,然后定义一个handler进行更新演示,更新水波高度以及修改水波进度数字,在button按钮中启动水波效果。

水滴滴下效果

这个我也是借助了第三方的类库,我只是取了一个方法,onDropPhase(),并且取消了源码中的阴影效果,因为不美观,然后将水滴滴下时显示的水平线也取消了。源码中修改的代码我就不贴了,第一是因为太多了,第二是我也忘记修改了什么了,在文章最后我把修改过的源码传一下吧,有兴趣的可以自己修改着看看效果,直接上我实现水滴效果的代码吧

 private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 0x123) {
                if (chargingProgress <= 100) {

                    mWaveSwipeRefreshLayout.onDropPhase();
                    textViewProgress.setText(chargingProgress + "%");
                    float level = chargingProgress / 100.0f;
                    waveView.setWaterLevelRatio(level);
                    chargingProgress++;

                }
            }
        }
    };

  //水滴
        mWaveSwipeRefreshLayout = (WaveSwipeRefreshLayout) view.findViewById(R.id.main_swipe);
        mWaveSwipeRefreshLayout.setColorSchemeColors(Color.TRANSPARENT, Color.TRANSPARENT);
        mWaveSwipeRefreshLayout.setWaveColor(Color.parseColor("#addef8"));
  //设置水滴效果控件宽高

        ViewGroup.LayoutParams lp2;
        lp2 = mWaveSwipeRefreshLayout.getLayoutParams();
        lp2.width = bitmapWave.getWidth() - (int) (30 * density);
        lp2.height = bitmapWave.getHeight() - (int) (30 * density);
        mWaveSwipeRefreshLayout.setMaxDropHeight(mWaveSwipeRefreshLayout.getHeight());
        mWaveSwipeRefreshLayout.setLayoutParams(lp2);

实现始终朝向重力方向的功能

这个功能需要用到传感器,唉,也是各种纠结,参考了其他几篇文章,主要是判断重力角度,要继承 implements SensorEventListener ,然后使用动画进行旋转,直接上代码吧

  // 传感器管理器
        SensorManager sm = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);
        // 注册传感器(Sensor.TYPE_ORIENTATION(方向传感器);SENSOR_DELAY_FASTEST(0毫秒延迟);
        // SENSOR_DELAY_GAME(20,000毫秒延迟)、SENSOR_DELAY_UI(60,000毫秒延迟))
        sm.registerListener(this,
                sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                SensorManager.SENSOR_DELAY_FASTEST);
 @Override
    public void onSensorChanged(SensorEvent event) {
        if (Sensor.TYPE_ACCELEROMETER != event.sensor.getType()) {
            return;
        }

        float[] values = event.values;
        float ax = values[0];
        float ay = values[1];

        double g = Math.sqrt(ax * ax + ay * ay);
        double cos = ay / g;
        if (cos > 1) {
            cos = 1;
        } else if (cos < -1) {
            cos = -1;
        }
        double rad = Math.acos(cos);
        if (ax < 0) {
            rad = 2 * Math.PI - rad;
        }

        int uiRot = getActivity().getWindowManager().getDefaultDisplay().getRotation();
        double uiRad = Math.PI / 2 * uiRot;
        rad -= uiRad;
        int degrees = (int) (180 * rad / Math.PI);

        //如果度数变化不超过5,不变化,防止频繁晃动
        if(Math.abs(currentDegree-degrees)>5){
            RotateAnimation ra = new RotateAnimation(currentDegree, degrees,
                    Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f);
            ra.setFillAfter(true);
            frameLayoutWater.startAnimation(ra);
            currentDegree = degrees;
        }

这个角度是个难点,我就是因为这个纠结了半天,当时是忘记了这句换算int degrees = (int) (180 * rad / Math.PI); 
贴上完整代码

public class ChargeFragment extends Fragment implements SensorEventListener {

    private TextView textViewProgress;//充电进度
    private int mBorderColor = Color.parseColor("#addef8");
    private int mBorderWidth = 2;
    private WaveHelper mWaveHelper;
    private WaveView waveView;
    private WaveSwipeRefreshLayout mWaveSwipeRefreshLayout;
    //手机屏幕密度
    private float density;
    //测试动画
    private int chargingProgress = 0;
    private float currentDegree = 0f;
    //重力感应,让水滴效果不随着屏幕旋转变化

    private FrameLayout frameLayoutWater;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 0x123) {
                if (chargingProgress <= 100) {

                    mWaveSwipeRefreshLayout.onDropPhase();
                    textViewProgress.setText(chargingProgress + "%");
                    float level = chargingProgress / 100.0f;
                    waveView.setWaterLevelRatio(level);
                    chargingProgress++;

                }
            }
        }
    };

    public ChargeFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_charge, container, false);
        density = getActivity().getResources().getDisplayMetrics().density;

        imageViewRota = (ImageView) view.findViewById(R.id.id_imageRota);
        textViewProgress = (TextView) view.findViewById(R.id.id_textViewProgress);
        Button button = (Button) view.findViewById(R.id.id_buttonWave);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mWaveHelper.start();
                final Timer timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        handler.sendEmptyMessage(0x123);
                        if (chargingProgress >= 100) {
                            timer.cancel();
                        }
                    }
                }, 0, 1000);
            }
        });
        final RotateAnimation ra = new RotateAnimation(0, 359, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        ra.setDuration(1000);
        ra.setRepeatCount(-1);
        //匀速
        LinearInterpolator lin = new LinearInterpolator();
        ra.setInterpolator(lin);
        imageViewRota.startAnimation(ra);
        //水滴
        mWaveSwipeRefreshLayout = (WaveSwipeRefreshLayout) view.findViewById(R.id.main_swipe);
        mWaveSwipeRefreshLayout.setColorSchemeColors(Color.TRANSPARENT, Color.TRANSPARENT);
        mWaveSwipeRefreshLayout.setWaveColor(Color.parseColor("#addef8"));
        //水纹效果
        waveView = (WaveView) view.findViewById(R.id.wave);
        Bitmap bitmapWave = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.wave_1);

        //代码设置控件宽高,不超过默认图片
        ViewGroup.LayoutParams lp;
        lp = waveView.getLayoutParams();
        lp.width = bitmapWave.getWidth() - (int) (30 * density);
        lp.height = bitmapWave.getHeight() - (int) (30 * density);
        waveView.setLayoutParams(lp);
        //设置水滴效果控件宽高

        ViewGroup.LayoutParams lp2;
        lp2 = mWaveSwipeRefreshLayout.getLayoutParams();
        lp2.width = bitmapWave.getWidth() - (int) (30 * density);
        lp2.height = bitmapWave.getHeight() - (int) (30 * density);
        mWaveSwipeRefreshLayout.setMaxDropHeight(mWaveSwipeRefreshLayout.getHeight());
        mWaveSwipeRefreshLayout.setLayoutParams(lp2);

        waveView.setBorder(mBorderWidth, mBorderColor);
        waveView.setWaterLevelRatio(0);

        mWaveHelper = new WaveHelper(waveView);
        frameLayoutWater = (FrameLayout) view.findViewById(R.id.id_framelayout);

/*
        final RotateAnimation ra2 = new RotateAnimation(0, 360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        ra2.setDuration(5000);
        ra2.setRepeatCount(-1);
          frameLayout.startAnimation(ra2);*/
        // 传感器管理器
        SensorManager sm = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);
        // 注册传感器(Sensor.TYPE_ORIENTATION(方向传感器);SENSOR_DELAY_FASTEST(0毫秒延迟);
        // SENSOR_DELAY_GAME(20,000毫秒延迟)、SENSOR_DELAY_UI(60,000毫秒延迟))
        sm.registerListener(this,
                sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                SensorManager.SENSOR_DELAY_FASTEST);

        return view;
    }



    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

    }

    @Override
    public void onDetach() {
        super.onDetach();

    }

    @Override
    public void onDestroy() {
        super.onDestroy();

    }

    @Override
    public void onPause() {
        super.onPause();
        mWaveHelper.cancel();
    }

    @Override
    public void onResume() {
        super.onResume();

    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (Sensor.TYPE_ACCELEROMETER != event.sensor.getType()) {
            return;
        }

        float[] values = event.values;
        float ax = values[0];
        float ay = values[1];

        double g = Math.sqrt(ax * ax + ay * ay);
        double cos = ay / g;
        if (cos > 1) {
            cos = 1;
        } else if (cos < -1) {
            cos = -1;
        }
        double rad = Math.acos(cos);
        if (ax < 0) {
            rad = 2 * Math.PI - rad;
        }

        int uiRot = getActivity().getWindowManager().getDefaultDisplay().getRotation();
        double uiRad = Math.PI / 2 * uiRot;
        rad -= uiRad;
        int degrees = (int) (180 * rad / Math.PI);

        //如果度数变化不超过5,不变化,防止频繁晃动
        if(Math.abs(currentDegree-degrees)>5){
            RotateAnimation ra = new RotateAnimation(currentDegree, degrees,
                    Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f);
            ra.setFillAfter(true);
            frameLayoutWater.startAnimation(ra);
            currentDegree = degrees;
        }

    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}

下边贴上修改过的资源地址 
http://download.csdn.net/detail/jifashihan/9384182 
http://download.csdn.net/detail/jifashihan/9384242

原始资源地址 
https://github.com/gelitenight/WaveView 
https://github.com/recruit-lifestyle/WaveSwipeRefreshLayout

 
 
原文地址:https://www.cnblogs.com/android-blogs/p/5177644.html