一个不错的loading效果

一个不错的loading加载效果,弹性收缩,效果不错,学习android动画的朋友可以下载来研究研究
本例子其实由SeekBar实现,由MetaballView,MetaballDebugView实现动画效果.
当滑动到有一个位置的时候设置选中和未选中状态.
metaballView.setPaintMode();
           
debugMetaballView.setPaintMode();
设置SeekBar 的进度debugMetaballView.setMaxDistance(progress);

布局引入:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#001d30"
    android:clipChildren="false"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

<com.dodola.animview.MetaballView
        android:id="@+id/metaball"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" />

<com.dodola.animview.MetaballDebugView
        android:id="@+id/debug_metaball"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignEnd="@+id/metaball"
        android:layout_alignRight="@+id/metaball"
        android:layout_below="@+id/metaball"
        android:layout_marginTop="20dp" />

<TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignTop="@+id/debug_metaball"
        android:text="Debug test"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@android:color/white" />

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:clickable="true"
        android:orientation="vertical">

<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="最大间距"
            android:textColor="@android:color/white" />

<SeekBar
            android:id="@+id/seekBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:max="400" />

<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="贝塞尔曲线角度"
            android:textColor="@android:color/white" />

<SeekBar
            android:id="@+id/seekBar2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="200" />

<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="贝塞尔曲线控制点长度比率"
            android:textColor="@android:color/white" />

<SeekBar
            android:id="@+id/seekBar3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="500" />
    </LinearLayout>
</RelativeLayout>

主要代码如下:

package com.dodola.animview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ProgressBar;
import android.widget.SeekBar;

