From c0bc8da86f09a1e8b418e801ca15c43534d3cbd9 Mon Sep 17 00:00:00 2001
From: xuxiuxi <xuxiuxi@454eff88-639b-444f-9e54-f578c98de674>
Date: 星期一, 17 四月 2017 11:21:24 +0800
Subject: [PATCH] 

---
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/LoadingLayout.java                |  114 ++++
 VisitFace/DemoForBsk/app/src/main/res/layout/load_more.xml                                               |   16 
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshAdapterViewBase.java |  180 +++++++
 VisitFace/DemoForBsk/app/src/main/res/layout/no_more.xml                                                 |   16 
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/CommonVariables.java             |    3 
 VisitFace/DemoForBsk/app/src/main/res/layout/reach_bottom.xml                                            |   16 
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/ResultBean.java                  |    7 
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/fragment/VisitFragment.java                     |   13 
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/EmptyViewMethodAccessor.java      |   33 +
 VisitFace/DemoForBsk/app/src/main/res/values/strings.xml                                                 |    4 
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/widget/visit/VisitLeftListView.java             |   22 
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshBase.java            |  749 +++++++++++++++++++++++++++++
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/BaseCommonCallBack.java          |   12 
 VisitFace/DemoForBsk/app/src/main/res/drawable/pulltorefresh_down_arrow.png                              |    0 
 VisitFace/DemoForBsk/app/src/main/res/drawable/pulltorefresh_up_arrow.png                                |    0 
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/service/VisitMng.java                           |   16 
 VisitFace/DemoForBsk/app/src/main/res/layout/pull_to_refresh_header.xml                                  |   38 +
 VisitFace/DemoForBsk/app/src/main/res/values/attrs.xml                                                   |   10 
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/adapter/VisitFragment.java                      |   28 +
 VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshListView.java        |  208 ++++++++
 20 files changed, 1,476 insertions(+), 9 deletions(-)

diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/adapter/VisitFragment.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/adapter/VisitFragment.java
index 410f5bc..6de9df2 100644
--- a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/adapter/VisitFragment.java
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/adapter/VisitFragment.java
@@ -10,6 +10,7 @@
 import com.camnter.easyrecyclerview.holder.EasyRecyclerViewHolder;
 import com.facebook.drawee.view.SimpleDraweeView;
 
+import cn.com.basic.face.discern.common.CommonVariables;
 import cn.com.basic.face.discern.query.item.VisitQueryItem;
 import cn.com.basic.face.util.AppApi;
 
@@ -22,11 +23,27 @@
 
         @Override
         public int[] getItemLayouts() {
-            return new int[]{R.layout.fragment_visit_left_date_row,R.layout.fragment_visit_left_person_row};
+            return new int[]{R.layout.fragment_visit_left_date_row,R.layout.fragment_visit_left_person_row,R.layout.load_more, R.layout.no_more, R.layout.reach_bottom};
         }
 
         @Override
         public void onBindRecycleViewHolder(EasyRecyclerViewHolder viewHolder, final int position) {
+            if (getItem(position) instanceof Integer && ((int)getItem(position))== CommonVariables.Page.reachBottom) {
+                return;
+            }
+            if (getItem(position) instanceof Integer && ((int)getItem(position))== CommonVariables.Page.noMorePage) {
+                return;
+            }
+            if (getItem(position) instanceof Integer && ((int)getItem(position))== CommonVariables.Page.hasMorePages) {
+                TextView load_more_text_view = viewHolder.findViewById(R.id.load_more_text_view);
+                load_more_text_view.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        cn.com.basic.face.fragment.VisitFragment.getInstance().append();
+                    }
+                });
+                return;
+            }
             if(!(getItem(position) instanceof String)) {
                 final RadioButton fragment_visit_left_person_row_check_box = viewHolder.findViewById(R.id.fragment_visit_left_person_row_check_box);
                 TextView fragment_visit_left_person_row_name = viewHolder.findViewById(R.id.fragment_visit_left_person_row_name);
@@ -75,6 +92,15 @@
 
         @Override
         public int getRecycleViewItemType(int position) {
+            if (getItem(position) instanceof Integer && ((int)getItem(position))== CommonVariables.Page.reachBottom) {
+                return 4;
+            }
+            if (getItem(position) instanceof Integer && ((int)getItem(position))== CommonVariables.Page.noMorePage) {
+                return 3;
+            }
+            if (getItem(position) instanceof Integer && ((int)getItem(position))== CommonVariables.Page.hasMorePages) {
+                return 2;
+            }
             if(!(getItem(position) instanceof String)) {
                 return 1;
             }
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/BaseCommonCallBack.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/BaseCommonCallBack.java
index eb2dc0d..6bce6fc 100644
--- a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/BaseCommonCallBack.java
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/BaseCommonCallBack.java
@@ -60,4 +60,16 @@
         System.out.print("hello");
     }
 
+    public int getPageNum() {
+        return resultBean.getPageNum();
+    }
+
+    public int getTotalPages() {
+        return resultBean.getTotalPages();
+    }
+
+    public boolean hasMorePages() {
+        return resultBean.getPageNum() < resultBean.getTotalPages();
+    }
+
 }
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/CommonVariables.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/CommonVariables.java
index a6e9142..6c7c99f 100644
--- a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/CommonVariables.java
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/CommonVariables.java
@@ -49,6 +49,9 @@
 	public static class Page {
 		public static final String PAGE_SIZE = "pageSize";
 		public static final String PAGE_NUM = "pageNum";
+		public static final int hasMorePages = 1;
+		public static final int noMorePage = 2;
+        public static final int reachBottom = 3;
 	}
 
 }
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/ResultBean.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/ResultBean.java
index ebd4dc5..c21ee31 100644
--- a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/ResultBean.java
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/discern/common/ResultBean.java
@@ -14,6 +14,7 @@
 	private String message;
 	private Object data;
 	private int totalPages;
+	private int pageNum;
 
 
 	public String getCode() {
@@ -74,5 +75,11 @@
 		this.totalPages = totalPages;
 	}
 
+	public void setPageNum(int pageNum) {
+		this.pageNum = pageNum;
+	}
 
+	public int getPageNum() {
+		return pageNum;
+	}
 }
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/fragment/VisitFragment.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/fragment/VisitFragment.java
index 0b3ce6b..ae1a352 100644
--- a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/fragment/VisitFragment.java
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/fragment/VisitFragment.java
@@ -69,6 +69,8 @@
     @ViewInject(R.id.fragment_visit_right_head_photo_placeholder_text_view)
     private TextView fragment_visit_right_head_photo_placeholder_text_view;
 
+    int pageNum = 1;
+
     public int[] getLeftRightLayoutIds() {
         return new int[]{R.layout.fragment_visit_left, R.layout.fragment_visit_right};
     }
@@ -100,8 +102,14 @@
         }
     }
 
