Android RecyclerView 드 롭 다운 리 셋 과 업 로드 실현

RecyclerView 가 나 온 지 오래 되 었 습 니 다.많은 프로젝트 가 ListView 에서 RecyclerView 로 전환 되 기 시 작 했 습 니 다.그러면 위로 끌 어 올 리 고 아래로 끌 어 올 리 는 것 이 필요 합 니 다.
ListView 에서 저 희 는 addHeadView 와 addFootView 를 추가 하여 헤드 레이아웃 과 아래쪽 국 가 를 추가 하여 사용자 정의 상 당 김 과 하 당 김 을 실현 하거나 제3자 라 이브 러 리 를 사용 하여 간단 한 통합 을 할 수 있 습 니 다.예 를 들 어 Android-pultorefresh 나 android-Ultra-Pull-to-Refresh 는 후자 의 사용자 정의 가 더욱 강하 지만 스스로 상 당 김 로드 를 실현 해 야 합 니 다.
아래 에서 우 리 는 두 가지 방식 으로 상 라 로드 와 하 라 리 셋 을 실현 할 것 이다.
첫 번 째 방법:SwipeRefreshLayout+슬라이더 밑 에 자동 으로 불 러 오기
두 번 째 방식:제3자 라 이브 러 리 SwipeToLoadLayout 를 사용 하여 위로 끌 어 올 리 고 아래로 끌 어 올 리 기 를 실현 합 니 다.
첫 번 째 방법:SwipeRefreshLayout+슬라이더 밑 에 자동 으로 불 러 오기
Swipe RefreshLayout 의 실현 은 매우 간단 하 다.중요 한 것 은 미끄럼 이 도대체 자동 으로 불 러 오 는 것 을 어떻게 실현 해 야 하 는 지 하 는 것 이다.사실은 그 실현 방식 은 ListView 의 실현 방식 과 유사 하 다.
activityrecycle_swiperefresh.xml 파일:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/swipe_refresh"
 android:orientation="vertical" android:layout_width="match_parent"
 android:layout_height="match_parent">

 <android.support.v7.widget.RecyclerView
  android:id="@+id/swipe_target"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:scrollbars="none" />

</android.support.v4.widget.SwipeRefreshLayout>

레이아웃 파일 은 두 개의 컨트롤 입 니 다.Swipe RefreshLayout 에 RecyclerView 가 포함 되 어 있 습 니 다.
코드 에서 RecyclerView 를 초기 화하 고 adapter 를 실현 하 는 등 중요 한 것 이 아니 라 코드 를 붙 이지 않 습 니 다.
RecyclerView 에 서 는 addOnScrollListener 방법 이 있 습 니 다.이 방법 은 ListView 의 setOnScrollListener 방법 과 유사 합 니 다.OnScrollListener 에는 두 가지 방법 이 있 습 니 다.
*on Scrolled(RecyclerView recyclerView,int dx,int dy):굴 러 가 는 반전,dx 와 dy 는 손가락 의 미끄럼 수준 과 수직 오프셋 을 나타 낸다.
*onScrollStateChanged(RecyclerView recyclerView,int newState):미끄럼 상태의 리 셋.
그렇다면 우리 의 중점 은 이 두 가지 방법 에 있다.
위로 더 많이 불 러 오 는 것 에 대해 우 리 는 다음 과 같은 판단 이 필요 하 다.
--위로 미 끄 러 지 는 지
--끝까지 미 끄 러 졌 는 지
--현재 데 이 터 를 불 러 오 는 중 인지
--현재 상태 가 미끄럼 이 멈 춘 상태 인지
비교적 복잡 한 것 을 실현 하고 클래스 LoadDataScrollController,계승 클래스 RecyclerView 를 정의 합 니 다.OnScrollListener,
onScroll State Changed 의 실제 상태 가 바 뀌 었 을 때의 리 셋 으로 표시 되 는 항목 과 위 치 를 수시로 가 져 올 수 없 기 때문에 onScrolled 에서 해당 위 치 를 가 져 옵 니 다.

 @Override
 public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

  /**
   *       
   */
  RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();

  //   null,     ,      
  if (mLayoutManagerType == null) {
   if (layoutManager instanceof LinearLayoutManager) {
    mLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT;
   } else if (layoutManager instanceof GridLayoutManager) {
    mLayoutManagerType = LayoutManagerType.GRID_LAYOUT;
   } else if (layoutManager instanceof StaggeredGridLayoutManager) {
    mLayoutManagerType = LayoutManagerType.STAGGERED_GRID_LAYOUT;
   } else {
    throw new RuntimeException("LayoutManager should be LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager");
   }
  }

  //           ,                    
  switch (mLayoutManagerType) {
   case LINEAR_LAYOUT:
    mLastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
    break;
   case GRID_LAYOUT:
    mLastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
    break;
   case STAGGERED_GRID_LAYOUT:
    StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
    if (mLastPostions == null) {
     mLastPostions = new int[staggeredGridLayoutManager.getSpanCount()];
    }
    staggeredGridLayoutManager.findLastVisibleItemPositions(mLastPostions);
    mLastVisibleItemPosition = findMax(mLastPostions);
    break;
   default:
    break;
  }

 }

