近来需求要求下拉刷新动画Android和iOS统一样式, 效果如下:
使用SmartRefreshLayout这个框架自定义Header
动画. 感觉这个框架还是很好用的.
-
把
SmartRefreshLayout
加入到项目:compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.2-alpha-5'
-
在自定义的
Application
文件里初始化:public class App extends Application { @Override public void onCreate() { super.onCreate(); initRefreshViewLayout(); } private void initRefreshViewLayout() { MyRefreshLayout.init(); } }
-
自定义个继承自
SmartRefreshLayout
的MyRefreshLayout
文件:public class MyRefreshLayout extends SmartRefreshLayout { public static void init() { // 指定全局的下拉Header SmartRefreshLayout.setDefaultRefreshHeaderCreater(new DefaultRefreshHeaderCreater() { @Override public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) { return new MyRefreshHeader(context); } }); // 指定全局的上拉Footer SmartRefreshLayout.setDefaultRefreshFooterCreater(new DefaultRefreshFooterCreater() { @NonNull @Override public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) { return new ClassicsFooter(context); } }); } public MyRefreshLayout(Context context) { super(context); initView(context); } public MyRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public MyRefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); } private void initView(Context context) { setReboundDuration(300); // 设置回弹动画时长 setPrimaryColorsId(R.color.white); // 主题色 setEnableAutoLoadmore(false); // 设置是否监听列表在滚动到底部时触发加载事件 } // 下拉/上拉完成 public void complete() { if (mState == RefreshState.Loading) { finishLoadmore(); } else { finishRefresh(); } } }
-
创建个
MyRefreshHeader
文件, 在这里做自定义的动画:public class MyRefreshHeader extends RelativeLayout implements RefreshHeader { private CircleProgressView mCircleProgressView; private TextView mTextView; private ImageView mArrow; private boolean isArrowDown = false; public MyRefreshHeader(Context context) { super(context); this.initView(context, null, 0); } public MyRefreshHeader(Context context, AttributeSet attrs) { super(context, attrs); this.initView(context, attrs, 0); } public MyRefreshHeader(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.initView(context, attrs, defStyleAttr); } private void initView(Context context, AttributeSet attrs, int defStyleAttr) { setMinimumHeight(dp2px(context, 80)); LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.addRule(CENTER_IN_PARENT); View headerView = View.inflate(context, R.layout.my_refresh_header, null); mCircleProgressView = (CircleProgressView) headerView.findViewById(R.id.circleProgressView); mTextView = (TextView) headerView.findViewById(R.id.textview); mArrow = (ImageView) headerView.findViewById(R.id.iv_refresh_center); addView(headerView, params); } @Override public void onInitialized(RefreshKernel kernel, int height, int extendHeight) { // 尺寸定义完成 } @Override public void onPullingDown(float percent, int offset, int headHeight, int extendHeight) { // 手指拖动下拉(会连续多次调用) if (mCircleProgressView == null) return; float startPercent = 0.20f; if (percent > startPercent && percent < 1) { float tempPercent = (percent-startPercent) * 1.0f / (1 - startPercent); mCircleProgressView.setProgressPersent(tempPercent); } } @Override public void onReleasing(float percent, int offset, int headHeight, int extendHeight) { // 手指释放之后的持续动画 } @Override public void onStartAnimator(RefreshLayout layout, int headHeight, int extendHeight) { RotateAnimation ta = new RotateAnimation(0, 360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); ta.setDuration(500); ta.setRepeatCount(10000); ta.setInterpolator(new LinearInterpolator()); ta.setFillAfter(true); mCircleProgressView.startAnimation(ta); } @Override public int onFinish(RefreshLayout layout, boolean success) { mCircleProgressView.clearAnimation(); return 100; // 动画结束,延迟多少毫秒之后再收回 } @Override public void setPrimaryColors(int... colors) { setBackgroundColor(getResources().getColor(R.color.activity_bg)); } @NonNull public View getView() { return this; } @Override public SpinnerStyle getSpinnerStyle() { return SpinnerStyle.Translate; } @Override public void onStateChanged(RefreshLayout refreshLayout, RefreshState oldState, RefreshState newState) { // 状态改变事件 switch (newState) { case None: // 无状态 if (mCircleProgressView != null) mCircleProgressView.setProgressPersent(0); if (isArrowDown) { arrowAnimation(); isArrowDown = false; } break; case PullDownToRefresh: // 可以下拉状态 mTextView.setText("下拉即可刷新"); break; case Refreshing: // 刷新中状态 mTextView.setText("正在刷新数据..."); break; case ReleaseToRefresh: // 释放就开始刷新状态 mTextView.setText("松开立即刷新"); if (!isArrowDown) { arrowAnimation(); isArrowDown = true; } break; } } private void arrowAnimation() { RotateAnimation ra = new RotateAnimation(0, isArrowDown ? 0 : 180.0f, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); ra.setDuration(200); ra.setRepeatCount(0); ra.setInterpolator(new LinearInterpolator()); ra.setFillAfter(true); mArrow.startAnimation(ra); } /** * dp转px */ private int dp2px(Context context, float dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources().getDisplayMetrics()); } }
-
创建一个贝塞尔画圆工具
CircleProgressView
来画圆弧:public class CircleProgressView extends View { private RectF mRectF; private Paint mPaint; private int width; private int height; private float persent = 0.0f; // 进度 private float lineWidth = 2; // 线宽 public CircleProgressView(Context context) { super(context); lineWidth = dp2px(context, 1.0f); initView(); } public CircleProgressView(Context context, AttributeSet attrs) { super(context, attrs); lineWidth = dp2px(context, 1.0f); initView(); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = MeasureSpec.getSize(widthMeasureSpec); height = MeasureSpec.getSize(heightMeasureSpec); if (width != height) { int min = Math.min(width, height); width = min; height = min; } mRectF.left = lineWidth / 2; mRectF.top = lineWidth / 2; mRectF.right = width - lineWidth / 2; mRectF.bottom = height - lineWidth / 2; } private void initView() { mRectF = new RectF(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(getResources().getColor(R.color.theme_color_80)); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(lineWidth); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.TRANSPARENT); canvas.drawArc(mRectF, 90, persent * 350, false, mPaint); } public void setProgressPersent(float persent) { this.persent = persent; this.invalidate(); } // dp转px private int dp2px(Context context, float dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources().getDisplayMetrics()); } }
-
在
res\layout\
创建一个my_refresh_header.xml
文件:<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="5dp" > <ImageView android:id="@+id/iv_head" android:layout_width="135dp" android:layout_height="15dp" android:layout_centerHorizontal="true" android:src="@mipmap/refresh_head" /> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="12dp" android:layout_below="@+id/iv_head" > <RelativeLayout android:id="@+id/rlCircleContainer" android:layout_width="wrap_content" android:layout_height="wrap_content" > <app.laowen.com.downrefreshdemo.CircleProgressView android:id="@+id/circleProgressView" android:layout_width="22dp" android:layout_height="22dp" android:layout_centerInParent="true" /> <ImageView android:id="@+id/iv_refresh_center" android:layout_width="15dp" android:layout_height="15dp" android:layout_centerInParent="true" android:scaleType="fitCenter" android:src="@mipmap/arrow_up" /> </RelativeLayout> <TextView android:id="@+id/textview" style="@style/text_24_80" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@+id/rlCircleContainer" android:paddingLeft="10dp" android:text="下拉即可刷新" /> </RelativeLayout> </RelativeLayout>
-
使用示例:
public class MainActivity extends AppCompatActivity { private MyRefreshLayout refreshLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); refreshLayout = (MyRefreshLayout)findViewById(R.id.refreshLayout); refreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(RefreshLayout refreshlayout) { refreshlayout.finishRefresh(3000); // 模拟请求数据, 3秒后结束 } }); refreshLayout.setOnLoadmoreListener(new OnLoadmoreListener() { @Override public void onLoadmore(RefreshLayout refreshlayout) { refreshlayout.finishLoadmore(3000); } }); } }
xml:
<?xml version="1.0" encoding="utf-8"?> <app.laowen.com.downrefreshdemo.MyRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/refreshLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/activity_bg" > <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" android:background="#236678" /> </app.laowen.com.downrefreshdemo.MyRefreshLayout>