ListView下拉刷新

来源:http://www.cnblogs.com/wangfengdange/archive/2016/01/05/5101940.html
-Advertisement-
Play Games

下拉刷新------- 1.addHeaderView必須在setAdapter之前調用 2.將paddingTop設置一個headerView高度的負值去隱藏它 getHeight()和getMeasuredHeight()的區別: getMeasuredHeight():獲取測量完的高度,只要....


下拉刷新-------
    1.addHeaderView必須在setAdapter之前調用
    2.將paddingTop設置一個headerView高度的負值去隱藏它
    
    getHeight()和getMeasuredHeight()的區別:
    getMeasuredHeight():獲取測量完的高度,只要在onMeasure方法執行完,就可以用
                        它獲取到寬高,在自定義控制項內部多使用這個
                        使用view.measure(0,0)方法可以主動通知系統去測量,然後就
                        可以直接使用它獲取寬高
    getHeight():必須在onLayout方法執行完後,才能獲得寬高
                view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                    headerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    int headerViewHeight = headerView.getHeight();
                    //直接可以獲取寬高
            }
        });
    3.setSelection(position);將對應位置的item放置到屏幕頂端

 

其中headerView的佈局文件

<?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"
    android:gravity="center_horizontal"
    android:orientation="horizontal" >

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="10dp" >

        <ImageView
            android:id="@+id/iv_arrow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/indicator_arrow"
            android:contentDescription="@null" />

        <ProgressBar
            android:id="@+id/pb_rotate"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:visibility="invisible"
            android:layout_centerInParent="true"
            android:indeterminateDrawable="@drawable/indeterminate_drawable"
            android:indeterminateDuration="2000" />
    </RelativeLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/tv_state"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="下拉刷新"
            android:textColor="#aa000000"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/tv_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="最後刷新:"
            android:textColor="@android:color/darker_gray"
            android:textSize="14sp" />
    </LinearLayout>

</LinearLayout>
View Code

其中footerView的佈局文件

<?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"
    android:gravity="center"
    android:orientation="horizontal" >

    <ProgressBar
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:indeterminate="true"
        android:indeterminateDrawable="@drawable/indeterminate_drawable"
        android:indeterminateDuration="1000" />

    <TextView android:layout_width="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_height="wrap_content"
        android:textColor="#aa000000"
        android:layout_marginLeft="15dp"
        android:textSize="20sp"
        android:text="載入更多..."/>
</LinearLayout>
View Code

android:indeterminateDrawable="@drawable/indeterminate_drawable"

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android" 
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:drawable="@drawable/indicate_rotate"
    android:toDegrees="360">
    

</rotate>

RefreshListView的主代碼

package com.demo.pullrefresh.view;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.demo.pullrefresh.R;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;

public class RefreshListView extends ListView implements OnScrollListener {

    private View headerView;// headerView
    private ImageView iv_arrow;
    private ProgressBar pb_rotate;
    private TextView tv_state, tv_time;

    private int downY;// 按下時y的坐標
    private int headerViewHeight;// headerView高

    private View footerView;
    private int footerViewHeight;

    private final int PULL_REFRESH = 0;// 下拉刷新的狀態
    private final int RELEASE_REFRESH = 1;// 鬆開刷新的狀態
    private final int REFRESHING = 2;// 正在刷新的狀態
    private int currentState = PULL_REFRESH;// headerView的預設位置

    private RotateAnimation upAnimation, downAnimation;
    private boolean isLoadingMore = false;// 當前是否正在處於載入更多

    public RefreshListView(Context context) {
        super(context);
        init();
    }

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

    private void init() {
        setOnScrollListener(this);
        initHeaderView();
        initFooterView();
        initRotateAnimation();
    }

