下拉刷新------- 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; } } }