먼저 레이아웃 관리 자 를 가 져 오고 그런 유형 으로 판단 합 니 다.세 가지 유형 이 있 기 때문에 레이아웃 형식의 인 자 를 저장 하기 위해 매 거 진 을 정의 합 니 다.

/**
 *
 * RecycleView         
 * Created by Alex_MaHao on 2016/5/10.
 */
public enum LayoutManagerType {
 LINEAR_LAYOUT,
 GRID_LAYOUT,
 STAGGERED_GRID_LAYOUT
}

그 다음 에 구조 관례 에 따라 그 유형 에 따라 현재 표 시 된 최대 항목 을 얻 을 수 있 습 니 다.폭포 흐름 에 있어 서 그 가 수직 으로 두 개의 폭포 라면 우 리 는 두 열 에서 각각 최대 항목 을 얻 고 비교 하여 최대 항목 을 선택해 야 합 니 다.

 /**
  *       ,                  ,        
  */
 private int findMax(int[] lastPositions) {
  int max = lastPositions[0];
  for (int value : lastPositions) {
   if (value > max) {
    max = value;
   }
  }
  return max;
 }

현재 최대 항목 수 를 가 져 온 후 onScroll State Change 에서 상태 등 을 판단 합 니 다.

 @Override
 public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

  RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();

  //RecycleView       
  int visibleCount = layoutManager.getChildCount();

  //      
  int totalCount = layoutManager.getItemCount();


  //     ,        ,           ,               (     ),        
  if(visibleCount>0
    &&newState==RecyclerView.SCROLL_STATE_IDLE
    &&mLastVisibleItemPosition>=totalCount-1
    &&!isLoadData){
   //      
   isLoadData = true;
  }

 }

설명 이 분명 합 니 다.데 이 터 를 불 러 오 는 곳 에서 isLoadData 를 true 로 설정 하고 인터페이스 리 셋 으로 데 이 터 를 불 러 옵 니 다.데이터 불 러 오 기 를 기다 리 고 있 습 니 다.setLoadDataStatus 방법 을 통 해 false 로 설정 합 니 다.

 public void setLoadDataStatus(boolean isLoadData){
  this.isLoadData = isLoadData;
 }

이렇게 끝나 면 귀 찮 습 니 다.새로 고침 과 로 딩 에 대해 더 많은 것 을 설정 해 야 합 니 다.호출 된 곳 에 각각 감청 을 설정 해 야 합 니 다.그러면 LoadDataScroll Controller 가 Swipe Refresh Layout 의 새로 고침 감청 방법 을 실현 하고 우리 가 정의 한 통 일 된 위 에서 새로 고침 과 로 딩 데이터 인 터 페 이 스 를 이용 하여 처리 할 수 있 습 니 다.

/**
 *          :    :     ,      ,       
 * Created by Alex_MaHao on 2016/5/10.
 */
public class LoadDataScrollController extends RecyclerView.OnScrollListener implements SwipeRefreshLayout.OnRefreshListener {

 /**
  *           
  */
 private LayoutManagerType mLayoutManagerType;


 /**
  *   RecycleView       
  */
 private int mLastVisibleItemPosition;


 /**
  *          
  */
 private int[] mLastPostions;


 /**
  *                     
  */
 private boolean isLoadData = false;


 /**
  *     
  */
 private OnRecycleRefreshListener mListener;


 public LoadDataScrollController(OnRecycleRefreshListener onRecycleRefreshListener) {
  this.mListener = onRecycleRefreshListener;
 }

 @Override
 public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