public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {

    private MetaballView metaballView;
    private MetaballDebugView debugMetaballView;
    private SeekBar seekBar, seekBar2, seekBar3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        metaballView = (MetaballView) this.findViewById(R.id.metaball);
        debugMetaballView = (MetaballDebugView) findViewById(R.id.debug_metaball);
        seekBar = (SeekBar) findViewById(R.id.seekBar);
        seekBar2 = (SeekBar) findViewById(R.id.seekBar2);
        seekBar3 = (SeekBar) findViewById(R.id.seekBar3);
        seekBar.setOnSeekBarChangeListener(this);
        seekBar2.setOnSeekBarChangeListener(this);
        seekBar3.setOnSeekBarChangeListener(this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_fill) {
            metaballView.setPaintMode(1);
            debugMetaballView.setPaintMode(1);
            return true;
        } else if (id == R.id.action_strock) {
            metaballView.setPaintMode(0);
            debugMetaballView.setPaintMode(0);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        switch (seekBar.getId()) {
            case R.id.seekBar:
                debugMetaballView.setMaxDistance(progress);
                break;
            case R.id.seekBar2:
                debugMetaballView.setMv(progress / 100f);
                break;
            case R.id.seekBar3:
                debugMetaballView.setHandleLenRate(progress / 100f);
                break;
        }

    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
}

自定义页面MetaballDebugView,主要代码如下

package com.dodola.animview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * Created by dodola on 15/7/27.
 */
public class MetaballDebugView extends View {

    private Paint paint = new Paint();

    private float handleLenRate = 2f;
    private final float radius = 60;
    private final float SCALE_RATE = 0.3f;
    private ArrayList<Circle> circlePaths = new ArrayList<>();
    private float mv = 0.6f;
    private float maxDistance = radius * 4;

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

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

    public MetaballDebugView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }

    public float getMv() {
        return mv;
    }

    public void setMv(float mv) {
        this.mv = mv;
        invalidate();
    }

    public float getMaxDistance() {
        return maxDistance;
    }

    public void setMaxDistance(float maxDistance) {
        this.maxDistance = maxDistance;
        invalidate();
    }

    public float getHandleLenRate() {
        return handleLenRate;
    }

    public void setHandleLenRate(float handleLenRate) {
        this.handleLenRate = handleLenRate;
        invalidate();
    }

    private class Circle {
        float[] center;
        float radius;
    }

    public void setPaintMode(int mode) {
        paint.setStyle(mode == 0 ? Paint.Style.STROKE : Paint.Style.FILL);
        invalidate();
    }

    private void init() {
        paint.setColor(0xff4db9ff);
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);

    }

    private void initMetaballs() {
        Circle circlePath = new Circle();
        circlePath.center = new float[]{(radius), radius};
        circlePath.radius = radius;
        circlePaths.add(circlePath);

        circlePath = new Circle();
        circlePath.center = new float[]{this.getMeasuredWidth() / 2, this.getMeasuredHeight() / 3};
        circlePath.radius = radius;
        circlePaths.add(circlePath);
    }

    private float[] getVector(float radians, float length) {
        float x = (float) (Math.cos(radians) * length);
        float y = (float) (Math.sin(radians) * length);
        return new float[]{
                x, y
        };
    }

    /**
     * @param canvas          画布
     * @param j
     * @param i
     * @param v               控制两个圆连接时候长度,间接控制连接线的粗细,该值为1的时候连接线为直线
     * @param handle_len_rate
     * @param maxDistance
     */
    private void metaball(Canvas canvas, int j, int i, float v, float handle_len_rate, float maxDistance) {
        final Circle circle1 = circlePaths.get(i);
        final Circle circle2 = circlePaths.get(j);

        RectF ball1 = new RectF();
        ball1.left = circle1.center[0] - circle1.radius;
        ball1.top = circle1.center[1] - circle1.radius;
        ball1.right = ball1.left + circle1.radius * 2;
        ball1.bottom = ball1.top + circle1.radius * 2;

        RectF ball2 = new RectF();
        ball2.left = circle2.center[0] - circle2.radius;
        ball2.top = circle2.center[1] - circle2.radius;
        ball2.right = ball2.left + circle2.radius * 2;
        ball2.bottom = ball2.top + circle2.radius * 2;

        float[] center1 = new float[]{
                ball1.centerX(),
                ball1.centerY()
        };
        float[] center2 = new float[]{
                ball2.centerX(),
                ball2.centerY()
        };
        float d = getDistance(center1, center2);

        float radius1 = ball1.width() / 2;
        float radius2 = ball2.width() / 2;
        float pi2 = (float) (Math.PI / 2);
        float u1, u2;

        if (d > maxDistance) {
            canvas.drawCircle(ball2.centerX(), ball2.centerY(), circle2.radius, paint);
        } else {
            float scale2 = 1 + SCALE_RATE * (1 - d / maxDistance);
            radius2 *= scale2;
            canvas.drawCircle(ball2.centerX(), ball2.centerY(), radius2, paint);
        }

        Log.d("Metaball_radius", "radius1:" + radius1 + ",radius2:" + radius2);
        if (radius1 == 0 || radius2 == 0) {
            return;
        }

        if (d > maxDistance || d <= Math.abs(radius1 - radius2)) {
            return;
        } else if (d < radius1 + radius2) {
            u1 = (float) Math.acos((radius1 * radius1 + d * d - radius2 * radius2) /
                    (2 * radius1 * d));
            u2 = (float) Math.acos((radius2 * radius2 + d * d - radius1 * radius1) /
                    (2 * radius2 * d));
        } else {
            u1 = 0;
            u2 = 0;
        }
        Log.d("Metaball", "center2:" + Arrays.toString(center2) + ",center1:" + Arrays.toString(center1));
        float[] centermin = new float[]{center2[0] - center1[0], center2[1] - center1[1]};

        float angle1 = (float) Math.atan2(centermin[1], centermin[0]);
        float angle2 = (float) Math.acos((radius1 - radius2) / d);
        float angle1a = angle1 + u1 + (angle2 - u1) * v;
        float angle1b = angle1 - u1 - (angle2 - u1) * v;
        float angle2a = (float) (angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v);
        float angle2b = (float) (angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v);

        Log.d("Metaball", "angle1:" + angle1 + ",angle2:" + angle2 + ",angle1a:" + angle1a + ",angle1b:" + angle1b + ",angle2a:" + angle2a + ",angle2b:" + angle2b);

        float[] p1a1 = getVector(angle1a, radius1);
        float[] p1b1 = getVector(angle1b, radius1);
        float[] p2a1 = getVector(angle2a, radius2);
        float[] p2b1 = getVector(angle2b, radius2);

        float[] p1a = new float[]{p1a1[0] + center1[0], p1a1[1] + center1[1]};
        float[] p1b = new float[]{p1b1[0] + center1[0], p1b1[1] + center1[1]};
        float[] p2a = new float[]{p2a1[0] + center2[0], p2a1[1] + center2[1]};
        float[] p2b = new float[]{p2b1[0] + center2[0], p2b1[1] + center2[1]};

        Log.d("Metaball", "p1a:" + Arrays.toString(p1a) + ",p1b:" + Arrays.toString(p1b) + ",p2a:" + Arrays.toString(p2a) + ",p2b:" + Arrays.toString(p2b));

        float[] p1_p2 = new float[]{p1a[0] - p2a[0], p1a[1] - p2a[1]};

        float totalRadius = (radius1 + radius2);
        float d2 = Math.min(v * handle_len_rate, getLength(p1_p2) / totalRadius);
        d2 *= Math.min(1, d * 2 / (radius1 + radius2));
        Log.d("Metaball", "d2:" + d2);
        radius1 *= d2;
        radius2 *= d2;

        float[] sp1 = getVector(angle1a - pi2, radius1);
        float[] sp2 = getVector(angle2a + pi2, radius2);
        float[] sp3 = getVector(angle2b - pi2, radius2);
        float[] sp4 = getVector(angle1b + pi2, radius1);
        Log.d("Metaball", "sp1:" + Arrays.toString(sp1) + ",sp2:" + Arrays.toString(sp2) + ",sp3:" + Arrays.toString(sp3) + ",sp4:" + Arrays.toString(sp4));

        Path path1 = new Path();
        path1.moveTo(p1a[0], p1a[1]);
        path1.cubicTo(p1a[0] + sp1[0], p1a[1] + sp1[1], p2a[0] + sp2[0], p2a[1] + sp2[1], p2a[0], p2a[1]);
        path1.lineTo(p2b[0], p2b[1]);
        path1.cubicTo(p2b[0] + sp3[0], p2b[1] + sp3[1], p1b[0] + sp4[0], p1b[1] + sp4[1], p1b[0], p1b[1]);
        path1.lineTo(p1a[0], p1a[1]);
        path1.close();
        canvas.drawPath(path1, paint);

    }

    private float getLength(float[] b) {
        return (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]);
    }

    private float getDistance(float[] b1, float[] b2) {
        float x = b1[0] - b2[0];
        float y = b1[1] - b2[1];
        float d = x * x + y * y;
        return (float) Math.sqrt(d);
    }

    //测试用
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Circle circle = circlePaths.get(0);
        circle.center[0] = event.getX();
        circle.center[1] = event.getY();
        invalidate();
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (circlePaths.size() == 0) {
            initMetaballs();
        }

        final Circle circle1 = circlePaths.get(0);
        RectF ball1 = new RectF();
        ball1.left = circle1.center[0] - circle1.radius;
        ball1.top = circle1.center[1] - circle1.radius;
        ball1.right = ball1.left + circle1.radius * 2;
        ball1.bottom = ball1.top + circle1.radius * 2;
        canvas.drawCircle(ball1.centerX(), ball1.centerY(), circle1.radius, paint);

        for (int i = 1; i < circlePaths.size(); i++) {
            metaball(canvas, i, 0, mv, handleLenRate, maxDistance);
        }
    }

}

