一个不错的loading效果--IT蓝豹
一个不错的loading效果
介绍:
一个不错的loading加载效果,弹性收缩,效果不错,学习android动画的朋友可以下载来研究研究
本例子其实由SeekBar实现,由MetaballView,MetaballDebugView实现动画效果.
项目来自:http://www.itlanbao.com/code/20151209/10000/100683.html
当滑动到有一个位置的时候设置选中和未选中状态.
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,主要代码如下
文章来源《IT蓝豹》
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的时候连接线为直线
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蓝豹》http://www.itlanbao.com/code/20151209/10000/100683.html
一个不错的loading效果--IT蓝豹的更多相关文章
- 一个很酷的加载loading效果--IT蓝豹
一个很酷的加载loading效果,自定义LeafLoadingView实现,LeafLoadingView继承view, 本例子主要由以下几点构成 (1):RotateAnimation实现叶子旋转 ...
- CSS3饼状loading效果
概述 之前看到很多饼状loading效果是用图片的方式实现的,本例子采用的是纯CSS3实现,这样可以节省资源空间,有兴趣的小伙伴可以看下~ 详细 代码下载:http://www.demodashi.c ...
- 转---写一个网页进度loading
作者:jack_lo www.jianshu.com/p/4c93f5bd9861 如有好文章投稿,请点击 → 这里了解详情 loading随处可见,比如一个app经常会有下拉刷新,上拉加载的功能,在 ...
- CSS3实现的几个小loading效果
昨晚上闲的没事突然想做几个小loading效果,下面是昨晚上做的几个小案例,分享给大家 1.水波loading:这个loading是我觉得非常简单,但是看上去的效果却非常不错的一个小loading 这 ...
- 写一个网页进度loading
作者:jack_lo www.jianshu.com/p/4c93f5bd9861 如有好文章投稿,请点击 → 这里了解详情 loading随处可见,比如一个app经常会有下拉刷新,上拉加载的功能,在 ...
- 页面loading效果
当网页太大,打开太慢的时候,为了增加良好的用户体验(不让用户眼巴巴的等,心中暗骂c,这么慢),我们需要加一个等待动画. 只需把以下代码加入页面中即可,图片可以根据自己的需求更换,更换图片之后需要改变l ...
- 网页Loading效果
问题描述:由于项目要求在页面提交以及加载的时候,有短暂的卡顿,需要用loading过渡. 1.下一个页面加载的时候实现: base-loading.js //获取浏览器页面可见高度和宽度 var _P ...
- datetimepicker一个不错的日历android特效
datetimepicker一个不错的日历效,选中和选择日历效果都很不错, 实用的时候直接可以把datetimepicker-library这个引入到项目,调用的地方在实现 TimePickerDia ...
- 在android开发中使用multdex的方法-IT蓝豹为你整理
Android系统在安装应用时,往往需要优化Dex,而由于处理工具DexOpt对id数目的限制,导致其处理的数目不能超过65536个,因此在Android开发中,需要使用到MultiDex来解决这个问 ...
随机推荐
- How Garbage Collection Really Works
Java Memory Management, with its built-in garbage collection, is one of the language's finest achiev ...
- Codeforces Round #383 (Div. 2) D. Arpa's weak amphitheater and Mehrdad's valuable Hoses(分组背包+dsu)
D. Arpa's weak amphitheater and Mehrdad's valuable Hoses Problem Description: Mehrdad wants to invit ...
- Python基础语法,基本数据类型及相关操作
---恢复内容开始--- python文件 文件开头要有 #!/usr/bin/ python --在linux中是告诉系统phthon的路径是在/usr/bin/ python目录下 ...
- JAVA垃圾收集机制剖析
1.垃圾收集算法的核心思想 Java语言建立了垃圾收集机制,用以跟踪正在使用的对象和发现并回收不再使用(引用)的对象.该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽 ...
- 一些常用的sql语句
1.查询表里的null值:is null 和 is not null select*from student where email is null 返回的该表里面邮箱为null的结果集 ...
- js解决IE不支持数组的indexOf()方法
if (!Array.indexOf) { Array.indexOf = function (obj) { ...
- (Hibernate进阶)Hibernate映射——多对多关联映射(八)
多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数 ...
- The PHP Package 之 monolog[转]
Monolog 发送你的日志到文件.到sockets.到邮箱.到数据库或(和)者其他网路存储服务(云).Monolog可以做到同时保存到一个或多个存储介质(后面的栈冒泡处理). 安装 $ comp ...
- python Django教程 之 模型(数据库)、自定义Field、数据表更改、QuerySet API
python Django教程 之 模型(数据库).自定义Field.数据表更改.QuerySet API 一.Django 模型(数据库) Django 模型是与数据库相关的,与数据库相关的代码 ...
- js原型基础
js中的原型链是实现继承等面向对象的一种方式,而我这里不详细展开,仅仅是画了一张原型部分结构图,主要说明: 1._proto_和prototype之间的关系 2.原型链的起点是Object.proto ...