  /**
   *       
   */
  RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();

  //   null,     ,      
  if (mLayoutManagerType == null) {
   if (layoutManager instanceof LinearLayoutManager) {
    mLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT;
   } else if (layoutManager instanceof GridLayoutManager) {
    mLayoutManagerType = LayoutManagerType.GRID_LAYOUT;
   } else if (layoutManager instanceof StaggeredGridLayoutManager) {
    mLayoutManagerType = LayoutManagerType.STAGGERED_GRID_LAYOUT;
   } else {
    throw new RuntimeException("LayoutManager should be LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager");
   }
  }

  //           ,                    
  switch (mLayoutManagerType) {
   case LINEAR_LAYOUT:
    mLastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
    break;
   case GRID_LAYOUT:
    mLastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
    break;
   case STAGGERED_GRID_LAYOUT:
    StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
    if (mLastPostions == null) {
     mLastPostions = new int[staggeredGridLayoutManager.getSpanCount()];
    }
    staggeredGridLayoutManager.findLastVisibleItemPositions(mLastPostions);
    mLastVisibleItemPosition = findMax(mLastPostions);
    break;
   default:
    break;
  }

 }

 @Override
 public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

  RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();

  //RecycleView       
  int visibleCount = layoutManager.getChildCount();

  //      
  int totalCount = layoutManager.getItemCount();


  //     ,        ,           ,               (     ),        
  if(visibleCount>0
    &&newState==RecyclerView.SCROLL_STATE_IDLE
    &&mLastVisibleItemPosition>=totalCount-1
    &&!isLoadData){
   //      
   if(mListener!=null){
    isLoadData = true;
    mListener.loadMore();
   }
  }

 }


 /**
  *       ,                  ,        
  */
 private int findMax(int[] lastPositions) {
  int max = lastPositions[0];
  for (int value : lastPositions) {
   if (value > max) {
    max = value;
   }
  }
  return max;
 }


 public void setLoadDataStatus(boolean isLoadData){
  this.isLoadData = isLoadData;
 }

 @Override
 public void onRefresh() {
  //       
  if(mListener!=null){
   isLoadData = true;
   mListener.refresh();
  }

 }

 /**
  *         
  */
 interface OnRecycleRefreshListener{
  void refresh();
  void loadMore();
 }
}

마지막 으로 main 코드 를 볼 게 요.

/**
 *      SwipeRefreshLayout     
 *    RecyclewView         
 *
 * Created by Alex_MaHao on 2016/5/10.
 */
public class SwipeRefreshActivity extends AppCompatActivity implements LoadDataScrollController.OnRecycleRefreshListener {


 private SwipeRefreshLayout mSwipeRefresh;

 private RecyclerView mRecycle;

 private HomeAdapter mAdapter;

 private LoadDataScrollController mController;


 private ProgressDialog pd;

 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  setContentView(R.layout.activity_recycle_swiperefresh);

  mRecycle = ((RecyclerView) findViewById(R.id.swipe_target));

  mSwipeRefresh = ((SwipeRefreshLayout) findViewById(R.id.swipe_refresh));

  mSwipeRefresh.setColorSchemeColors(Color.RED,Color.GREEN,Color.BLUE);

  /**
   *      ,     activity          
   */
  mController = new LoadDataScrollController(this);



  mAdapter = new HomeAdapter();

  //            ,Orientation --> VERTICAL:   HORIZONTAL:  
  LinearLayoutManager layoutManager = new LinearLayoutManager(this);
  layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

  //StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);

  //     
  mRecycle.addItemDecoration(new DividerItemDecoration(getApplicationContext(), DividerItemDecoration.VERTICAL_LIST));


  mRecycle.setLayoutManager(layoutManager);

  mRecycle.setItemAnimator(new DefaultItemAnimator());

  mRecycle.setAdapter(mAdapter);

  mAdapter.refresh();

  /**
   *     
   */
  mRecycle.addOnScrollListener(mController);

  mSwipeRefresh.setOnRefreshListener(mController);

 }

 @Override
 public void refresh() {
  //      
  mSwipeRefresh.postDelayed(new Runnable() {
   @Override
   public void run() {
    mAdapter.refresh();
    mSwipeRefresh.setRefreshing(false);
    mController.setLoadDataStatus(false);
   }
  },2000);
 }

 @Override
 public void loadMore() {
  //         
  pd = new ProgressDialog(this);
  pd.show();
  mSwipeRefresh.postDelayed(new Runnable() {
   @Override
   public void run() {
    mAdapter.add();
    //             
    mController.setLoadDataStatus(false);
    pd.dismiss();
   }
  },2000);
 }
}