-    private void reloadList() {
-        VisitMng.getInstance().findLeftVisitorList(fragment_visit_left_search.getText().toString());
+    public void append() {
+        VisitMng.getInstance().findLeftVisitorList(fragment_visit_left_search.getText().toString(), pageNum, true);
+        pageNum++;
+    }
+
+    public void reloadList() {
+        pageNum=1;
+        VisitMng.getInstance().findLeftVisitorList(fragment_visit_left_search.getText().toString(), pageNum, false);
     }
 
     public void setVisitInfo(VisitQueryItem item) {
@@ -125,7 +133,6 @@
         fragment_visit_right_head_photo_placeholder_text_view.setVisibility(View.INVISIBLE);
         fragment_visit_right_head_photo_placeholder_image.setVisibility(View.INVISIBLE);
         fragment_visit_right_card_photo_placeholder_image.setVisibility(View.INVISIBLE);
-
     }
 
 }
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/EmptyViewMethodAccessor.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/EmptyViewMethodAccessor.java
new file mode 100644
index 0000000..b9b6db4
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/EmptyViewMethodAccessor.java
@@ -0,0 +1,33 @@
+package cn.com.basic.face.pulltorefresh;
+
+import android.view.View;
+import android.widget.ImageView;
+
+/**
+ * Interface that allows PullToRefreshBase to hijack the call to
+ * AdapterView.setEmptyView()
+ *
+ * @author chris
+ */
+public interface EmptyViewMethodAccessor {
+
+    /**
+     * Calls upto AdapterView.setEmptyView()
+     *
+     * @param View
+     *            to set as Empty View
+     */
+    public void setEmptyViewInternal(View emptyView);
+
+    /**
+     * Should call PullToRefreshBase.setEmptyView() which will then
+     * automatically call through to setEmptyViewInternal()
+     *
+     * @param View
+     *            to set as Empty View
+     */
+    public void setEmptyView(View emptyView);
+
+
+
+}
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/LoadingLayout.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/LoadingLayout.java
new file mode 100644
index 0000000..1cd6e57
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/LoadingLayout.java
@@ -0,0 +1,114 @@
+package cn.com.basic.face.pulltorefresh;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.RotateAnimation;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.bsk.zhangbo.demoforbsk.R;
+
+public class LoadingLayout extends FrameLayout {
+
+    static final int DEFAULT_ROTATION_ANIMATION_DURATION = 150;
+
+    private final ImageView headerImage;
+    private final ProgressBar headerProgress;
+    private final TextView headerText;
+
+    private String pullLabel;
+    private String refreshingLabel;
+    private String releaseLabel;
+
+    private final Animation rotateAnimation, resetRotateAnimation;
+
+    public LoadingLayout(Context context, final int mode, String releaseLabel,
+                         String pullLabel, String refreshingLabel) {
+        super(context);
+        ViewGroup header = (ViewGroup) LayoutInflater.from(context).inflate(
+                R.layout.pull_to_refresh_header, this);
+        headerText = (TextView) header.findViewById(R.id.pull_to_refresh_text);
+        headerImage = (ImageView) header
+                .findViewById(R.id.pull_to_refresh_image);
+        headerProgress = (ProgressBar) header
+                .findViewById(R.id.pull_to_refresh_progress);
+
+        final Interpolator interpolator = new LinearInterpolator();
+        rotateAnimation = new RotateAnimation(0, -180,
+                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
+                0.5f);
+        rotateAnimation.setInterpolator(interpolator);
+        rotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION);
+        rotateAnimation.setFillAfter(true);
+
+        resetRotateAnimation = new RotateAnimation(-180, 0,
+                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
+                0.5f);
+        resetRotateAnimation.setInterpolator(interpolator);
+        resetRotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION);
+        resetRotateAnimation.setFillAfter(true);
+
+        this.releaseLabel = releaseLabel;
+        this.pullLabel = pullLabel;
+        this.refreshingLabel = refreshingLabel;
+
+        switch (mode) {
+            case PullToRefreshBase.MODE_PULL_UP_TO_REFRESH:
+                headerImage.setImageResource(R.drawable.pulltorefresh_up_arrow);
+                break;
+            case PullToRefreshBase.MODE_PULL_DOWN_TO_REFRESH:
+            default:
+                headerImage.setImageResource(R.drawable.pulltorefresh_down_arrow);
+                break;
+        }
+    }
+
+    public void reset() {
+        headerText.setText(pullLabel);
+        headerImage.setVisibility(View.VISIBLE);
+        headerProgress.setVisibility(View.GONE);
+    }
+
+    public void releaseToRefresh() {
+        headerText.setText(releaseLabel);
+        headerImage.clearAnimation();
+        headerImage.startAnimation(rotateAnimation);
+    }
+
+    public void setPullLabel(String pullLabel) {
+        this.pullLabel = pullLabel;
+    }
+
+    public void refreshing() {
+        headerText.setText(refreshingLabel);
+        headerImage.clearAnimation();
+        headerImage.setVisibility(View.INVISIBLE);
+        headerProgress.setVisibility(View.VISIBLE);
+    }
+
+    public void setRefreshingLabel(String refreshingLabel) {
+        this.refreshingLabel = refreshingLabel;
+    }
+
+    public void setReleaseLabel(String releaseLabel) {
+        this.releaseLabel = releaseLabel;
+    }
+
+    public void pullToRefresh() {
+        headerText.setText(pullLabel);
+        headerImage.clearAnimation();
+        headerImage.startAnimation(resetRotateAnimation);
+    }
+
+    public void setTextColor(int color) {
+        headerText.setTextColor(color);
+    }
+
+}
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshAdapterViewBase.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshAdapterViewBase.java
new file mode 100644
index 0000000..509acc4
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshAdapterViewBase.java
@@ -0,0 +1,180 @@
+package cn.com.basic.face.pulltorefresh;
+
+
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.FrameLayout;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+
+
+
+public abstract class PullToRefreshAdapterViewBase<T extends AbsListView> extends PullToRefreshBase<T> implements
+        OnScrollListener {
+
+    private int lastSavedFirstVisibleItem = -1;
+    private OnScrollListener onScrollListener;
+    private OnLastItemVisibleListener onLastItemVisibleListener;
+    private View emptyView;
+    private FrameLayout refreshableViewHolder;
+    private ImageView mTopImageView;
+
+    public PullToRefreshAdapterViewBase(Context context) {
+        super(context);
+        refreshableView.setOnScrollListener(this);
+    }
+
+    public PullToRefreshAdapterViewBase(Context context, int mode) {
+        super(context, mode);
+        refreshableView.setOnScrollListener(this);
+    }
+
+    public PullToRefreshAdapterViewBase(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        refreshableView.setOnScrollListener(this);
+    }
+
+    abstract public ContextMenuInfo getContextMenuInfo();
+
+    public final void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
+                               final int totalItemCount) {
+
+        if (null != onLastItemVisibleListener) {
+            // detect if last item is visible
+            if (visibleItemCount > 0 && (firstVisibleItem + visibleItemCount == totalItemCount)) {
+                // only process first event
+                if (firstVisibleItem != lastSavedFirstVisibleItem) {
+                    lastSavedFirstVisibleItem = firstVisibleItem;
+                    onLastItemVisibleListener.onLastItemVisible();
+                }
+            }
+        }
+
+        if (null != onScrollListener) {
+            onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
+        }
+    }
+
+    public final void onScrollStateChanged(final AbsListView view, final int scrollState) {
+        if (null != onScrollListener) {
+            onScrollListener.onScrollStateChanged(view, scrollState);
+        }
+    }
+
+    public void setBackToTopView(ImageView mTopImageView){
+        this.mTopImageView = mTopImageView;
+        mTopImageView.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (refreshableView instanceof ListView ) {
+                    ((ListView)refreshableView).setSelection(0);
+                }else if(refreshableView instanceof GridView){
+                    ((GridView)refreshableView).setSelection(0);
+                }
+            }
+        });
+    }
+
+    /**
+     * Sets the Empty View to be used by the Adapter View.
+     *
+     * We need it handle it ourselves so that we can Pull-to-Refresh when the
+     * Empty View is shown.
+     *
+     * 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) {
+        // If we already have an Empty View, remove it
+        if (null != emptyView) {
+            refreshableViewHolder.removeView(emptyView);
+        }
+
+        if (null != newEmptyView) {
+            ViewParent newEmptyViewParent = newEmptyView.getParent();
+            if (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) {
+                ((ViewGroup) newEmptyViewParent).removeView(newEmptyView);
+            }
+
+            this.refreshableViewHolder.addView(newEmptyView, ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT);
+        }
+
+        if (refreshableView instanceof EmptyViewMethodAccessor) {
+            ((EmptyViewMethodAccessor) refreshableView).setEmptyViewInternal(newEmptyView);
+        } else {
+            this.refreshableView.setEmptyView(newEmptyView);
+        }
+    }
+
+    public final void setOnLastItemVisibleListener(OnLastItemVisibleListener listener) {
+        onLastItemVisibleListener = listener;
+    }
+
+    public final void setOnScrollListener(OnScrollListener listener) {
+        onScrollListener = listener;
+    }
+
+    protected void addRefreshableView(Context context, T refreshableView) {
+        refreshableViewHolder = new FrameLayout(context);
+        refreshableViewHolder.addView(refreshableView, ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT);
+        addView(refreshableViewHolder, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0, 1.0f));
+    };
+
+    protected boolean isReadyForPullDown() {
+        return isFirstItemVisible();
+    }
+
+    protected boolean isReadyForPullUp() {
+        return isLastItemVisible();
+    }
+
+    private boolean isFirstItemVisible() {
+        if (this.refreshableView.getCount() == 0) {
+            return true;
+        } else if (refreshableView.getFirstVisiblePosition() == 0) {
+
+            final View firstVisibleChild = refreshableView.getChildAt(0);
+
+            if (firstVisibleChild != null) {
+                return firstVisibleChild.getTop() >= refreshableView.getTop();
+            }
+        }
+
+        return false;
+    }
+
+    private boolean isLastItemVisible() {
+        final int count = this.refreshableView.getCount();
+        final int lastVisiblePosition = refreshableView.getLastVisiblePosition();
+
+        if (count == 0) {
+            return true;
+        } else if (lastVisiblePosition == count - 1) {
+
+            final int childIndex = lastVisiblePosition - refreshableView.getFirstVisiblePosition();
+            final View lastVisibleChild = refreshableView.getChildAt(childIndex);
+
+            if (lastVisibleChild != null) {
+                return lastVisibleChild.getBottom() <= refreshableView.getBottom();
+            }
+        }
+        return false;
+    }
+}
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshBase.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshBase.java
new file mode 100644
index 0000000..9aef86c
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshBase.java
@@ -0,0 +1,749 @@
+package cn.com.basic.face.pulltorefresh;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.widget.LinearLayout;
+
+import com.bsk.zhangbo.demoforbsk.R;
+
+public abstract class PullToRefreshBase<T extends View> extends LinearLayout {
+
+    final class SmoothScrollRunnable implements Runnable {
+
+        static final int ANIMATION_DURATION_MS = 190;
+        static final int ANIMATION_FPS = 1000 / 60;
+
+        private final Interpolator interpolator;
+        private final int scrollToY;
+        private final int scrollFromY;
+        private final Handler handler;
+
+        private boolean continueRunning = true;
+        private long startTime = -1;
+        private int currentY = -1;
+
+        public SmoothScrollRunnable(Handler handler, int fromY, int toY) {
+            this.handler = handler;
+            this.scrollFromY = fromY;
+            this.scrollToY = toY;
+            this.interpolator = new AccelerateDecelerateInterpolator();
+        }
+
+        @Override
+        public void run() {
+
+            /**
+             * Only set startTime if this is the first time we're starting, else
+             * actually calculate the Y delta
+             */
+            if (startTime == -1) {
+                startTime = System.currentTimeMillis();
+            } else {
+
+                /**
+                 * We do do all calculations in long to reduce software float
+                 * calculations. We use 1000 as it gives us good accuracy and
+                 * small rounding errors
+                 */
+                long normalizedTime = (1000 * (System.currentTimeMillis() - startTime))
+                        / ANIMATION_DURATION_MS;
+                normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0);
+
+                final int deltaY = Math
+                        .round((scrollFromY - scrollToY)
+                                * interpolator
+                                .getInterpolation(normalizedTime / 1000f));
+                this.currentY = scrollFromY - deltaY;
+                setHeaderScroll(currentY);
+            }
+
+            // If we're not at the target Y, keep going...
+            if (continueRunning && scrollToY != currentY) {
+                handler.postDelayed(this, ANIMATION_FPS);
+            }
+        }
+
+        public void stop() {
+            this.continueRunning = false;
+            this.handler.removeCallbacks(this);
+        }
+    };
+
+    // ===========================================================
+    // Constants
+    // ===========================================================
+
+    static final float FRICTION = 2.0f;
+
+    static final int PULL_TO_REFRESH = 0x0;
+    static final int RELEASE_TO_REFRESH = 0x1;
+    static final int REFRESHING = 0x2;
+    static final int MANUAL_REFRESHING = 0x3;
+
+    public static final int MODE_PULL_DOWN_TO_REFRESH = 0x1;
+    public static final int MODE_PULL_UP_TO_REFRESH = 0x2;
+    public static final int MODE_BOTH = 0x3;
+
+    // ===========================================================
+    // Fields
+    // ===========================================================
+
+    private int touchSlop;
+
+    private float initialMotionY;
+    private float lastMotionX;
+    private float lastMotionY;
+    private boolean isBeingDragged = false;
+
+    private int state = PULL_TO_REFRESH;
+    private int mode = MODE_PULL_DOWN_TO_REFRESH;
+    private int currentMode;
+
+    private boolean disableScrollingWhileRefreshing = true;
+
+    T refreshableView;
+    private boolean isPullToRefreshEnabled = true;
+
+    private LoadingLayout headerLayout;
+    private LoadingLayout footerLayout;
+    private int headerHeight;
+
+    private final Handler handler = new Handler();
+
+    private OnRefreshListener onRefreshListener;
+
+    private SmoothScrollRunnable currentSmoothScrollRunnable;
+
+    // ===========================================================
+    // Constructors
+    // ===========================================================
+
+    public PullToRefreshBase(Context context) {
+        super(context);
+        init(context, null);
+    }
+
+    public PullToRefreshBase(Context context, int mode) {
+        super(context);
+        this.mode = mode;
+        init(context, null);
+    }
+
+    public PullToRefreshBase(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs);
+    }
+
+    // ===========================================================
+    // Getter & Setter
+    // ===========================================================
+
+    /**
+     * Deprecated. Use {@link #getRefreshableView()} from now on.
+     *
+     * @deprecated
+     * @return The Refreshable View which is currently wrapped
+     */
+    public final T getAdapterView() {
+        return refreshableView;
+    }
+
+    /**
+     * Get the Wrapped Refreshable View. Anything returned here has already been
+     * added to the content view.
+     *
+     * @return The View which is currently wrapped
+     */
+    public final T getRefreshableView() {
+        return refreshableView;
+    }
+
+    /**
+     * Whether Pull-to-Refresh is enabled
+     *
+     * @return enabled
+     */
+    public final boolean isPullToRefreshEnabled() {
+        return isPullToRefreshEnabled;
+    }
+
+    /**
+     * Returns whether the widget has disabled scrolling on the Refreshable View
+     * while refreshing.
+     *
+     * @param true if the widget has disabled scrolling while refreshing
+     */
+    public final boolean isDisableScrollingWhileRefreshing() {
+        return disableScrollingWhileRefreshing;
+    }
+
+    /**
+     * Returns whether the Widget is currently in the Refreshing state
+     *
+     * @return true if the Widget is currently refreshing
+     */
+    public final boolean isRefreshing() {
+        return state == REFRESHING || state == MANUAL_REFRESHING;
+    }
+
+    /**
+     * By default the Widget disabled scrolling on the Refreshable View while
+     * refreshing. This method can change this behaviour.
+     *
+     * @param disableScrollingWhileRefreshing
+     *            - true if you want to disable scrolling while refreshing
+     */
+    public final void setDisableScrollingWhileRefreshing(
+            boolean disableScrollingWhileRefreshing) {
+        this.disableScrollingWhileRefreshing = disableScrollingWhileRefreshing;
+    }
+
+    /**
+     * Mark the current Refresh as complete. Will Reset the UI and hide the
+     * Refreshing View
+     */
+    public final void onRefreshComplete() {
+        if (state != PULL_TO_REFRESH) {
+            resetHeader();
+        }
+    }
+
+    /**
+     * Set OnRefreshListener for the Widget
+     *
+     * @param listener
+     *            - Listener to be used when the Widget is set to Refresh
+     */
+    public final void setOnRefreshListener(OnRefreshListener listener) {
+        onRefreshListener = listener;
+    }
+
+    /**
+     * A mutator to enable/disable Pull-to-Refresh for the current View
+     *
+     * @param enable
+     *            Whether Pull-To-Refresh should be used
+     */
+    public final void setPullToRefreshEnabled(boolean enable) {
+        this.isPullToRefreshEnabled = enable;
+    }
+
+    /**
+     * Set Text to show when the Widget is being pulled, and will refresh when
+     * released
+     *
+     * @param releaseLabel
+     *            - String to display
+     */
+    public void setReleaseLabel(String releaseLabel) {
+        if (null != headerLayout) {
+            headerLayout.setReleaseLabel(releaseLabel);
+        }
+        if (null != footerLayout) {
+            footerLayout.setReleaseLabel(releaseLabel);
+        }
+    }
+
+    /**
+     * Set Text to show when the Widget is being Pulled
+     *
+     * @param pullLabel
+     *            - String to display
+     */
+    public void setPullLabel(String pullLabel) {
+        if (null != headerLayout) {
+            headerLayout.setPullLabel(pullLabel);
+        }
+        if (null != footerLayout) {
+            footerLayout.setPullLabel(pullLabel);
+        }
+    }
+
+    /**
+     * Set Text to show when the Widget is refreshing
+     *
+     * @param refreshingLabel
+     *            - String to display
+     */
+    public void setRefreshingLabel(String refreshingLabel) {
+        if (null != headerLayout) {
+            headerLayout.setRefreshingLabel(refreshingLabel);
+        }
+        if (null != footerLayout) {
+            footerLayout.setRefreshingLabel(refreshingLabel);
+        }
+    }
+
+    public final void setRefreshing() {
+        this.setRefreshing(true);
+    }
+
+    /**
+     * Sets the Widget to be in the refresh state. The UI will be updated to
+     * show the 'Refreshing' view.
+     *
+     * @param doScroll
+     *            - true if you want to force a scroll to the Refreshing view.
+     */
+    public final void setRefreshing(boolean doScroll) {
+        if (!isRefreshing()) {
+            setRefreshingInternal(doScroll);
+            state = MANUAL_REFRESHING;
+        }
+    }
+
+    public final boolean hasPullFromTop() {
+        return currentMode != MODE_PULL_UP_TO_REFRESH;
+    }
+
+    // ===========================================================
+    // Methods for/from SuperClass/Interfaces
+    // ===========================================================
+
+    @Override
+    public final boolean onTouchEvent(MotionEvent event) {
+        if (!isPullToRefreshEnabled) {
+            return false;
+        }
+
+        if (isRefreshing() && disableScrollingWhileRefreshing) {
+            return true;
+        }
+
+        if (event.getAction() == MotionEvent.ACTION_DOWN
+                && event.getEdgeFlags() != 0) {
+            return false;
+        }
+
+        switch (event.getAction()) {
+
+            case MotionEvent.ACTION_MOVE: {
+                if (isBeingDragged) {
+                    lastMotionY = event.getY();
+                    this.pullEvent();
+                    return true;
+                }
+                break;
+            }
+
+            case MotionEvent.ACTION_DOWN: {
+                if (isReadyForPull()) {
+                    lastMotionY = initialMotionY = event.getY();
+                    return true;
+                }
+                break;
+            }
+
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP: {
+                if (isBeingDragged) {
+                    isBeingDragged = false;
+
+                    if (state == RELEASE_TO_REFRESH && null != onRefreshListener) {
+                        setRefreshingInternal(true);
+                        onRefreshListener.onRefresh();
+                    } else {
+                        smoothScrollTo(0);
+                    }
+                    return true;
+                }
+                break;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public final boolean onInterceptTouchEvent(MotionEvent event) {
+
+        if (!isPullToRefreshEnabled) {
+            return false;
+        }
+
+        if (isRefreshing() && disableScrollingWhileRefreshing) {
+            return true;
+        }
+
+        final int action = event.getAction();
+
+        if (action == MotionEvent.ACTION_CANCEL
+                || action == MotionEvent.ACTION_UP) {
+            isBeingDragged = false;
+            return false;
+        }
+
+        if (action != MotionEvent.ACTION_DOWN && isBeingDragged) {
+            return true;
+        }
+
+        switch (action) {
+            case MotionEvent.ACTION_MOVE: {
+                if (isReadyForPull()) {
+
+                    final float y = event.getY();
+                    final float dy = y - lastMotionY;
+                    final float yDiff = Math.abs(dy);
+                    final float xDiff = Math.abs(event.getX() - lastMotionX);
+
+                    if (yDiff > touchSlop && yDiff > xDiff) {
+                        if ((mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH)
+                                && dy >= 0.0001f && isReadyForPullDown()) {
+                            lastMotionY = y;
+                            isBeingDragged = true;
+                            if (mode == MODE_BOTH) {
+                                currentMode = MODE_PULL_DOWN_TO_REFRESH;
+                            }
+                        } else if ((mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH)
+                                && dy <= 0.0001f && isReadyForPullUp()) {
+                            lastMotionY = y;
+                            isBeingDragged = true;
+                            if (mode == MODE_BOTH) {
+                                currentMode = MODE_PULL_UP_TO_REFRESH;
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+            case MotionEvent.ACTION_DOWN: {
+                if (isReadyForPull()) {
+                    lastMotionY = initialMotionY = event.getY();
+                    lastMotionX = event.getX();
+                    isBeingDragged = false;
+                }
+                break;
+            }
+        }
+
+        return isBeingDragged;
+    }
+
+    protected void addRefreshableView(Context context, T refreshableView) {
+        addView(refreshableView, new LinearLayout.LayoutParams(
+                LayoutParams.FILL_PARENT, 0, 1.0f));
+    }
+
+    /**
+     * This is implemented by derived classes to return the created View. If you
+     * need to use a custom View (such as a custom ListView), override this
+     * method and return an instance of your custom class.
+     *
+     * Be sure to set the ID of the view in this method, especially if you're
+     * using a ListActivity or ListFragment.
+     *
+     * @param context
+     * @param attrs
+     *            AttributeSet from wrapped class. Means that anything you
+     *            include in the XML layout declaration will be routed to the
+     *            created View
+     * @return New instance of the Refreshable View
+     */
+    protected abstract T createRefreshableView(Context context,
+                                               AttributeSet attrs);
+
+    protected final int getCurrentMode() {
+        return currentMode;
+    }
+
+    protected final LoadingLayout getFooterLayout() {
+        return footerLayout;
+    }
+
+    protected final LoadingLayout getHeaderLayout() {
+        return headerLayout;
+    }
+
+    protected final int getHeaderHeight() {
+        return headerHeight;
+    }
+
+    protected final int getMode() {
+        return mode;
+    }
+
+    /**
+     * Implemented by derived class to return whether the View is in a state
+     * where the user can Pull to Refresh by scrolling down.
+     *
+     * @return true if the View is currently the correct state (for example, top
+     *         of a ListView)
+     */
+    protected abstract boolean isReadyForPullDown();
+
+    /**
+     * Implemented by derived class to return whether the View is in a state
+     * where the user can Pull to Refresh by scrolling up.
+     *
+     * @return true if the View is currently in the correct state (for example,
+     *         bottom of a ListView)
+     */
+    protected abstract boolean isReadyForPullUp();
+
+    // ===========================================================
+    // Methods
+    // ===========================================================
+
+    protected void resetHeader() {
+        state = PULL_TO_REFRESH;
+        isBeingDragged = false;
+
+        if (null != headerLayout) {
+            headerLayout.reset();
+        }
+        if (null != footerLayout) {
+            footerLayout.reset();
+        }
+
+        smoothScrollTo(0);
+    }
+
+    protected void setRefreshingInternal(boolean doScroll) {
+        state = REFRESHING;
+
+        if (null != headerLayout) {
+            headerLayout.refreshing();
+        }
+        if (null != footerLayout) {
+            footerLayout.refreshing();
+        }
+
+        if (doScroll) {
+            smoothScrollTo(currentMode == MODE_PULL_DOWN_TO_REFRESH ? -headerHeight
+                    : headerHeight);
+        }
+    }
+
+    protected final void setHeaderScroll(int y) {
+        scrollTo(0, y);
+    }
+
+    protected final void smoothScrollTo(int y) {
+        if (null != currentSmoothScrollRunnable) {
+            currentSmoothScrollRunnable.stop();
+        }
+
+        if (this.getScrollY() != y) {
+            this.currentSmoothScrollRunnable = new SmoothScrollRunnable(
+                    handler, getScrollY(), y);
+            handler.post(currentSmoothScrollRunnable);
+        }
+    }
+
+    private void init(Context context, AttributeSet attrs) {
+
+        setOrientation(LinearLayout.VERTICAL);
+
+        touchSlop = ViewConfiguration.getTouchSlop();
+
+        // Styleables from XML
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.PullToRefresh);
+        if (a.hasValue(R.styleable.PullToRefresh_mode)) {
+            mode = a.getInteger(R.styleable.PullToRefresh_mode,
+                    MODE_PULL_DOWN_TO_REFRESH);
+        }
+
+        // Refreshable View
+        // By passing the attrs, we can add ListView/GridView params via XML
+        refreshableView = this.createRefreshableView(context, attrs);
+        this.addRefreshableView(context, refreshableView);
+
+        // Loading View Strings
+        String pullLabel = context
+                .getString(R.string.pull_to_refresh_pull_label);
+        String refreshingLabel = context
+                .getString(R.string.pull_to_refresh_refreshing_label);
+        String releaseLabel = context
+                .getString(R.string.pull_to_refresh_release_label);
+
+        // Add Loading Views
+        if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) {
+            headerLayout = new LoadingLayout(context,
+                    MODE_PULL_DOWN_TO_REFRESH, releaseLabel, pullLabel,
+                    refreshingLabel);
+            addView(headerLayout, 0, new LinearLayout.LayoutParams(
+                    ViewGroup.LayoutParams.FILL_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT));
+            measureView(headerLayout);
+            headerHeight = headerLayout.getMeasuredHeight();
+        }
+        if (mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) {
+            footerLayout = new LoadingLayout(context, MODE_PULL_UP_TO_REFRESH,
+                    releaseLabel, pullLabel, refreshingLabel);
+            addView(footerLayout, new LinearLayout.LayoutParams(
+                    ViewGroup.LayoutParams.FILL_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT));
+            measureView(footerLayout);
+            headerHeight = footerLayout.getMeasuredHeight();
+        }
+
+        // Styleables from XML
+        if (a.hasValue(R.styleable.PullToRefresh_headerTextColor)) {
+            final int color = a.getColor(
+                    R.styleable.PullToRefresh_headerTextColor, Color.BLACK);
+            if (null != headerLayout) {
+                headerLayout.setTextColor(color);
+            }
+            if (null != footerLayout) {
+                footerLayout.setTextColor(color);
+            }
+        }
+        if (a.hasValue(R.styleable.PullToRefresh_headerBackground)) {
+            this.setBackgroundResource(a.getResourceId(
+                    R.styleable.PullToRefresh_headerBackground, Color.WHITE));
+        }
+        if (a.hasValue(R.styleable.PullToRefresh_adapterViewBackground)) {
+            refreshableView.setBackgroundResource(a.getResourceId(
+                    R.styleable.PullToRefresh_adapterViewBackground,
+                    Color.WHITE));
+        }
+        a.recycle();
+
+        // Hide Loading Views
+        switch (mode) {
+            case MODE_BOTH:
+                setPadding(0, -headerHeight, 0, -headerHeight);
+                break;
+            case MODE_PULL_UP_TO_REFRESH:
+                setPadding(0, 0, 0, -headerHeight);
+                break;
+            case MODE_PULL_DOWN_TO_REFRESH:
+            default:
+                setPadding(0, -headerHeight, 0, 0);
+                break;
+        }
+
+        // If we're not using MODE_BOTH, then just set currentMode to current
+        // mode
+        if (mode != MODE_BOTH) {
+            currentMode = mode;
+        }
+    }
+
+    private void measureView(View child) {
+        ViewGroup.LayoutParams p = child.getLayoutParams();
+        if (p == null) {
+            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT);
+        }
+
+        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
+        int lpHeight = p.height;
+        int childHeightSpec;
+        if (lpHeight > 0) {
+            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
+                    MeasureSpec.EXACTLY);
+        } else {
+            childHeightSpec = MeasureSpec.makeMeasureSpec(0,
+                    MeasureSpec.UNSPECIFIED);
+        }
+        child.measure(childWidthSpec, childHeightSpec);
+    }
+
+    /**
+     * Actions a Pull Event
+     *
+     * @return true if the Event has been handled, false if there has been no
+     *         change
+     */
+    private boolean pullEvent() {
+
+        final int newHeight;
+        final int oldHeight = this.getScrollY();
+
+        switch (currentMode) {
+            case MODE_PULL_UP_TO_REFRESH:
+                newHeight = Math.round(Math.max(initialMotionY - lastMotionY, 0)
+                        / FRICTION);
+                // newHeight = Math.round((initialMotionY - lastMotionY) /
+                // FRICTION);
+                break;
+            case MODE_PULL_DOWN_TO_REFRESH:
+            default:
+                newHeight = Math.round(Math.min(initialMotionY - lastMotionY, 0)
+                        / FRICTION);
+                // newHeight = Math.round((initialMotionY - lastMotionY) /
+                // FRICTION);
+                break;
+        }
+
+        setHeaderScroll(newHeight);
+
+        if (newHeight != 0) {
+            if (state == PULL_TO_REFRESH && headerHeight < Math.abs(newHeight)) {
+                state = RELEASE_TO_REFRESH;
+
+                switch (currentMode) {
+                    case MODE_PULL_UP_TO_REFRESH:
+                        footerLayout.releaseToRefresh();
+                        break;
+                    case MODE_PULL_DOWN_TO_REFRESH:
+                        headerLayout.releaseToRefresh();
+                        break;
+                }
+
+                return true;
+
+            } else if (state == RELEASE_TO_REFRESH
+                    && headerHeight >= Math.abs(newHeight)) {
+                state = PULL_TO_REFRESH;
+
+                switch (currentMode) {
+                    case MODE_PULL_UP_TO_REFRESH:
+                        footerLayout.pullToRefresh();
+                        break;
+                    case MODE_PULL_DOWN_TO_REFRESH:
+                        headerLayout.pullToRefresh();
+                        break;
+                }
+
+                return true;
+            }
+        }
+
+        return oldHeight != newHeight;
+    }
+
+    private boolean isReadyForPull() {
+        switch (mode) {
+            case MODE_PULL_DOWN_TO_REFRESH:
+                return isReadyForPullDown();
+            case MODE_PULL_UP_TO_REFRESH:
+                return isReadyForPullUp();
+            case MODE_BOTH:
+                return isReadyForPullUp() || isReadyForPullDown();
+        }
+        return false;
+    }
+
+    // ===========================================================
+    // Inner and Anonymous Classes
+    // ===========================================================
+
+    public static interface OnRefreshListener {
+
+        public void onRefresh();
+
+    }
+
+    public static interface OnLastItemVisibleListener {
+
+        public void onLastItemVisible();
+
+    }
+
+    @Override
+    public void setLongClickable(boolean longClickable) {
+        getRefreshableView().setLongClickable(longClickable);
+    }
+}
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshListView.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshListView.java
new file mode 100644
index 0000000..61d0836
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/pulltorefresh/PullToRefreshListView.java
@@ -0,0 +1,208 @@
+package cn.com.basic.face.pulltorefresh;
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.View;
+import android.widget.ListView;
+
+public class PullToRefreshListView extends PullToRefreshAdapterViewBase<ListView> {
+
+//	private LoadingLayout headerLoadingView;
+//	private LoadingLayout footerLoadingView;
+
+    class InternalListView extends ListView implements EmptyViewMethodAccessor {
+
+        public InternalListView(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        @Override
+        public void setEmptyView(View emptyView) {
+            PullToRefreshListView.this.setEmptyView(emptyView);
+        }
+
+        @Override
+        public void setEmptyViewInternal(View emptyView) {
+            super.setEmptyView(emptyView);
+        }
+
+        public ContextMenuInfo getContextMenuInfo() {
+            return super.getContextMenuInfo();
+        }
+    }
+
+    public PullToRefreshListView(Context context) {
+        super(context);
+        this.setDisableScrollingWhileRefreshing(false);
+    }
+
+    public PullToRefreshListView(Context context, int mode) {
+        super(context, mode);
+        this.setDisableScrollingWhileRefreshing(false);
+    }
+
+    public PullToRefreshListView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        this.setDisableScrollingWhileRefreshing(false);
+    }
+
+    @Override
+    public ContextMenuInfo getContextMenuInfo() {
+        return ((InternalListView) getRefreshableView()).getContextMenuInfo();
+    }
+
+//	public void setReleaseLabel(String releaseLabel) {
+//		super.setReleaseLabel(releaseLabel);
+//		if (null != headerLoadingView) {
+//			headerLoadingView.setReleaseLabel(releaseLabel);
+//		}
+//		if (null != footerLoadingView) {
+//			footerLoadingView.setReleaseLabel(releaseLabel);
+//		}
+//	}
+//
+//	public void setPullLabel(String pullLabel) {
+//		super.setPullLabel(pullLabel);
+//
+//		if (null != headerLoadingView) {
+//			headerLoadingView.setPullLabel(pullLabel);
+//		}
+//		if (null != footerLoadingView) {
+//			footerLoadingView.setPullLabel(pullLabel);
+//		}
+//	}
+//
+//	public void setRefreshingLabel(String refreshingLabel) {
+//		super.setRefreshingLabel(refreshingLabel);
+//
+//		if (null != headerLoadingView) {
+//			headerLoadingView.setRefreshingLabel(refreshingLabel);
+//		}
+//		if (null != footerLoadingView) {
+//			footerLoadingView.setRefreshingLabel(refreshingLabel);
+//		}
+//	}
+
+    @Override
+    protected final ListView createRefreshableView(Context context, AttributeSet attrs) {
+        ListView lv = new InternalListView(context, attrs);
+//		final int mode = this.getMode();
+//
+//		// Loading View Strings
+//		String pullLabel = context.getString(R.string.pull_to_refresh_pull_label);
+//		String refreshingLabel = context.getString(R.string.pull_to_refresh_refreshing_label);
+//		String releaseLabel = context.getString(R.string.pull_to_refresh_release_label);
+
+        // Add Loading Views
+//		if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) {
+//			FrameLayout frame = new FrameLayout(context);
+//			headerLoadingView = new LoadingLayout(context, MODE_PULL_DOWN_TO_REFRESH, releaseLabel, pullLabel,
+//					refreshingLabel);
+//			frame.addView(headerLoadingView, FrameLayout.LayoutParams.FILL_PARENT,
+//					FrameLayout.LayoutParams.WRAP_CONTENT);
+//			headerLoadingView.setVisibility(View.GONE);
+//			lv.addHeaderView(frame);
+//		}
+//		if (mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) {
+//			FrameLayout frame = new FrameLayout(context);
+//			footerLoadingView = new LoadingLayout(context, MODE_PULL_UP_TO_REFRESH, releaseLabel, pullLabel,
+//					refreshingLabel);
+//			frame.addView(footerLoadingView, FrameLayout.LayoutParams.FILL_PARENT,
+//					FrameLayout.LayoutParams.WRAP_CONTENT);
+//			footerLoadingView.setVisibility(View.GONE);
+//			lv.addFooterView(frame);
+//		}
+
+        // Set it to this so it can be used in ListActivity/ListFragment
+        lv.setId(android.R.id.list);
+        return lv;
+    }
+
+//	@Override
+//	protected void setRefreshingInternal(boolean doScroll) {
+//		super.setRefreshingInternal(false);
+//
+//		final LoadingLayout originalLoadingLayout, listViewLoadingLayout;
+//		final int selection, scrollToY;
+//
+//		switch (getCurrentMode()) {
+//			case MODE_PULL_UP_TO_REFRESH:
+//				originalLoadingLayout = this.getFooterLayout();
+//				listViewLoadingLayout = this.footerLoadingView;
+//				selection = refreshableView.getCount() - 1;
+//				scrollToY = getScrollY() - getHeaderHeight();
+//				break;
+//			case MODE_PULL_DOWN_TO_REFRESH:
+//			default:
+//				originalLoadingLayout = this.getHeaderLayout();
+//				listViewLoadingLayout = this.headerLoadingView;
+//				selection = 0;
+//				scrollToY = getScrollY() + getHeaderHeight();
+//				break;
+//		}
+//
+//		if (doScroll) {
+//			// We scroll slightly so that the ListView's header/footer is at the
+//			// same Y position as our normal header/footer
+//			this.setHeaderScroll(scrollToY);
+//		}
+//
+//		// Hide our original Loading View
+//		originalLoadingLayout.setVisibility(View.INVISIBLE);
+//
+//		// Show the ListView Loading View and set it to refresh
+//		listViewLoadingLayout.setVisibility(View.VISIBLE);
+//		listViewLoadingLayout.refreshing();
+//
+//		if (doScroll) {
+//			// Make sure the ListView is scrolled to show the loading
+//			// header/footer
+//			refreshableView.setSelection(selection);
+//
+//			// Smooth scroll as normal
+//			smoothScrollTo(0);
+//		}
+//	}
+
+//	@Override
+//	protected void resetHeader() {
+//
+//		LoadingLayout originalLoadingLayout;
+//		LoadingLayout listViewLoadingLayout;
+//
+//		int scrollToHeight = getHeaderHeight();
+//		final boolean doScroll;
+//
+//		switch (getCurrentMode()) {
+//			case MODE_PULL_UP_TO_REFRESH:
+//				originalLoadingLayout = this.getFooterLayout();
+//				listViewLoadingLayout = footerLoadingView;
+//				doScroll = this.isReadyForPullUp();
+//				break;
+//			case MODE_PULL_DOWN_TO_REFRESH:
+//			default:
+//				originalLoadingLayout = this.getHeaderLayout();
+//				listViewLoadingLayout = headerLoadingView;
+//				scrollToHeight *= -1;
+//				doScroll = this.isReadyForPullDown();
+//				break;
+//		}
+//
+//		// Set our Original View to Visible
+//		originalLoadingLayout.setVisibility(View.VISIBLE);
+//
+//		// Scroll so our View is at the same Y as the ListView header/footer,
+//		// but only scroll if the ListView is at the top/bottom
+//		if (doScroll) {
+//			this.setHeaderScroll(scrollToHeight);
+//		}
+//
+//		// Hide the ListView Header/Footer
+//		listViewLoadingLayout.setVisibility(View.GONE);
+//
+//		super.resetHeader();
+//	}
+
+}
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/service/VisitMng.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/service/VisitMng.java
index d8582bc..dc9b425 100644
--- a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/service/VisitMng.java
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/service/VisitMng.java
@@ -8,6 +8,7 @@
 import java.util.List;
 
 import cn.com.basic.face.discern.common.BaseCommonCallBack;
+import cn.com.basic.face.discern.common.CommonVariables;
 import cn.com.basic.face.discern.query.condition.VisitQueryCondition;
 import cn.com.basic.face.discern.query.item.VisitQueryItem;
 import cn.com.basic.face.util.AppApi;
@@ -19,9 +20,11 @@
         return instance;
     }
 
-    public void findLeftVisitorList(String searchText) {
+    public void findLeftVisitorList(String searchText, int pageNum, final boolean append) {
         RequestParams params = new RequestParams(AppApi.BASE_URL +AppApi.Query.VISIT_QUERY);
         params.addBodyParameter(VisitQueryCondition.FieldNames.username, searchText);
+        params.addBodyParameter(CommonVariables.Page.PAGE_SIZE, "7");
+        params.addBodyParameter(CommonVariables.Page.PAGE_NUM, pageNum+"");
         x.http().post(params, new BaseCommonCallBack() {
             public void success() {
                 List<VisitQueryItem> list = getList(VisitQueryItem.class);
@@ -41,7 +44,16 @@
                     itemList.add(item);
                     i++;
                 }
-                cn.com.basic.face.fragment.VisitFragment.getInstance().get_fragment_visit_left_list_view().show(itemList);
+                if (hasMorePages()) {
+                    itemList.add(CommonVariables.Page.hasMorePages);
+                } else {
+                    if (getPageNum() > 1) {
+                        itemList.add(CommonVariables.Page.reachBottom);
+                    } else {
+                        itemList.add(CommonVariables.Page.noMorePage);
+                    }
+                }
+                cn.com.basic.face.fragment.VisitFragment.getInstance().get_fragment_visit_left_list_view().show(itemList, append);
             }
         });
 
diff --git a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/widget/visit/VisitLeftListView.java b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/widget/visit/VisitLeftListView.java
index 8f83875..2fd52a9 100644
--- a/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/widget/visit/VisitLeftListView.java
+++ b/VisitFace/DemoForBsk/app/src/main/java/cn/com/basic/face/widget/visit/VisitLeftListView.java
@@ -5,9 +5,11 @@
 
 import com.camnter.easyrecyclerview.widget.EasyRecyclerView;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import cn.com.basic.face.adapter.VisitFragment;
+import cn.com.basic.face.discern.common.CommonVariables;
 
 public class VisitLeftListView extends EasyRecyclerView {
 
@@ -16,7 +18,6 @@
     private void initView() {
         adapter = new VisitFragment.VisitLeftAdapter();
         setAdapter(adapter);
-
     }
 
     public VisitLeftListView(Context context) {
@@ -34,9 +35,24 @@
         initView();
     }
 
-    public void show(List list) {
-        adapter.setList(list);
+    public void show(List list, boolean append) {
+        if (append) {
+            List newList = new ArrayList();
+            if (adapter.getList().size() > 0 &&  adapter.getList().get(adapter.getList().size()-1) instanceof Integer && ((int)adapter.getList().get(adapter.getList().size()-1))== CommonVariables.Page.hasMorePages) {
+                adapter.getList().remove(adapter.getList().size() - 1);
+            }
+            if (adapter.getList().size() > 0 &&  adapter.getList().get(adapter.getList().size()-1) instanceof
+                    Integer && ((int)adapter.getList().get(adapter.getList().size()-1))== CommonVariables.Page.noMorePage) {
+                adapter.getList().remove(adapter.getList().size() - 1);
+            }
+            newList.addAll(adapter.getList());
+            newList.addAll(list);
+            adapter.setList(newList);
+        } else {
+            adapter.setList(list);
+        }
         setAdapter(adapter);
+        adapter.notifyDataSetChanged();
     }
 
 }
diff --git a/VisitFace/DemoForBsk/app/src/main/res/drawable/pulltorefresh_down_arrow.png b/VisitFace/DemoForBsk/app/src/main/res/drawable/pulltorefresh_down_arrow.png
new file mode 100644
index 0000000..924df00
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/res/drawable/pulltorefresh_down_arrow.png
Binary files differ
diff --git a/VisitFace/DemoForBsk/app/src/main/res/drawable/pulltorefresh_up_arrow.png b/VisitFace/DemoForBsk/app/src/main/res/drawable/pulltorefresh_up_arrow.png
new file mode 100644
index 0000000..f994c38
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/res/drawable/pulltorefresh_up_arrow.png
Binary files differ
diff --git a/VisitFace/DemoForBsk/app/src/main/res/layout/load_more.xml b/VisitFace/DemoForBsk/app/src/main/res/layout/load_more.xml
new file mode 100644
index 0000000..109dfa2
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/res/layout/load_more.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:orientation="vertical">
+    <TextView
+        android:id="@+id/load_more_text_view"
+        android:layout_marginTop="20dp"
+        android:layout_marginBottom="20dp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="鍔犺浇鏇村"
+        android:gravity="center"
+        />
+</LinearLayout>
\ No newline at end of file
diff --git a/VisitFace/DemoForBsk/app/src/main/res/layout/no_more.xml b/VisitFace/DemoForBsk/app/src/main/res/layout/no_more.xml
new file mode 100644
index 0000000..1218709
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/res/layout/no_more.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:orientation="vertical">
+    <TextView
+        android:id="@+id/no_more_text_view"
+        android:layout_marginTop="20dp"
+        android:layout_marginBottom="20dp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="娌℃湁鏁版嵁"
+        android:gravity="center"
+        />
+</LinearLayout>
\ No newline at end of file
diff --git a/VisitFace/DemoForBsk/app/src/main/res/layout/pull_to_refresh_header.xml b/VisitFace/DemoForBsk/app/src/main/res/layout/pull_to_refresh_header.xml
new file mode 100644
index 0000000..6895075
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/res/layout/pull_to_refresh_header.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:paddingTop="10dp"
+    android:paddingBottom="10dip">
+    
+     <TextView
+        android:id="@+id/pull_to_refresh_text"
+        android:text="Pull to refresh..."
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textStyle="bold"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true" />
+
+    <ProgressBar
+        android:id="@+id/pull_to_refresh_progress"
+        android:indeterminate="true"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="30dip"
+        android:layout_marginRight="20dip"
+        android:visibility="gone"
+        android:layout_centerVertical="true"
+        style="?android:attr/progressBarStyleSmall" />
+
+    <ImageView
+        android:id="@+id/pull_to_refresh_image"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="30dip"
+        android:layout_marginRight="20dip"
+        android:layout_centerVertical="true" />
+
+   
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/VisitFace/DemoForBsk/app/src/main/res/layout/reach_bottom.xml b/VisitFace/DemoForBsk/app/src/main/res/layout/reach_bottom.xml
new file mode 100644
index 0000000..a3eff7d
--- /dev/null
+++ b/VisitFace/DemoForBsk/app/src/main/res/layout/reach_bottom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:orientation="vertical">
+    <TextView
+        android:id="@+id/load_more_text_view"
+        android:layout_marginTop="20dp"
+        android:layout_marginBottom="20dp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="宸插埌杈惧簳閮�"
+        android:gravity="center"
+        />
+</LinearLayout>
\ No newline at end of file
diff --git a/VisitFace/DemoForBsk/app/src/main/res/values/attrs.xml b/VisitFace/DemoForBsk/app/src/main/res/values/attrs.xml
index 7ab4b1d..dacc50f 100644
--- a/VisitFace/DemoForBsk/app/src/main/res/values/attrs.xml
+++ b/VisitFace/DemoForBsk/app/src/main/res/values/attrs.xml
@@ -15,4 +15,14 @@
         <attr name="label" format="string"/>
         <attr name="text" format="string"/>
     </declare-styleable>
+    <declare-styleable name="PullToRefresh">
+        <attr name="adapterViewBackground" format="reference|color" />
+        <attr name="headerBackground" format="reference|color" />
+        <attr name="headerTextColor" format="color" />
+        <attr name="mode">
+            <flag name="pullDownFromTop" value="0x1" />
+            <flag name="pullUpFromBottom" value="0x2" />
+            <flag name="both" value="0x3" />
+        </attr>
+    </declare-styleable>
 </resources>
\ No newline at end of file
diff --git a/VisitFace/DemoForBsk/app/src/main/res/values/strings.xml b/VisitFace/DemoForBsk/app/src/main/res/values/strings.xml
index 82d70a7..84a09a1 100644
--- a/VisitFace/DemoForBsk/app/src/main/res/values/strings.xml
+++ b/VisitFace/DemoForBsk/app/src/main/res/values/strings.xml
@@ -43,4 +43,8 @@
     <string name="device_camera1">鎽勫儚鏈�1</string>
     <string name="device_camera2">鎽勫儚鏈�2</string>
     <string name="country">鍥藉</string>
+    <string name="pull_to_refresh_pull_label">涓嬫媺鍒锋柊</string>
+    <string name="pull_to_refresh_release_label">鏉惧紑鍒锋柊鏁版嵁</string>
+    <string name="pull_to_refresh_refreshing_label">姝e湪鍔犺浇...</string>
+    <string name="pull_to_refresh_tap_label">Tap to refresh...</string>
 </resources>

--
Gitblit v1.8.0