自定义MetaballView,主要代码如下
控制两个圆连接时候长度,间接控制连接线的粗细,该值为1的时候连接线为直线
文章原创《IT蓝豹》http://www.itlanbao.com/

package com.dodola.animview;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

/**
 * Created by dodola on 15/7/27.
 */
public class MetaballView extends View {

    private Paint paint = new Paint();
    private float handle_len_rate = 2f;
    private float radius = 30;
    private final int ITEM_COUNT = 6;
    private final int ITEM_DIVIDER = 60;
    private final float SCALE_RATE = 0.3f;
    private float maxLength;
    private ArrayList<Circle> circlePaths = new ArrayList<>();
    private float mInterpolatedTime;
    private MoveAnimation wa;
    private Circle circle;

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

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

    public MetaballView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }

    private class Circle {
        float[] center;
        float radius;
    }

    public void setPaintMode(int mode) {
        paint.setStyle(mode == 0 ? Paint.Style.STROKE : Paint.Style.FILL);
        invalidate();
    }

    private void init() {
        paint.setColor(0xff4db9ff);
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        Circle circlePath = new Circle();
        circlePath.center = new float[]{(radius + ITEM_DIVIDER), radius * (1f + SCALE_RATE)};
        circlePath.radius = radius / 4 * 3;
        circlePaths.add(circlePath);

        for (int i = 1; i < ITEM_COUNT; i++) {
            circlePath = new Circle();
            circlePath.center = new float[]{(radius * 2 + ITEM_DIVIDER) * i, radius * (1f + SCALE_RATE)};
            circlePath.radius = radius;
            circlePaths.add(circlePath);
        }
        maxLength = (radius * 2 + ITEM_DIVIDER) * ITEM_COUNT;
    }

    private float[] getVector(float radians, float length) {
        float x = (float) (Math.cos(radians) * length);
        float y = (float) (Math.sin(radians) * length);
        return new float[]{
                x, y
        };
    }

    private class MoveAnimation extends Animation {

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);
            mInterpolatedTime = interpolatedTime;
            invalidate();
        }
    }

    /**
     * @param canvas          画布
     * @param j
     * @param i
     * @param v               控制两个圆连接时候长度,间接控制连接线的粗细,该值为1的时候连接线为直线
     * @param handle_len_rate
     * @param maxDistance
     */
    private void metaball(Canvas canvas, int j, int i, float v, float handle_len_rate, float maxDistance) {
        final Circle circle1 = circlePaths.get(i);
        final Circle circle2 = circlePaths.get(j);

        RectF ball1 = new RectF();
        ball1.left = circle1.center[0] - circle1.radius;
        ball1.top = circle1.center[1] - circle1.radius;
        ball1.right = ball1.left + circle1.radius * 2;
        ball1.bottom = ball1.top + circle1.radius * 2;

        RectF ball2 = new RectF();
        ball2.left = circle2.center[0] - circle2.radius;
        ball2.top = circle2.center[1] - circle2.radius;
        ball2.right = ball2.left + circle2.radius * 2;
        ball2.bottom = ball2.top + circle2.radius * 2;

        float[] center1 = new float[]{
                ball1.centerX(),
                ball1.centerY()
        };
        float[] center2 = new float[]{
                ball2.centerX(),
                ball2.centerY()
        };
        float d = getDistance(center1, center2);

        float radius1 = ball1.width() / 2;
        float radius2 = ball2.width() / 2;
        float pi2 = (float) (Math.PI / 2);
        float u1, u2;

        if (d > maxDistance) {
//            canvas.drawCircle(ball1.centerX(), ball1.centerY(), circle1.radius, paint);
            canvas.drawCircle(ball2.centerX(), ball2.centerY(), circle2.radius, paint);
        } else {
            float scale2 = 1 + SCALE_RATE * (1 - d / maxDistance);
            float scale1 = 1 - SCALE_RATE * (1 - d / maxDistance);
            radius2 *= scale2;
//            radius1 *= scale1;
//            canvas.drawCircle(ball1.centerX(), ball1.centerY(), radius1, paint);
            canvas.drawCircle(ball2.centerX(), ball2.centerY(), radius2, paint);

        }

//        Log.d("Metaball_radius", "radius1:" + radius1 + ",radius2:" + radius2);
        if (radius1 == 0 || radius2 == 0) {
            return;
        }

        if (d > maxDistance || d <= Math.abs(radius1 - radius2)) {
            return;
        } else if (d < radius1 + radius2) {
            u1 = (float) Math.acos((radius1 * radius1 + d * d - radius2 * radius2) /
                    (2 * radius1 * d));
            u2 = (float) Math.acos((radius2 * radius2 + d * d - radius1 * radius1) /
                    (2 * radius2 * d));
        } else {
            u1 = 0;
            u2 = 0;
        }
//        Log.d("Metaball", "center2:" + Arrays.toString(center2) + ",center1:" + Arrays.toString(center1));
        float[] centermin = new float[]{center2[0] - center1[0], center2[1] - center1[1]};

        float angle1 = (float) Math.atan2(centermin[1], centermin[0]);
        float angle2 = (float) Math.acos((radius1 - radius2) / d);
        float angle1a = angle1 + u1 + (angle2 - u1) * v;
        float angle1b = angle1 - u1 - (angle2 - u1) * v;
        float angle2a = (float) (angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v);
        float angle2b = (float) (angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v);

//        Log.d("Metaball", "angle1:" + angle1 + ",angle2:" + angle2 + ",angle1a:" + angle1a + ",angle1b:" + angle1b + ",angle2a:" + angle2a + ",angle2b:" + angle2b);

        float[] p1a1 = getVector(angle1a, radius1);
        float[] p1b1 = getVector(angle1b, radius1);
        float[] p2a1 = getVector(angle2a, radius2);
        float[] p2b1 = getVector(angle2b, radius2);

        float[] p1a = new float[]{p1a1[0] + center1[0], p1a1[1] + center1[1]};
        float[] p1b = new float[]{p1b1[0] + center1[0], p1b1[1] + center1[1]};
        float[] p2a = new float[]{p2a1[0] + center2[0], p2a1[1] + center2[1]};
        float[] p2b = new float[]{p2b1[0] + center2[0], p2b1[1] + center2[1]};

//        Log.d("Metaball", "p1a:" + Arrays.toString(p1a) + ",p1b:" + Arrays.toString(p1b) + ",p2a:" + Arrays.toString(p2a) + ",p2b:" + Arrays.toString(p2b));

        float[] p1_p2 = new float[]{p1a[0] - p2a[0], p1a[1] - p2a[1]};

        float totalRadius = (radius1 + radius2);
        float d2 = Math.min(v * handle_len_rate, getLength(p1_p2) / totalRadius);
        d2 *= Math.min(1, d * 2 / (radius1 + radius2));
//        Log.d("Metaball", "d2:" + d2);
        radius1 *= d2;
        radius2 *= d2;

        float[] sp1 = getVector(angle1a - pi2, radius1);
        float[] sp2 = getVector(angle2a + pi2, radius2);
        float[] sp3 = getVector(angle2b - pi2, radius2);
        float[] sp4 = getVector(angle1b + pi2, radius1);
//        Log.d("Metaball", "sp1:" + Arrays.toString(sp1) + ",sp2:" + Arrays.toString(sp2) + ",sp3:" + Arrays.toString(sp3) + ",sp4:" + Arrays.toString(sp4));

        Path path1 = new Path();
        path1.moveTo(p1a[0], p1a[1]);
        path1.cubicTo(p1a[0] + sp1[0], p1a[1] + sp1[1], p2a[0] + sp2[0], p2a[1] + sp2[1], p2a[0], p2a[1]);
        path1.lineTo(p2b[0], p2b[1]);
        path1.cubicTo(p2b[0] + sp3[0], p2b[1] + sp3[1], p1b[0] + sp4[0], p1b[1] + sp4[1], p1b[0], p1b[1]);
        path1.lineTo(p1a[0], p1a[1]);
        path1.close();
        canvas.drawPath(path1, paint);

    }

    private float getLength(float[] b) {
        return (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]);
    }

    private float getDistance(float[] b1, float[] b2) {
        float x = b1[0] - b2[0];
        float y = b1[1] - b2[1];
        float d = x * x + y * y;
        return (float) Math.sqrt(d);
    }

    //测试用