효과 도 를 붙이다

두 번 째 방식:SwipeToLoadLayout 상 당 김 로드 와 드 롭 다운 리 셋 실현
이 컨트롤 을 새로 고 치 는 방식 은 Ultra-pull-to-refresh 와 유사 합 니 다.
다음 방법 으로 이 라 이브 러 리 를 추가 합 니 다:

 repositories {
  maven { url "https://jitpack.io" }
   }

 compile 'com.github.Aspsine:SwipeToLoadLayout:1.0.3'

우선 머리 보기 와 아래쪽 보 기 를 사용자 정의 해 야 합 니 다.머리 는 아래쪽 에서 시도 하 는 용법 과 같 기 때문에 머리 보기 류 를 정의 합 니 다.

/**
 *    refreshHeadView
 */
public class RefreshHeaderView extends TextView implements SwipeRefreshTrigger, SwipeTrigger {

 public RefreshHeaderView(Context context) {
  super(context);
 }

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

 public RefreshHeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
 }

 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
 public RefreshHeaderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
  super(context, attrs, defStyleAttr, defStyleRes);
 }

 @Override
 public void onRefresh() {
  //           ,     
  setText("refresh");

  Log.i("info","onRefresh");
 }

 @Override
 public void onPrepare() {

  //         
  Log.i("info","onPrepare");
 }

 @Override
 public void onMove(int yScrolled, boolean isComplete, boolean automatic) {
  if (!isComplete) {
   //  Y           ,       ,  “     ”
   if (yScrolled >= getHeight()) {

   } else {
    //      

   }
  } 
  Log.i("info","onMove");
 }

 @Override
 public void onRelease() {
  //        ,       
  setText("onRelease");
  Log.i("info","onRelease");
 }

 @Override
 public void onComplete() {
  //           
  setText("complete");
  Log.i("info","onComplete");
 }

 @Override
 public void onReset() {
  //  
  setText("onReset");
  Log.i("info","onReset");
 }
}

인터페이스 Swipe RefreshTrigger 와 Swipe Trigger 를 실현 해 야 합 니 다.
바닥 은 SwipeTrigger 와 SwipeLoadMoreTrigger 를 실현 해 야 합 니 다.
레이아웃 파일 에서 다음 과 같이 사용

<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="#ECEDF0"
 >

 <com.aspsine.swipetoloadlayout.SwipeToLoadLayout
  android:id="@+id/swipeToLoadLayout"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <com.mahao.alex.systemwidgetdemo.recycleView.swipetoloadlayout.RefreshHeaderView
   android:id="@+id/swipe_refresh_header"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" />

  <android.support.v7.widget.RecyclerView
   android:id="@+id/swipe_target"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:scrollbars="vertical" />

  <com.mahao.alex.systemwidgetdemo.recycleView.swipetoloadlayout.LoaderMoreView
   android:id="@+id/swipe_load_more_footer"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:gravity="center"
   android:padding="20dp" />
 </com.aspsine.swipetoloadlayout.SwipeToLoadLayout>


</RelativeLayout>

컨트롤 찾기,감청 설정
        swipeToLoadLayout.setOnRefreshListener(this);
        swipeToLoadLayout.setOnLoadMoreListener(this);
이전 코드 에 로그 정 보 를 추 가 했 습 니 다.로그 정 보 를 볼 수 있 습 니 다.여러 번 onMove()방법 을 여러 번 호출 합 니 다.
05-10 10:30:34.396 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onPrepare
05-10 10:30:34.536 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onMove
..........................................................................
05-10 10:30:34.886 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onMove
05-10 10:30:34.896 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onRelease
05-10 10:30:34.906 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onMove
..........................................................................
05-10 10:30:35.086 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onMove
05-10 10:30:35.106 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onRefresh
05-10 10:30:37.116 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onComplete
05-10 10:30:37.416 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onMove
..........................................................................
05-10 10:30:37.516 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onMove
05-10 10:30:37.916 23814-23814/com.mahao.alex.systemwidgetdemo I/info: onReset
우선 onPrepare()방법 을 호출 합 니 다.onMove()방법 은 계속 호출 되 며 보기 가 이동 하면 호출 됩 니 다.일정 거리 로 내 려 간 후,호출 onRelaease()를 풀 고,새로 고침 위치 로 돌아 갈 때 onRefresh()를 되 돌리 고,호출 onComplete()를 불 러 옵 니 다.보기 가 축소 되 기 시 작 했 습 니 다.마지막 으로 숨 긴 후 onReset()을 호출 합 니 다.
필요 에 따라 보 기 를 사용자 정의 합 니 다.

