Explorar o código

1.修改Android Apex Mobile,Result增加下拉刷新和触底加载。

Pen Li %!s(int64=8) %!d(string=hai) anos
pai
achega
090ea6210e

+ 323 - 0
Apex Mobile/app/src/main/java/com/usai/apex/Result/PullRefreshListView.java

@@ -0,0 +1,323 @@
+package com.usai.apex.Result;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.RotateAnimation;
+import android.widget.AbsListView;
+import android.widget.ListView;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class PullRefreshListView extends ListView implements AbsListView.OnScrollListener {
+
+    /**
+     * 头布局
+     */
+    private View headerView;
+
+    /**
+     * 头部布局的高度
+     */
+    private int headerViewHeight;
+
+    /**
+     * 底部布局
+     */
+    private View footerView;
+
+
+    /**
+     * 底部布局的高度
+     */
+    private int footerViewHeight;
+
+
+    /**
+     * 按下时的Y坐标
+     */
+    private int downY;
+
+    public static final int PULL_REFRESH = 0;//下拉刷新的状态
+    public static final int RELEASE_REFRESH = 1;//松开刷新的状态
+    public static final int REFRESHING = 2;//正在刷新的状态
+
+    /**
+     * 当前下拉刷新处于的状态
+     */
+    private int currentState = PULL_REFRESH;
+
+    /**
+     * 头部布局在下拉刷新改变时,图标的动画
+     */
+    private RotateAnimation upAnimation,downAnimation;
+
+    private boolean isLoadingMore = false;
+    private boolean isRefreshing = false;
+
+    public PullRefreshListView(Context context) {
+        this(context,null);
+    }
+
+    public PullRefreshListView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    private void init(){
+        //设置滑动监听
+        setOnScrollListener(this);
+        //初始化头布局
+        initHeaderView();
+        //初始化头布局中图标的旋转动画
+        initRotateAnimation();
+        //初始化为尾布局
+        initFooterView();
+    }
+
+    @Override
+    public void setLayoutParams(ViewGroup.LayoutParams params) {
+        super.setLayoutParams(params);
+    }
+
+    /**
+     * 初始化headerView
+     */
+    private void initHeaderView() {
+
+//        headerView =  View.inflate(getContext(), R.layout.refresh_header, null);
+        if (headerView != null) {
+            //测量headView的高度
+            headerView.measure(0, 0);
+            //获取高度,并保存
+            headerViewHeight = headerView.getMeasuredHeight();
+            //设置paddingTop = -headerViewHeight;这样,该控件被隐藏
+//            headerView.setPadding(0, -headerViewHeight, 0, 0);
+            headerStateChange(currentState,-headerViewHeight);
+            //添加头布局
+            addHeaderView(headerView);
+        }
+    }
+
+    /**
+     * 初始化旋转动画
+     */
+    private void initRotateAnimation() {
+
+        upAnimation = new RotateAnimation(0, -180,
+                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
+                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
+        upAnimation.setDuration(300);
+        upAnimation.setFillAfter(true);
+
+        downAnimation = new RotateAnimation(-180, -360,
+                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
+                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
+        downAnimation.setDuration(300);
+        downAnimation.setFillAfter(true);
+    }
+
+    //初始化底布局,与头布局同理
+    private void initFooterView() {
+
+//        footerView =  View.inflate(getContext(), R.layout.refresh_footer, null);
+        if (footerView != null) {
+            footerView.measure(0, 0);
+            footerViewHeight = footerView.getMeasuredHeight();
+//            footerView.setPadding(0, -footerViewHeight, 0, 0);
+            footerStateChange(PULL_REFRESH, -footerViewHeight);
+            addFooterView(footerView);
+        }
+    }
+
+    public void setRefreshHeader(View header) {
+        headerView = header;
+        initHeaderView();
+    }
+
+    public void setRefreshFooter(View footer) {
+        footerView = footer;
+        initFooterView();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+
+        if (headerView == null) {
+            return super.onTouchEvent(ev);
+        }
+
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                //获取按下时y坐标
+                downY = (int) ev.getY();
+                break;
+            case MotionEvent.ACTION_MOVE:
+
+                if(currentState==REFRESHING){
+                    //如果当前处在滑动状态,则不做处理
+                    break;
+                }
+                //手指滑动偏移量
+                int deltaY = (int) (ev.getY() - downY);
+
+                //获取新的padding值
+                int paddingTop = -headerViewHeight + deltaY;
+
+                if(paddingTop>-headerViewHeight && getFirstVisiblePosition()==0){
+                    //向下滑,且处于顶部,设置padding值,该方法实现了顶布局慢慢滑动显现
+//                    headerView.setPadding(0, paddingTop, 0, 0);
+
+
+                    if(paddingTop>=0 && currentState==PULL_REFRESH){
+
+                        //从下拉刷新进入松开刷新状态
+                        currentState = RELEASE_REFRESH;
+                    }else if (paddingTop<0 && currentState==RELEASE_REFRESH) {
+
+                        //进入下拉刷新状态
+                        currentState = PULL_REFRESH;
+                    }
+
+                    headerStateChange(currentState,paddingTop);
+
+                    return true;//拦截TouchMove,不让listview处理该次move事件,会造成listview无法滑动
+                }
+
+
+                break;
+            case MotionEvent.ACTION_UP:
+
+                if(currentState==PULL_REFRESH){
+                    //仍处于下拉刷新状态,未滑动一定距离,不加载数据,隐藏headView
+//                    headerView.setPadding(0, -headerViewHeight, 0, 0);
+                    headerStateChange(currentState,-headerViewHeight);
+
+                }else if (currentState==RELEASE_REFRESH) {
+
+                    //滑倒一定距离,显示无padding值得headcView
+//                    headerView.setPadding(0, 0, 0, 0);
+
+                    //设置状态为刷新
+                    currentState = REFRESHING;
+
+                    //刷新头部布局
+                    headerStateChange(currentState,0);
+
+                }
+                break;
+        }
+        return super.onTouchEvent(ev);
+    }
+
+
+    private void headerStateChange(int state,int offset) {
+
+        if (state == REFRESHING) {
+            isRefreshing = true;
+        }
+
+        if (headerView == null) {
+            return;
+        }
+
+        headerView.setPadding(0, offset, 0, 0);
+        if (listener != null) {
+            listener.onHeaderStateChange(state,offset);
+        }
+    }
+
+    private void footerStateChange(int state,int offset) {
+
+        if (state == REFRESHING) {
+            isRefreshing = true;
+        }
+
+        if (footerView == null) {
+            return;
+        }
+
+        footerView.setPadding(0, offset, 0, 0);
+
+        if (listener != null) {
+            listener.onFooterStateChange(state,offset + footerViewHeight);
+        }
+    }
+
+    /**
+     * 完成刷新操作,重置状态,在你获取完数据并更新完adater之后,去在UI线程中调用该方法
+     */
+    public void completeRefresh(){
+
+        isRefreshing = false;
+        if(isLoadingMore){
+
+            //重置footerView状态
+//            footerView.setPadding(0, -footerViewHeight, 0, 0);
+            isLoadingMore = false;
+            footerStateChange(PULL_REFRESH,-footerViewHeight);
+        } else {
+
+            //重置headerView状态
+//            headerView.setPadding(0, -headerViewHeight, 0, 0);
+            currentState = PULL_REFRESH;
+            headerStateChange(currentState,-headerViewHeight);
+        }
+    }
+
+    /**
+     * 获取当前系统时间,并格式化
+     * @return
+     */
+    private String getCurrentTime(){
+        SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
+        return format.format(new Date());
+    }
+
+    private OnRefreshListener listener;
+    public void setOnRefreshListener(OnRefreshListener listener){
+        this.listener = listener;
+    }
+    public interface OnRefreshListener{
+        void onHeaderStateChange(int state, int offset);
+        void onFooterStateChange(int state, int offset);
+    }
+
+    /**
+     * SCROLL_STATE_IDLE:闲置状态,就是手指松开
+     * SCROLL_STATE_TOUCH_SCROLL:手指触摸滑动,就是按着来滑动
+     * SCROLL_STATE_FLING:快速滑动后松开
+     */
+    @Override
+    public void onScrollStateChanged(AbsListView view, int scrollState) {
+
+        if (footerView == null) {
+            return;
+        }
+
+        if(scrollState==OnScrollListener.SCROLL_STATE_IDLE
+                && getLastVisiblePosition()==(getCount()-1) &&!isLoadingMore){
+            if (!isRefreshing) {
+
+                isRefreshing = true;
+                isLoadingMore = true;
+
+//                footerView.setPadding(0, 0, 0, 0);//显示出footerView
+                footerStateChange(REFRESHING,0);
+
+                setSelection(getCount());//让listview最后一条显示出来,在页面完全显示出底布局
+
+            }
+        }
+    }
+
+
+    @Override
+    public void onScroll(AbsListView view, int firstVisibleItem,
+                         int visibleItemCount, int totalItemCount) {
+    }
+
+}

+ 95 - 46
Apex Mobile/app/src/main/java/com/usai/apex/Result/SearchResultActivity.java

@@ -50,26 +50,33 @@ import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Iterator;
 
+import static java.lang.Thread.sleep;
+
 //import static com.usai.redant.CommonEditor.CommonEditorActivity.URL_REMOTE;
 
 
-public class SearchResultActivity extends AppCompatActivity implements AbsListView.OnScrollListener {
+public class SearchResultActivity extends AppCompatActivity {
 
     protected Bundle mParams;
     protected JSONObject resultData = new JSONObject();
 
     protected Context mContext;
-    protected ListView resultListView;
+    protected PullRefreshListView resultListView;
     protected ResultAdapter adapter;
+    protected SwipeRefreshLayout resultSwipe;
+    protected View list_footer;
+    protected View refresh_footer;
 
     private View clickedView;
     private View.OnTouchListener resultRowClickListener;
     private GestureDetector detector;
 
-    protected TextView footer;
-    protected int footer_height = 60;
+    protected int footer_height;
+    protected int header_height;
 
     ProgressDialog progressDialog;
+    public boolean isLoading = false;//表示是否正处于加载状态
+
 
     public void cellDoubleTapAction(int position) {
 
@@ -166,13 +173,23 @@ public class SearchResultActivity extends AppCompatActivity implements AbsListVi
 //        }
     }
 
+    void setMargin(View view,int l,int t,int r,int b) {
+        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(view.getLayoutParams());
+        lp.setMargins(l, t, r, b);
+        view.setLayoutParams(lp);
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_search_result);
 
         mContext = this;
-        resultListView = (ListView)findViewById(R.id.result_table_list);
+        footer_height = dp2px(this,30);
+        header_height = dp2px(this,60);
+
+        resultListView = (PullRefreshListView) findViewById(R.id.result_table_list);
+        resultSwipe = findViewById(R.id.result_swipe);
 
         progressDialog = new ProgressDialog(mContext);
         progressDialog.setCancelable(false);
@@ -180,24 +197,51 @@ public class SearchResultActivity extends AppCompatActivity implements AbsListVi
         initClickListener();
 
 
-        footer = new TextView(mContext);
-        footer.setBackgroundColor(Color.WHITE);
-        footer.setGravity(Gravity.CENTER);
-        footer.setText("Load More");
-        footer.setTextSize(sp2px(mContext,8));
-        footer.setVisibility(View.INVISIBLE);
+        adapter = new ResultAdapter(mContext);
+        resultListView.setAdapter(adapter);
+        resultListView.setDividerHeight(0);
 
-        AbsListView.LayoutParams footerLayoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,footer_height);
-        footer.setLayoutParams(footerLayoutParams);
+        // refresh header & footer
+        list_footer = View.inflate(this, R.layout.refresh_footer, null);
+        resultListView.setRefreshFooter(list_footer);
 
-        resultListView.addFooterView(footer);
+        refresh_footer = findViewById(R.id.result_refresh_footer);
+        refresh_footer.bringToFront();
 
+        resultListView.setOnRefreshListener(new PullRefreshListView.OnRefreshListener() {
+            @Override
+            public void onHeaderStateChange(int state, int offset) {
+                Log.d("Pull Down", "onHeaderStateChange: " + offset);
+//                setMargin(refresh_header,0,offset,0,0);
+//                if (state == PullRefreshListView.REFRESHING) {
+//                   loadData();
+//                }
+            }
+
+            @Override
+            public void onFooterStateChange(int state, int offset) {
+
+                setMargin(refresh_footer,0,resultListView.getHeight() - offset,0,0);
+                if (state == PullRefreshListView.REFRESHING) {
+                    if (!isLoading) {
+                        loadMore();
+                    }
+                }
+            }
+        });
+
+        resultSwipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+            @Override
+            public void onRefresh() {
+                if (isLoading) {
+                    resultSwipe.setRefreshing(false);
+                } else {
+                    loadData();
+                }
+            }
+        });
 
