快速自定义的各种想要的上啦刷新下拉加载的view

            大家在各自的项目中肯定会使用到到各种各样的自己定义的view,最常见的是自定义listview啊,gridview啊等视图空间,在自定义这些控件以后,大家会发现定义的好的视图空间需要上拉刷新下拉加载的功能:

            大家先看代码:

public class PullToRefreshListViewCompantPlan extends PullToRefreshAdapterViewBase<ListViewCompatPlan>{
    public PullToRefreshListViewCompantPlan(Context context) {
        super(context);
    }
    public PullToRefreshListViewCompantPlan(Context context, AttributeSet attrs) {
        super(context,attrs);
    }
    public PullToRefreshListViewCompantPlan(Context context, Mode mode) {
        super(context, mode);
    }
    public PullToRefreshListViewCompantPlan(Context context, Mode mode, AnimationStyle style) {
        super(context, mode, style);
    }
    @Override
    public Orientation getPullToRefreshScrollDirection() {
        return Orientation.VERTICAL;
    }
    @Override
    protected ListViewCompatPlan createRefreshableView(Context context, AttributeSet attrs) {
        final ListViewCompatPlan lv;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            lv = new InternalExpandableListViewSDK9(context, attrs);
        } else {
            lv = new InternalExpandableListView(context, attrs);
        }

        // Set it to this so it can be used in ListActivity/ListFragment
        lv.setId(android.R.id.list);
        return lv;
    }
    class InternalExpandableListView extends ListViewCompatPlan implements EmptyViewMethodAccessor {

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

        @Override
        public void setEmptyView(View emptyView) {
            PullToRefreshListViewCompantPlan.this.setEmptyView(emptyView);
        }

        @Override
        public void setEmptyViewInternal(View emptyView) {
            super.setEmptyView(emptyView);
        }
    }
    @TargetApi(9)
    final class InternalExpandableListViewSDK9 extends InternalExpandableListView {

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

        @Override
        protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,
                                       int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {

            final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
                    scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);

            // Does all of the hard work...
            OverscrollHelper.overScrollBy(PullToRefreshListViewCompantPlan.this, deltaX, scrollX, deltaY, scrollY,
                    isTouchEvent);

            return returnValue;
        }
    }
}
其中1.<ListViewCompantPlan>中的泛型是大家自己自定义的view;

        2.getPullToRefreshScrollDirection()方法标明刷新的方向,返回的是Oriention.VERTICAL:标明是垂直方向上下刷新

        3.createRefreshableView 创建刷新的view,其中setEmptyView给自定义的view设置空view;overScrollBy创建出刷新的view。

       继承与PullToRefreshAdapterViewBase<T extends AbsListView> 代码如下:

public abstract class PullToRefreshAdapterViewBase<T extends AbsListView> extends PullToRefreshBase<T> implements
      OnScrollListener {

   private static FrameLayout.LayoutParams convertEmptyViewLayoutParams(ViewGroup.LayoutParams lp) {
      FrameLayout.LayoutParams newLp = null;

      if (null != lp) {
         newLp = new FrameLayout.LayoutParams(lp);

         if (lp instanceof LayoutParams) {
            newLp.gravity = ((LayoutParams) lp).gravity;
         } else {
            newLp.gravity = Gravity.CENTER;
         }
      }

      return newLp;
   }

   private boolean mLastItemVisible;
   private OnScrollListener mOnScrollListener;
   private OnLastItemVisibleListener mOnLastItemVisibleListener;
   private View mEmptyView;

   private IndicatorLayout mIndicatorIvTop;
   private IndicatorLayout mIndicatorIvBottom;

   private boolean mShowIndicator;
   private boolean mScrollEmptyView = true;

   public PullToRefreshAdapterViewBase(Context context) {
      super(context);
      mRefreshableView.setOnScrollListener(this);
   }

   public PullToRefreshAdapterViewBase(Context context, AttributeSet attrs) {
      super(context, attrs);
      mRefreshableView.setOnScrollListener(this);
   }

   public PullToRefreshAdapterViewBase(Context context, Mode mode) {
      super(context, mode);
      mRefreshableView.setOnScrollListener(this);
   }

   public PullToRefreshAdapterViewBase(Context context, Mode mode, AnimationStyle animStyle) {
      super(context, mode, animStyle);
      mRefreshableView.setOnScrollListener(this);
   }

   /**
    * Gets whether an indicator graphic should be displayed when the View is in
    * a state where a Pull-to-Refresh can happen. An example of this state is
    * when the Adapter View is scrolled to the top and the mode is set to
    * {@link Mode#PULL_FROM_START}. The default value is <var>true</var> if
    * {@link PullToRefreshBase#isPullToRefreshOverScrollEnabled()
    * isPullToRefreshOverScrollEnabled()} returns false.
    * 
    * @return true if the indicators will be shown
    */
   public boolean getShowIndicator() {
      return mShowIndicator;
   }

   public final void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
         final int totalItemCount) {

      if (DEBUG) {
         Log.d(LOG_TAG, "First Visible: " + firstVisibleItem + ". Visible Count: " + visibleItemCount
               + ". Total Items:" + totalItemCount);
      }

      /**
       * Set whether the Last Item is Visible. lastVisibleItemIndex is a
       * zero-based index, so we minus one totalItemCount to check
       */
      if (null != mOnLastItemVisibleListener) {
         mLastItemVisible = (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1);
      }

      // If we're showing the indicator, check positions...
      if (getShowIndicatorInternal()) {
         updateIndicatorViewsVisibility();
      }

      // Finally call OnScrollListener if we have one
      if (null != mOnScrollListener) {
         mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
      }
   }

   public final void onScrollStateChanged(final AbsListView view, final int state) {
      /**
       * Check that the scrolling has stopped, and that the last item is
       * visible.
       */
      if (state == OnScrollListener.SCROLL_STATE_IDLE && null != mOnLastItemVisibleListener && mLastItemVisible) {
         mOnLastItemVisibleListener.onLastItemVisible();
      }

      if (null != mOnScrollListener) {
         mOnScrollListener.onScrollStateChanged(view, state);
      }
   }

   /**
    * Pass-through method for {@link PullToRefreshBase#getRefreshableView()
    * getRefreshableView()}.
    * {@link AdapterView#setAdapter(Adapter)}
    * setAdapter(adapter)}. This is just for convenience!
    * 
    * @param adapter - Adapter to set
    */
   public void setAdapter(ListAdapter adapter) {
      ((AdapterView<ListAdapter>) mRefreshableView).setAdapter(adapter);
   }

   /**
    * Sets the Empty View to be used by the Adapter View.
    * <p/>
    * We need it handle it ourselves so that we can Pull-to-Refresh when the
    * Empty View is shown.
    * <p/>
    * Please note, you do <strong>not</strong> usually need to call this method
    * yourself. Calling setEmptyView on the AdapterView will automatically call
    * this method and set everything up. This includes when the Android
    * Framework automatically sets the Empty View based on it's ID.
    * 
    * @param newEmptyView - Empty View to be used
    */
   public final void setEmptyView(View newEmptyView) {
      FrameLayout refreshableViewWrapper = getRefreshableViewWrapper();

      if (null != newEmptyView) {
         // New view needs to be clickable so that Android recognizes it as a
         // target for Touch Events
         newEmptyView.setClickable(true);

         ViewParent newEmptyViewParent = newEmptyView.getParent();
         if (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) {
            ((ViewGroup) newEmptyViewParent).removeView(newEmptyView);
         }

         // We need to convert any LayoutParams so that it works in our
         // FrameLayout
         FrameLayout.LayoutParams lp = convertEmptyViewLayoutParams(newEmptyView.getLayoutParams());
         if (null != lp) {
            refreshableViewWrapper.addView(newEmptyView, lp);
         } else {
            refreshableViewWrapper.addView(newEmptyView);
         }
      }

      if (mRefreshableView instanceof EmptyViewMethodAccessor) {
         ((EmptyViewMethodAccessor) mRefreshableView).setEmptyViewInternal(newEmptyView);
      } else {
         mRefreshableView.setEmptyView(newEmptyView);
      }
      mEmptyView = newEmptyView;
   }

   /**
    * Pass-through method for {@link PullToRefreshBase#getRefreshableView()
    * getRefreshableView()}.
    * {@link AdapterView#setOnItemClickListener(OnItemClickListener)
    * setOnItemClickListener(listener)}. This is just for convenience!
    * 
    * @param listener - OnItemClickListener to use
    */
   public void setOnItemClickListener(OnItemClickListener listener) {
      mRefreshableView.setOnItemClickListener(listener);
   }

   public final void setOnLastItemVisibleListener(OnLastItemVisibleListener listener) {
      mOnLastItemVisibleListener = listener;
   }

   public final void setOnScrollListener(OnScrollListener listener) {
      mOnScrollListener = listener;
   }

   public final void setScrollEmptyView(boolean doScroll) {
      mScrollEmptyView = doScroll;
   }

   /**
    * Sets whether an indicator graphic should be displayed when the View is in
    * a state where a Pull-to-Refresh can happen. An example of this state is
    * when the Adapter View is scrolled to the top and the mode is set to
    * {@link Mode#PULL_FROM_START}
    * 
    * @param showIndicator - true if the indicators should be shown.
    */
   public void setShowIndicator(boolean showIndicator) {
      mShowIndicator = showIndicator;

      if (getShowIndicatorInternal()) {
         // If we're set to Show Indicator, add/update them
         addIndicatorViews();
      } else {
         // If not, then remove then
         removeIndicatorViews();
      }
   }

   ;

   @Override
   protected void onPullToRefresh() {
      super.onPullToRefresh();

      if (getShowIndicatorInternal()) {
         switch (getCurrentMode()) {
            case PULL_FROM_END:
               mIndicatorIvBottom.pullToRefresh();
               break;
            case PULL_FROM_START:
               mIndicatorIvTop.pullToRefresh();
               break;
            default:
               // NO-OP
               break;
         }
      }
   }

   protected void onRefreshing(boolean doScroll) {
      super.onRefreshing(doScroll);

      if (getShowIndicatorInternal()) {
         updateIndicatorViewsVisibility();
      }
   }

   @Override
   protected void onReleaseToRefresh() {
      super.onReleaseToRefresh();

      if (getShowIndicatorInternal()) {
         switch (getCurrentMode()) {
            case PULL_FROM_END:
               mIndicatorIvBottom.releaseToRefresh();
               break;
            case PULL_FROM_START:
               mIndicatorIvTop.releaseToRefresh();
               break;
            default:
               // NO-OP
               break;
         }
      }
   }

   @Override
   protected void onReset() {
      super.onReset();

      if (getShowIndicatorInternal()) {
         updateIndicatorViewsVisibility();
      }
   }

   @Override
   protected void handleStyledAttributes(TypedArray a) {
      // Set Show Indicator to the XML value, or default value
      mShowIndicator = a.getBoolean(R.styleable.PullToRefresh_ptrShowIndicator, !isPullToRefreshOverScrollEnabled());
   }

   protected boolean isReadyForPullStart() {
      return isFirstItemVisible();
   }

   protected boolean isReadyForPullEnd() {
      return isLastItemVisible();
   }

   @Override
   protected void onScrollChanged(int l, int t, int oldl, int oldt) {
      super.onScrollChanged(l, t, oldl, oldt);
      if (null != mEmptyView && !mScrollEmptyView) {
         mEmptyView.scrollTo(-l, -t);
      }
   }

   @Override
   protected void updateUIForMode() {
      super.updateUIForMode();

      // Check Indicator Views consistent with new Mode
      if (getShowIndicatorInternal()) {
         addIndicatorViews();
      } else {
         removeIndicatorViews();
      }
   }

   private void addIndicatorViews() {
      Mode mode = getMode();
      FrameLayout refreshableViewWrapper = getRefreshableViewWrapper();

      if (mode.showHeaderLoadingLayout() && null == mIndicatorIvTop) {
         // If the mode can pull down, and we don't have one set already
         mIndicatorIvTop = new IndicatorLayout(getContext(), Mode.PULL_FROM_START);
         FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
               ViewGroup.LayoutParams.WRAP_CONTENT);
         params.rightMargin = getResources().getDimensionPixelSize(R.dimen.indicator_right_padding);
         params.gravity = Gravity.TOP | Gravity.RIGHT;
         refreshableViewWrapper.addView(mIndicatorIvTop, params);

      } else if (!mode.showHeaderLoadingLayout() && null != mIndicatorIvTop) {
         // If we can't pull down, but have a View then remove it
         refreshableViewWrapper.removeView(mIndicatorIvTop);
         mIndicatorIvTop = null;
      }

      if (mode.showFooterLoadingLayout() && null == mIndicatorIvBottom) {
         // If the mode can pull down, and we don't have one set already
         mIndicatorIvBottom = new IndicatorLayout(getContext(), Mode.PULL_FROM_END);
         FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
               ViewGroup.LayoutParams.WRAP_CONTENT);
         params.rightMargin = getResources().getDimensionPixelSize(R.dimen.indicator_right_padding);
         params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
         refreshableViewWrapper.addView(mIndicatorIvBottom, params);

      } else if (!mode.showFooterLoadingLayout() && null != mIndicatorIvBottom) {
         // If we can't pull down, but have a View then remove it
         refreshableViewWrapper.removeView(mIndicatorIvBottom);
         mIndicatorIvBottom = null;
      }
   }

   private boolean getShowIndicatorInternal() {
      return mShowIndicator && isPullToRefreshEnabled();
   }

   private boolean isFirstItemVisible() {
      final Adapter adapter = mRefreshableView.getAdapter();

      if (null == adapter || adapter.isEmpty()) {
         if (DEBUG) {
            Log.d(LOG_TAG, "isFirstItemVisible. Empty View.");
         }
         return true;

      } else {

         /**
          * This check should really just be:
          * mRefreshableView.getFirstVisiblePosition() == 0, but PtRListView
          * internally use a HeaderView which messes the positions up. For
          * now we'll just add one to account for it and rely on the inner
          * condition which checks getTop().
          */
         if (mRefreshableView.getFirstVisiblePosition() <= 1) {
            final View firstVisibleChild = mRefreshableView.getChildAt(0);
            if (firstVisibleChild != null) {
               return firstVisibleChild.getTop() >= mRefreshableView.getTop();
            }
         }
      }

      return false;
   }

   private boolean isLastItemVisible() {
      final Adapter adapter = mRefreshableView.getAdapter();

      if (null == adapter || adapter.isEmpty()) {
         if (DEBUG) {
            Log.d(LOG_TAG, "isLastItemVisible. Empty View.");
         }
         return true;
      } else {
         final int lastItemPosition = mRefreshableView.getCount() - 1;
         final int lastVisiblePosition = mRefreshableView.getLastVisiblePosition();

         if (DEBUG) {
            Log.d(LOG_TAG, "isLastItemVisible. Last Item Position: " + lastItemPosition + " Last Visible Pos: "
                  + lastVisiblePosition);
         }

         /**
          * This check should really just be: lastVisiblePosition ==
          * lastItemPosition, but PtRListView internally uses a FooterView
          * which messes the positions up. For me we'll just subtract one to
          * account for it and rely on the inner condition which checks
          * getBottom().
          */
         if (lastVisiblePosition >= lastItemPosition - 1) {
            final int childIndex = lastVisiblePosition - mRefreshableView.getFirstVisiblePosition();
            final View lastVisibleChild = mRefreshableView.getChildAt(childIndex);
            if (lastVisibleChild != null) {
               return lastVisibleChild.getBottom() <= mRefreshableView.getBottom();
            }
         }
      }

      return false;
   }

   private void removeIndicatorViews() {
      if (null != mIndicatorIvTop) {
         getRefreshableViewWrapper().removeView(mIndicatorIvTop);
         mIndicatorIvTop = null;
      }

      if (null != mIndicatorIvBottom) {
         getRefreshableViewWrapper().removeView(mIndicatorIvBottom);
         mIndicatorIvBottom = null;
      }
   }

   private void updateIndicatorViewsVisibility() {
      if (null != mIndicatorIvTop) {
         if (!isRefreshing() && isReadyForPullStart()) {
            if (!mIndicatorIvTop.isVisible()) {
               mIndicatorIvTop.show();
            }
         } else {
            if (mIndicatorIvTop.isVisible()) {
               mIndicatorIvTop.hide();
            }
         }
      }

      if (null != mIndicatorIvBottom) {
         if (!isRefreshing() && isReadyForPullEnd()) {
            if (!mIndicatorIvBottom.isVisible()) {
               mIndicatorIvBottom.show();
            }
         } else {
            if (mIndicatorIvBottom.isVisible()) {
               mIndicatorIvBottom.hide();
            }
         }
      }
   }
   public final void setSelection(int scrollTop) {
      mRefreshableView.setSelection(scrollTop);
   }

   public final int getFirstVisiblePosition() {

      return mRefreshableView.getFirstVisiblePosition();
   }
}
其中PullToRefreshBase<T extends View>代码放在附件里面了;

       大家想要实现上啦刷新下拉加载的功能只需要在第一个累中把泛型里面的换成自己想用的view即可:

       使用方法如下:

lv_product.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListViewCompatProduct>() {
    @Override
    public void onPullDownToRefresh(PullToRefreshBase<ListViewCompatProduct> refreshView) {
    }
    @Override
    public void onPullUpToRefresh(PullToRefreshBase<ListViewCompatProduct> refreshView) {
        if (CommonUtils.getAPNType(AppApplication.getContext()) == 0) {
            // 没有网络
            Toast.makeText(MyAttentionActivity.this,"断网了,请连接网络!",Toast.LENGTH_SHORT).show();
        } else{
            getData(uid,"3116",""+indexs,true);
        }
    }
});
上啦和下拉的方法都在上面,在请求加载完毕以后呢,需要使用onRefreshComplete()方法关闭刷新的视图,判断加载的数据有没有返回完整的数据,判断时候还还有多余的数据,假设每次加载都返回10条数据,举例如下:

if(myAttentions.getCmndity()!=null&&myAttentions.getCmndity().size()<10){
    lv_product.setMode(PullToRefreshBase.Mode.DISABLED);
    if (indexs != 0) {
        Toast.makeText(MyAttentionActivity.this, "没有更多数据了", Toast.LENGTH_SHORT).show();
    }
}else{
    lv_product.setMode(PullToRefreshBase.Mode.PULL_FROM_END);
    indexs++;
}
好啦,这就完成啦,写的不好大家不要喷我。。。谢谢

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值