사용자 정의 컨트롤 을 사용 하여 타원 을 정의 합 니 다.

/**
 * CircleView     ,    
 * Created by Alex_MaHao on 2016/5/10.
 */
public class CircleView extends View {

 /**
  *      
  */
 private int mRadius;

 /**
  *        
  */
 private Paint mArcPaint;

 /**
  *        
  */
 private RectF mRange;


 private int[] colors = {Color.RED, Color.BLUE, Color.YELLOW, Color.GREEN};

 public CircleView(Context context) {
  this(context, null, 0);
 }

 public CircleView(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }

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

  init();
 }

 private void init() {
  mArcPaint = new Paint();
  mArcPaint.setAntiAlias(true);
  mArcPaint.setDither(true);
  mArcPaint.setStyle(Paint.Style.FILL);
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);

  int width = 0;
  int height = 0;

  int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  int widthMode = MeasureSpec.getMode(widthMeasureSpec);

  int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  int heightMode = MeasureSpec.getMode(heightMeasureSpec);


  if (widthMode == MeasureSpec.EXACTLY) {
   width = widthSize;
  } else {
   width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 45, getResources().getDisplayMetrics());
  }

  if (heightMode == MeasureSpec.EXACTLY) {
   height = heightSize;
  } else {
   height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 45, getResources().getDisplayMetrics());
  }

  //    
  mRadius = Math.min(width, height) / 2;
  /**
   *         
   */
  setMeasuredDimension(mRadius * 2, mRadius * 2);

   mRange = new RectF(0, 0, mRadius * 2, mRadius * 2);
 }


 @Override
 protected void onDraw(Canvas canvas) {

  float degree = 360/colors.length/2f;

  for (int i = 0; i < 8; i++) {
   mArcPaint.setColor(colors[i%4]);
   canvas.drawArc(mRange,-90f+degree*i,degree,true,mArcPaint);
  }

 }
}

머리 새로 고침 시도 그리 기

**
 *              
 * Created by Alex_MaHao on 2016/5/10.
 */
public class CircleRefreshHeaderView extends RelativeLayout implements SwipeTrigger, SwipeRefreshTrigger {

 CircleView mCircleView;

 TextView mDescText;

 private ObjectAnimator anim;

 private boolean isRelease;

 public CircleRefreshHeaderView(Context context) {
  this(context, null, 0);
 }

 public CircleRefreshHeaderView(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }

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

  initView();
 }

 /**
  *      
  */
 private void initView() {

  int circlewidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, getResources().getDisplayMetrics());

  mCircleView = new CircleView(getContext());

  LinearLayout.LayoutParams circleParams = new LinearLayout.LayoutParams(circlewidth,circlewidth);

  mCircleView.setLayoutParams(circleParams);

  mDescText = new TextView(getContext());

  LinearLayout.LayoutParams descParams = new LinearLayout.LayoutParams(circlewidth*3, ViewGroup.LayoutParams.WRAP_CONTENT);

  descParams.gravity = Gravity.CENTER;
  descParams.setMargins(circlewidth/2,0,0,0);
  mDescText.setLayoutParams(descParams);
  mDescText.setTextSize(12);
  mDescText.setTextColor(Color.GRAY);
  mDescText.setText("    ");

  //        
  LinearLayout ll = new LinearLayout(getContext());
  RelativeLayout.LayoutParams llParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
  llParams.addRule(CENTER_IN_PARENT);
  ll.setLayoutParams(llParams);
  ll.setPadding(10,10,10,10);

  ll.addView(mCircleView);
  ll.addView(mDescText);

  addView(ll);
 }

 @Override
 public void onRefresh() {

  //    ,    
  anim = ObjectAnimator.ofFloat(mCircleView, "rotation", mCircleView.getRotation(), mCircleView.getRotation()+360f)
    .setDuration(500);
  anim.setRepeatCount(ValueAnimator.INFINITE);
  anim.setRepeatMode(ValueAnimator.RESTART);
  anim.start();

  mDescText.setText("      ");
 }

 @Override
 public void onPrepare() {
  isRelease = false;
 }

 @Override
 public void onMove(int yScroll, boolean isComplete, boolean b1) {
  if (!isComplete) {
   if (yScroll < getHeight()) {
    mDescText.setText("    ");
   } else {
    mDescText.setText("      ");
   }

   //         ,           
   if (!isRelease)
    mCircleView.setRotation(((float) yScroll) / getHeight() * 360f);
  }


 }

 @Override
 public void onRelease() {
  isRelease = true;
 }

 @Override
 public void onComplete() {
  anim.cancel();
  mDescText.setText("    ");
 }

 @Override
 public void onReset() {
  //   ,         
  mCircleView.setRotation(0f);
 }
}