//    @Override
//    public boolean onTouchEvent(MotionEvent event) {
//        switch (event.getAction()) {
//            case MotionEvent.ACTION_DOWN:
//                break;
//            case MotionEvent.ACTION_MOVE:
//                Circle circle = circlePaths.get(0);
//                circle.center[0] = event.getX();
//                circle.center[1] = event.getY();
//                invalidate();
//                break;
//            case MotionEvent.ACTION_UP:
//                break;
//        }
//
//        return true;
//    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        circle = circlePaths.get(0);
        circle.center[0] = maxLength * mInterpolatedTime;

        RectF ball1 = new RectF();
        ball1.left = circle.center[0] - circle.radius;
        ball1.top = circle.center[1] - circle.radius;
        ball1.right = ball1.left + circle.radius * 2;
        ball1.bottom = ball1.top + circle.radius * 2;
        canvas.drawCircle(ball1.centerX(), ball1.centerY(), circle.radius, paint);

        for (int i = 1, l = circlePaths.size(); i < l; i++) {
            metaball(canvas, i, 0, 0.6f, handle_len_rate, radius * 4f);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(resolveSizeAndState((int) (ITEM_COUNT * (radius * 2 + ITEM_DIVIDER)), widthMeasureSpec, 0),
                resolveSizeAndState((int) (2 * radius * 1.4f), heightMeasureSpec, 0));
    }

    private void stopAnimation() {
        this.clearAnimation();
        postInvalidate();
    }

    private void startAnimation() {
        wa = new MoveAnimation();
        wa.setDuration(2500);
        wa.setInterpolator(new AccelerateDecelerateInterpolator());
        wa.setRepeatCount(Animation.INFINITE);
        wa.setRepeatMode(Animation.REVERSE);
        startAnimation(wa);
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);

        if (visibility == GONE || visibility == INVISIBLE) {
            stopAnimation();
        } else {
            startAnimation();
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        startAnimation();
    }

    @Override
    protected void onDetachedFromWindow() {
        stopAnimation();
        super.onDetachedFromWindow();
    }
}