    /**
     * 初始化headerView
     */
    private void initHeaderView() {
        headerView = View.inflate(getContext(), R.layout.layout_header, null);
        // headerView
        // =LayoutInflater.from(getContext()).inflate(R.layout.layout_header,
        // null);
        iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
        pb_rotate = (ProgressBar) headerView.findViewById(R.id.pb_rotate);
        tv_state = (TextView) headerView.findViewById(R.id.tv_state);
        tv_time = (TextView) headerView.findViewById(R.id.tv_time);
        // 第一種方法
        // headerView.getViewTreeObserver().addOnGlobalLayoutListener(new
        // OnGlobalLayoutListener() {
        // @Override
        // public void onGlobalLayout() {
        // headerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        // int headerViewHeight = headerView.getHeight();
        //
        //
        // Log.e("MainActivity", "headerViewHeight: "+headerViewHeight);
        // headerView.setPadding(0, -headerViewHeight, 0, 0);
        // refreshListView.addHeaderView(headerView);//
        // }
        // });
        // 第二種方法
        headerView.measure(0, 0);// 主動通知系統去測量
        headerViewHeight = headerView.getMeasuredHeight();
        Log.e("MainActivity", "headerViewHeight: " + headerViewHeight);
        headerView.setPadding(0, -headerViewHeight, 0, 0);
        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);
    }

    /**
     * 初始化footerView
     */
    private void initFooterView() {
        footerView = View.inflate(getContext(), R.layout.layout_footer, null);
        footerView.measure(0, 0);// 主動通知系統去測量該View
        footerViewHeight = footerView.getMeasuredHeight();
        footerView.setPadding(0, -footerViewHeight, 0, 0);
        addFooterView(footerView);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downY = (int) ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:

            int deltaY = (int) (ev.getY() - downY);
            int paddingTop = -headerViewHeight + deltaY;
            if (paddingTop > -headerViewHeight
                    && getFirstVisiblePosition() == 0) {
                headerView.setPadding(0, paddingTop, 0, 0);
                Log.d("jiejie", "paddingtop" + paddingTop);

                if (paddingTop >= 0 && currentState == PULL_REFRESH) {
                    // 從下拉刷新進入鬆開刷新的狀態
                    currentState = RELEASE_REFRESH;
                    refreshHeaderView();
                } else if (paddingTop < 0 && currentState == RELEASE_REFRESH) {
                    // 進入下拉刷新的狀態
                    currentState = PULL_REFRESH;
                    refreshHeaderView();
                }
                return true;// 攔截TouchMove,不讓ListView處理該次move事件,不過會造成ListView無法滑動
            }
            break;
        case MotionEvent.ACTION_UP:
            if (currentState == PULL_REFRESH) {
                // 隱藏headerView
                headerView.setPadding(0, -headerViewHeight, 0, 0);
            } else if (currentState == RELEASE_REFRESH) {
                headerView.setPadding(0, 0, 0, 0);
                currentState = REFRESHING;
                refreshHeaderView();
                if (listener != null) {
                    listener.onPullRefersh();
                }
            }
            break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 根據currentState來更新headerView
     */
    private void refreshHeaderView() {
        switch (currentState) {

        case PULL_REFRESH:
            tv_state.setText("下拉刷新");
            iv_arrow.startAnimation(downAnimation);
            break;

        case RELEASE_REFRESH:
            tv_state.setText("鬆開刷新");
            iv_arrow.startAnimation(upAnimation);
            break;

        case REFRESHING:
            iv_arrow.clearAnimation();// 因為向上的旋轉動畫有可能沒有執行完
            iv_arrow.setVisibility(View.INVISIBLE);
            pb_rotate.setVisibility(View.VISIBLE);
            tv_state.setText("正在刷新...");
            break;
        }

    }

    /**
     * 完成刷新操作,重置狀態,在你獲取完數據並更新完adater之後,去在UI線程中調用該方法
     */
    public void completeRefresh() {
        if (isLoadingMore) {
            // 重置footerView狀態
            footerView.setPadding(0, -footerViewHeight, 0, 0);
            isLoadingMore = false;
        } else {
            // 重置headerView狀態
            headerView.setPadding(0, -headerViewHeight, 0, 0);
            currentState = PULL_REFRESH;
            pb_rotate.setVisibility(View.INVISIBLE);
            iv_arrow.setVisibility(View.VISIBLE);
            tv_state.setText("下拉刷新");
            tv_time.setText("最後刷新:" + getCurrentTime());
        }
    }

    /**
     * 取得當前系統的時間,並格式化
     */
    @SuppressLint("SimpleDateFormat")
    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 onPullRefersh();

        void onLoadingMore();
    }

    /**
     * SCROLL_STATE_IDLE:閑置狀態,就是手指鬆開 SCROLL_STATE_TOUCH_SCROLL:手指觸摸滑動,就是按著來滑動
     * SCROLL_STATE_FLING:快速滑動後鬆開
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
                && getLastVisiblePosition() == (getCount() - 1)
                && !isLoadingMore) {
            isLoadingMore = true;
            footerView.setPadding(0, 0, 0, 0);// 顯示footerView
            setSelection(getCount());// 讓ListView的最後一條顯示出來
            if (listener != null) {
                listener.onLoadingMore();
            }
        }
    }
}

MainActivity的主代碼

package com.demo.pullrefresh;

import java.util.ArrayList;
import java.util.List;

import com.demo.pullrefresh.view.RefreshListView;
import com.demo.pullrefresh.view.RefreshListView.OnRefreshListener;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnItemClickListener {
    private RefreshListView refreshListView;
    private MyAdapter adapter;

    private List<String> list ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        initView();
        initData();
    }

    private void initView() {
        // TODO Auto-generated method stub
        // requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.mainactivity);
        refreshListView = (RefreshListView) findViewById(R.id.rf_mainlistview);
    }

    private void initData() {
        list = new ArrayList<String>();
        for (int i = 0; i < 30; i++) {
            list.add("ListView原來的數據——   " + i);
        }

        adapter = new MyAdapter();
        refreshListView.setAdapter(adapter);
        refreshListView.setOnRefreshListener(new OnRefreshListener() {

            @Override
            public void onPullRefersh() {
                // TODO Auto-generated method stub
                // 需要聯網請求伺服器的數據,然後更新UI
                requestDataFromServer(false);
            }

            @Override
            public void onLoadingMore() {
                // TODO Auto-generated method stub
                requestDataFromServer(true);
            }
        });
        refreshListView.setOnItemClickListener(this);
    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // 跟新UI
            adapter.notifyDataSetChanged();
            refreshListView.completeRefresh();
        }

    };

    /**
     * 模擬向伺服器請求數據
     * 
     * @param isLoadingMore
     */
    private void requestDataFromServer(final boolean isLoadingMore) {
        new Thread() {
            public void run() {
                SystemClock.sleep(3000);// 模擬請求伺服器的一個時間長度
                Log.d("jiejie", isLoadingMore + "");
                if (isLoadingMore) {
                    list.add("載入了更多的數據  ————1");
                    list.add("載入了更多的數據  ————2");
                    list.add("載入了更多的數據  ————3");
                } else {

                }
                handler.sendEmptyMessage(0);
            };
        }.start();
    }

    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        // TODO Auto-generated method stub
        Toast.makeText(MainActivity.this, "第" + arg2 + "個條目== " + list.get(arg2-1),
                Toast.LENGTH_SHORT).show();

    }

    private class MyAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return list.size();
        }

        @Override
        public Object getItem(int arg0) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public long getItemId(int arg0) {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        public View getView(int arg0, View arg1, ViewGroup arg2) {
            // TODO Auto-generated method stub
            TextView textView = new TextView(MainActivity.this);
            textView.setPadding(20, 20, 20, 20);
            textView.setTextSize(18);
            textView.setText(list.get(arg0));
            return textView;
        }

    }

}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文轉載於:http://www.cnblogs.com/tianzhijiexian/p/4254110.htmlBitmap是引起OOM的罪魁禍首之一,當我們從網路上下載圖片的時候無法知道網路圖片的準確大小,所以為了節約記憶體,一般會在伺服器上緩存一個縮略圖,提升下載速度。除此之外,我們還可以在本...
  • 實現圖片按鈕的縮放、動畫效果(block的初步應用)
  • 準備工作:1.下載對應手機型號線刷Rom包,進入小米官網Rom下載頻道2.解壓下載下來的Rom包,並用Rom助手提取出system.img中的文件內容。這方面的文章很多,請參考Rom助手如何提取IMG文件3.找到跟小米桌面相關的apk——/system/priv-app/MiuiHome.apk(5...
  • 支付坑的故事 -最主要的是微信 ,以下都是自己的思考得來的,難免有不足之處。如有錯誤,歡迎給位批評指正!也可在下麵留下你的QQ 咱們一起討論問題!總結:樓主感覺微信支付是最坑人的-沒有之一!1:微信支付步驟如下:微信支付原理:https://pay.weixin.qq.com/wiki/doc/a....
  • 1. 什麼是cachecache就是緩存的意思.電腦上的cache就是高速緩存,電腦組成課程里的定義是,存在於主存和CPU之間,主要用於解決CPU處理數據的速度遠遠大於讀取主存數據的速度.手機上也有cache,主要作用是保存一些軟體生成的臨時文件,避免每次都要重覆地向伺服器請求相同的數據,既浪費...
  • 1 styles.xml源碼 2 主佈局 DrawerLayout 主佈局activity_my.xml源碼 2 右邊佈局app_bar_main.xml源碼 content_main.xml ...
  • 1 2 6 7 12 13 22 23 33 34 45 46 57 -58 59 60 61 66 67 72 73 79 80 86 87 88 運行效果圖:需要用到四個lib包 :解...
  • 轉載請註明出處:http://www.cnblogs.com/titibili/p/5102035.html 謝謝~ 1、下載JDK並配置Java運行環境 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...