-        adapter = new ResultAdapter(mContext);
-        resultListView.setAdapter(adapter);
-        resultListView.setDividerHeight(0);
 
-        resultListView.setOnScrollListener(this);
 
         if (savedInstanceState != null) {
             mParams = savedInstanceState.getBundle("query_params");
@@ -279,30 +323,31 @@ public class SearchResultActivity extends AppCompatActivity implements AbsListVi
         return true;
     }
 
-    public int last_index;
-    public int total_index;
-    public boolean isLoading = false;//表示是否正处于加载状态
 
-    @Override
-    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
-        last_index = firstVisibleItem+visibleItemCount;
-        total_index = totalItemCount;
-    }
-
-    @Override
-    public void onScrollStateChanged(AbsListView view, int scrollState) {
-        if(last_index == total_index && (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE))
-        {
-            // 表示此时需要显示刷新视图界面进行新数据的加载(要等滑动停止)
-            if(!isLoading)
-            {
-                // 设置刷新界面可见
-                footer.setVisibility(View.VISIBLE);
-                loadMore();
-            }
-        }
-    }
+//    public int last_index;
+//    public int total_index;
+//
+//    @Override
+//    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+//        last_index = firstVisibleItem+visibleItemCount;
+//        total_index = totalItemCount;
+//    }
+//
+//    @Override
+//    public void onScrollStateChanged(AbsListView view, int scrollState) {
+//        if(last_index == total_index && (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE))
+//        {
+//            // 表示此时需要显示刷新视图界面进行新数据的加载(要等滑动停止)
+//            if(!isLoading)
+//            {
+//                // 设置刷新界面可见
+//                footer.setVisibility(View.VISIBLE);
+//                loadMore();
+//            }
+//        }
+//    }
 