레이아웃 파일

<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="#ECEDF0"
 >

 <com.aspsine.swipetoloadlayout.SwipeToLoadLayout
  android:id="@+id/swipeToLoadLayout"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <com.mahao.alex.systemwidgetdemo.recycleView.swipetoloadlayout.CircleRefreshHeaderView
   android:id="@+id/swipe_refresh_header"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" />

  <android.support.v7.widget.RecyclerView
   android:id="@+id/swipe_target"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:scrollbars="vertical" />

  <com.mahao.alex.systemwidgetdemo.recycleView.swipetoloadlayout.LoaderMoreView
   android:id="@+id/swipe_load_more_footer"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:gravity="center"
   android:padding="20dp" />
 </com.aspsine.swipetoloadlayout.SwipeToLoadLayout>


</RelativeLayout>


public class SwipeToLayoutActivity extends AppCompatActivity implements OnRefreshListener, OnLoadMoreListener {



 private RecyclerView mRecycleView;

 SwipeToLoadLayout swipeToLoadLayout;

 private HomeAdapter adapter;


 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_recycle_swipetolayout);


  swipeToLoadLayout = ((SwipeToLoadLayout) findViewById(R.id.swipeToLoadLayout));


  mRecycleView = ((RecyclerView) findViewById(R.id.swipe_target));


  adapter = new HomeAdapter();

  //            ,Orientation --> VERTICAL:   HORIZONTAL:  
  LinearLayoutManager layoutManager = new LinearLayoutManager(this);
  layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

//  StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);

  //     
  mRecycleView.addItemDecoration(new DividerItemDecoration(getApplicationContext(), DividerItemDecoration.VERTICAL_LIST));

  mRecycleView.setLayoutManager(layoutManager);

  mRecycleView.setItemAnimator(new DefaultItemAnimator());

  mRecycleView.setAdapter(adapter);

  adapter.refresh();

  /**
   *              
   */
  swipeToLoadLayout.setOnRefreshListener(this);
  swipeToLoadLayout.setOnLoadMoreListener(this);

 }




 @Override
 public void onRefresh() {
  swipeToLoadLayout.postDelayed(new Runnable() {
   @Override
   public void run() {
    adapter.refresh();
    swipeToLoadLayout.setRefreshing(false);
   }
  },2000);
 }

 @Override
 public void onLoadMore() {
  swipeToLoadLayout.postDelayed(new Runnable() {
   @Override
   public void run() {

    adapter.add();
    swipeToLoadLayout.setLoadingMore(false);
   }
  },2000);
 }
}

OK。틀림없이 동료 들 이 이 프레임 워 크 를 사용 할 때 계속 틀 렸 을 것 이다.왜,프레임 의 원본 코드 를 보면 다음 과 같은 단락 이 있다.

this.mHeaderView = this.findViewById(id.swipe_refresh_header);
 this.mTargetView = this.findViewById(id.swipe_target);
 this.mFooterView = this.findViewById(id.swipe_load_more_footer);
이 를 통 해 알 수 있 듯 이 작 가 는 고정된 id 값 에 따라 가 져 왔 기 때문에 우리 의 레이아웃 파일 에 고정된 세 개의 id 를 사용 해 야 합 니 다.
필요 하 다 면,소스 코드 를 시스템 widgetdemo 에서 가 져 올 수 있 습 니 다.
이상 은 본 고의 모든 내용 입 니 다.여러분 이 안 드 로 이 드 소프트웨어 프로 그래 밍 을 배 우 는 데 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기