文章来源《IT蓝豹》www.itlanbao.com

时间: 2024-10-13 23:17:39

一个不错的loading效果的相关文章

一个很酷的加载loading效果

一个很酷的加载loading效果,自定义LeafLoadingView实现,LeafLoadingView继承view,本例子主要由以下几点构成(1):RotateAnimation实现叶子旋转(2):叶子飘动(3):当前进度绘制当前进度条大体实现: @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas); // 绘制进度条和叶子        // 之所以把叶子放在进度条里绘制,主要是层级原

一个不错效果的调光调色开关

先上效果图: 不错吧,最中间那个开关是个CheckBox,中间那个蓝色的是个圆形的拖动条,可以用来显示灯的亮度,而最外面的彩色环形也是可以拖动的,可以用来控制色彩. 彩色环形是自定义View--CirclView,onTouch事件计算如旋转的角度,然后旋转画布,那个环形是UI素材.代码如下: 1 import android.content.Context; 2 import android.graphics.Bitmap; 3 import android.graphics.Canvas;

转---写一个网页进度loading

作者:jack_lo www.jianshu.com/p/4c93f5bd9861 如有好文章投稿,请点击 → 这里了解详情 loading随处可见,比如一个app经常会有下拉刷新,上拉加载的功能,在刷新和加载的过程中为了让用户感知到 load 的过程,我们会使用一些过渡动画来表达.最常见的比如"转圈圈","省略号"等等. 网页loading有很多用处,比如页面的加载进度,数据的加载过程等等,数据的加载loading很好做,只需要在加载数据之前(before aja

CSS3实现的几个小loading效果

昨晚上闲的没事突然想做几个小loading效果,下面是昨晚上做的几个小案例,分享给大家 1.水波loading:这个loading是我觉得非常简单,但是看上去的效果却非常不错的一个小loading 这个是效果图片 下面我直接把代码放上来,大家需要的可以直接拉走 核心思想:(旋转,以及overflow:hidden属性),可以把代码中的overflow属性注释掉,保准你看一眼明白了,看不明白回来找我,我对你负责 <!DOCTYPE html> <html lang="en&quo

Jquery Easy UI 实现页面的Loading效果(类似于Android的ProgressDialog)

前言 很常用的一种前端效果,比如当用户点击网页的某个按钮发送了一条异步请求,如果响应时间过长容易导致用户重复点击,一方面影响用户体验一方面容易造成不必要的服务端压力,Easy UI有现成的mask样式,简单封装一下就可以使用,之前查阅搜集了相关资料和文章,发现都介绍的都不是很完整,所以本篇blog就完整的记录一下通过Easy UI快速实现这种效果以及如何集成到项目中. 引入.封装和调用 首先当然是在我们的项目中集成jquery以及easyui的相关资源包,除了jquery的核心js文件,easy

网页Loading效果

问题描述:由于项目要求在页面提交以及加载的时候,有短暂的卡顿,需要用loading过渡. 1.下一个页面加载的时候实现: base-loading.js //获取浏览器页面可见高度和宽度 var _PageHeight = document.documentElement.clientHeight, _PageWidth = document.documentElement.clientWidth; //计算loading框距离顶部和左部的距离(loading框的宽度为215px,高度为61px

javscript 实现iframe加载内容页出现LOADING效果

<div id="load" align="center"> <img src="http://sc.cnwebshow.com/upimg/allimg/070707/01294420.gif" /> loading </div> <!-- 首先放一个div,用做loading效果 --> <iframe id="demo" src="http://www.**

仿易讯客户端loading效果

下面来实现一个loading效果.具体效果如下: 首先对这个效果进行拆分,它由以下部分组成: 1 一个"闪电"样式的图案: 2 "闪电"图案背后是一个圆角矩形; 3 "闪电"图案上面有一层颜色不断"飘过" 拆分完效果后,思考下如何实现.下面是我的思考过程. 1 android sdk并没有提供这样的控件,很显然是需要自定义控件: 2 很显然是一个View而不是ViewGroup,所以可以继承View; 3 重点是onDraw的

HTML5 Canvas 实现的9个 Loading 效果

Sonic.js 是一个很小的 JavaScript 类,用于创建基于 HTML5 画布的加载图像.更强大的是 Sonic.js 还提供了基于现成的例子的创建工具,可以帮助你实现更多自定义的(Loading)加载动画效果. 在线演示      源码下载 您可能感兴趣的相关文章 网站开发中很有用的 jQuery 效果[附源码] 分享35个让人惊讶的 CSS3 动画效果演示 十分惊艳的8个 HTML5 & JavaScript 特效 Web 开发中很实用的10个效果[源码下载] 12款经典的白富美型