一个Android下拉刷新样式

作者: hello老文 | 来源:发表于2017-10-31 10:02 被阅读3194次

    近来需求要求下拉刷新动画Android和iOS统一样式, 效果如下:

    下拉刷新gif

    使用SmartRefreshLayout这个框架自定义Header动画. 感觉这个框架还是很好用的.

    1. SmartRefreshLayout加入到项目:

      compile 'com.android.support:appcompat-v7:25.3.1'
      compile 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.2-alpha-5'
      
    2. 在自定义的Application文件里初始化:

      public class App extends Application {
          @Override
          public void onCreate() {
              super.onCreate();
              initRefreshViewLayout();
          }
      
          private void initRefreshViewLayout() {
              MyRefreshLayout.init();
          }
      }
      
    3. 自定义个继承自SmartRefreshLayoutMyRefreshLayout文件:

      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();
              }
          }
      }
      
    4. 创建个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());
          }
      }   
      
    5. 创建一个贝塞尔画圆工具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());
          }
      }
      
    6. 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>
      
    7. 使用示例:

      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>
      

    相关文章

      网友评论

        本文标题:一个Android下拉刷新样式

        本文链接:https://www.haomeiwen.com/subject/bqjmpxtx.html