过年放假前最后一天班,就想着作个简单又有趣的小东西。因而决定来写个自定义的LoadingView做为这个App框架的加载效果吧 |
走过路过点歌Start O(∩_∩)O Github项目地址android
这篇文章叫你如何搭建手写LoadingView,看完这篇文章你能学会:git
--------------------------------关门,上分割线------------------------------------------------ 先看看效果: github
1.建立item_loading_view.xml布局,把样式先写出来
2.自定义View,加载这个自定义布局
3.自定义View内作动画处理
复制代码
1.布局:item_loading_view.xmlcanvas
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:padding="24dp"
android:layout_height="148dp">
<ImageView
android:id="@+id/iv_loading"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_above="@+id/tv_loading"
android:src="@drawable/ic_favorites" />
<TextView
android:id="@+id/tv_loading"
android:layout_width="wrap_content"
android:text="加载中..."
android:layout_marginTop="12dp"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content" />
</RelativeLayout>
复制代码
2.自定义Viewbash
public class LoadingView extends FrameLayout {
public LoadingView(Context context) {
this(context,null);
}
public LoadingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 加载布局
LayoutInflater.from(mContext).inflate(R.layout.item_loading_view, this);
}
复制代码
这个时候在Activity的布局中引用的话,能看到这个loadingView的静态效果了。最后最关键的一步 3.动画效果实现: 这里面涉及到两个动画效果,一个是那个爱心上下跳动,以及底下一个阴影缩放 爱心上下跳动效果:框架
private void logic() {
ValueAnimator animator = ValueAnimator.ofInt(0,mJumpHeightPx,0);
animator.setDuration(800);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
mIv.setTranslationY(-value);
// 为了画shadow
mMovePercent = value / 100f;
postInvalidate();
}
});
animator.start();
}
复制代码
LoaingView构造函数中调用该方法(详细见githun项目源码) 实现思路:利用属性动画移动 关于属性动画做用的原理能够去百度几篇文章,一句话归纳就是,属性动画提供的是:使用某种变化规则去获得一个不断变化值,而后本身利用这个值去设置控件的属性以达到动画的效果。ide
shadow缩放效果:函数
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 阴影宽高的一半 最大不超过16 / 8
float shadowHalfWidth = Math.max(16f,(mIvRight - mIvLeft) / 2 );
float shadowHalfHeight = Math.max(8f,(mIvBottom - mIvTop) / 2 );
// 阴影区域中线位置(决定阴影所在位置) yCenter:垂直中线的纵坐标 xCenter:水平中线的横坐标
float yCenter = mIvLeft + shadowHalfWidth;
float xCenter = mIvTop + shadowHalfHeight * 2;
// 缩放的变化量(决定阴影变化大小)
float horizontalDiff = Math.max(2,(1f - mMovePercent) * shadowHalfWidth * mShadowFlatX);
float verticalDiff = Math.max(2,(1f - mMovePercent) * shadowHalfHeight * mShadowFlatY);
Log.d("bigname", "onDraw: " + yCenter + "-----" + xCenter + "------" + horizontalDiff + "--------" + verticalDiff + "-------" + mMovePercent);
mShadowRectF.set(
yCenter - horizontalDiff,
xCenter - verticalDiff,
yCenter + horizontalDiff,
xCenter + verticalDiff
);
canvas.drawOval(mShadowRectF, mShadowPaint);
}
复制代码
shadow利用画布去实现: 首先在使用属性动画的时候将变化的值赋给全局变量mMovePercent;而且变化的时候调用postInvalidate()重绘,这样的话在onDraw()方法中接口和mMovePercent就能知道当前动画进行的进度。依此来控制shadow缩放。布局
这个自定义LoadingView效果就已经实现了,接下来会对这个控件作些优化,增长更炫的动画效果,而后作好封装。post
源码在上面的github连接
敬请期待---