+    // 设置header 和 footer宽度,否则listView会显示默认宽度
     protected void setupUI() {
         try {
             if (resultData == null) {
@@ -319,14 +364,13 @@ public class SearchResultActivity extends AppCompatActivity implements AbsListVi
             int width = header.getInt("width");
             width = convertDp2Px(width);
 
-            AbsListView.LayoutParams footerLayoutParams = (AbsListView.LayoutParams)footer.getLayoutParams();
+            AbsListView.LayoutParams footerLayoutParams = (AbsListView.LayoutParams)list_footer.getLayoutParams();
             if (footerLayoutParams == null) {
                 footerLayoutParams = new AbsListView.LayoutParams(width,footer_height);
             }
             footerLayoutParams.height = footer_height;
             footerLayoutParams.width = width;
-
-            footer.setLayoutParams(footerLayoutParams);
+            list_footer.setLayoutParams(footerLayoutParams);
 
 
         } catch (JSONException e) {
@@ -336,7 +380,12 @@ public class SearchResultActivity extends AppCompatActivity implements AbsListVi
     }
 
     public void loadComplete() {
-        footer.setVisibility(View.GONE);//设置刷新界面不可见
+
+        setupUI();
+        resultListView.completeRefresh();
+        if (resultSwipe.isRefreshing()) {
+            resultSwipe.setRefreshing(false);
+        }
         resultListView.forceLayout();
 
         isLoading = false;//设置正在刷新标志位false
@@ -428,7 +477,7 @@ public class SearchResultActivity extends AppCompatActivity implements AbsListVi
                     runOnUiThread(new Runnable() {
                         @Override
                         public void run() {
-                            setupUI();
+
                             loadComplete();
                             int result = resultData.optInt("result",0);
                             if (result == 2) {
@@ -514,7 +563,7 @@ public class SearchResultActivity extends AppCompatActivity implements AbsListVi
                             runOnUiThread(new Runnable() {
                                 @Override
                                 public void run() {
-                                    setupUI();
+
                                     loadComplete();
                                     adapter.notifyDataSetChanged();
                                 }

+ 38 - 13
Apex Mobile/app/src/main/res/layout/activity_search_result.xml

@@ -8,26 +8,51 @@
     tools:context="com.usai.apex.Result.SearchResultActivity">
 
 
-
-    <HorizontalScrollView
-        android:id="@+id/horizontal_scroll"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:background="#ffffff"
-        >
-
-
-        <ListView
-            android:id="@+id/result_table_list"
+    <!--<View-->
+        <!--android:id="@+id/result_refresh_header"-->
+        <!--android:layout_width="match_parent"-->
+        <!--android:layout_height="60dp"-->
+        <!--android:layout_marginTop="-60dp"-->
+        <!--android:background="#a3d309"-->
+        <!--/>-->
+
+    <android.support.v4.widget.SwipeRefreshLayout
+        android:id="@+id/result_swipe"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <HorizontalScrollView
+            android:id="@+id/horizontal_scroll"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:background="#ffffff"
             >
 
-        </ListView>
 
+            <com.usai.apex.Result.PullRefreshListView
+                android:id="@+id/result_table_list"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:background="#ffffff"
+                >
+
+            </com.usai.apex.Result.PullRefreshListView>
+
+
+        </HorizontalScrollView>
 
-    </HorizontalScrollView>
+    </android.support.v4.widget.SwipeRefreshLayout>
 
+    <TextView
+        android:id="@+id/result_refresh_footer"
+        android:layout_width="match_parent"
+        android:layout_height="30dp"
+        android:layout_below="@id/result_swipe"
+        android:background="#445588"
+        android:text="Loading More..."
+        android:textSize="22sp"
+        android:textColor="#ffffff"
+        android:gravity="center"
+        />
 
 </RelativeLayout>

+ 16 - 0
Apex Mobile/app/src/main/res/layout/refresh_footer.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="30dp"
+    android:background="#445588">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="30dp"
+        android:text="Loading More..."
+        android:textSize="22sp"
+        android:textColor="#ffffff"
+        android:gravity="center"
+        />
+
+</RelativeLayout>

+ 15 - 0
Apex Mobile/app/src/main/res/layout/refresh_header.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="60dp"
+    android:background="#a3d309">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        android:text="Pull Down"
+        android:textSize="30sp"
+        android:gravity="center"
+        />
+
+</RelativeLayout>