您好,登錄后才能下訂單哦!
這個博客好想不能提供下載代碼啊, 我只能把代碼貼出來了...
其實你只需看用法, 不用關心具體實現,demo非常容易看懂
public class CustomListViewActivity extends Activity { private CustomListView listview; private ArrayList<String> data; private BaseAdapter adapter; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); init(); setListener(); } private void init(){ data = new ArrayList<String>(); //虛擬一些數據 data.add("a"); data.add("b"); data.add("c"); data.add("e"); data.add("f"); data.add("g"); data.add("h"); data.add("i"); data.add("j"); data.add("k"); data.add("L"); data.add("M"); data.add("L"); data.add("N"); data.add("O"); data.add("P"); data.add("Q"); listview = (CustomListView) findViewById(R.id.listview); adapter = new BaseAdapter(){ @Override public int getCount() { return data.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView textView = new TextView(getApplicationContext()); textView.setHeight(100); textView.setTextSize(20); textView.setGravity(Gravity.CENTER); textView.setBackgroundColor(0x66666666); textView.setTextColor(0xaaffffff); textView.setText(data.get(position)); return textView; } }; listview.setAdapter(adapter); } private void setListener(){ listview.setOnRefreshListner(new OnRefreshListner() { @Override public void onRefresh() { new AsyncTask<Void, Void, ArrayList<String>>(){ @Override protected ArrayList<String> doInBackground(Void... params) { try { //模擬從服務器獲取數據的過程 Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } ArrayList<String> virtualData = new ArrayList<String>(); virtualData.add("Head刷新后的新數據1"); virtualData.add("Head刷新后的新數據2"); virtualData.add("Head刷新后的新數據3"); virtualData.add("Head刷新后的新數據4"); virtualData.add("Head刷新后的新數據5"); virtualData.add("Head刷新后的新數據6"); return virtualData; } //更新UI的方法,系統自動實現 @Override protected void onPostExecute(ArrayList<String> result) { data.addAll(0,result);//注意是往前添加數據 adapter.notifyDataSetChanged(); listview.onRefreshComplete();//完成下拉刷新,這個方法要調用 super.onPostExecute(result); } }.execute(); } }); //創建FootView final View footer = View.inflate(CustomListViewActivity.this, R.layout.footer, null); listview.setOnAddFootListener(new OnAddFootListener() { @Override public void addFoot() { listview.addFooterView(footer); } }); listview.setOnFootLoadingListener(new OnFootLoadingListener() { @Override public void onFootLoading() { new AsyncTask<Void, Void, ArrayList<String>>(){ @Override protected ArrayList<String> doInBackground(Void... params) { try { //模擬從服務器獲取數據的過程 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } ArrayList<String> virtualData = new ArrayList<String>(); virtualData.add("Foot刷新后的新數據1"); virtualData.add("Foot刷新后的新數據2"); virtualData.add("Foot刷新后的新數據3"); virtualData.add("Foot刷新后的新數據4"); virtualData.add("Foot刷新后的新數據5"); virtualData.add("Foot刷新后的新數據6"); return virtualData; } //在doInBackground后面執行 @Override protected void onPostExecute(ArrayList<String> result) { data.addAll(result);//這個是往后添加數據 adapter.notifyDataSetChanged(); listview.onFootLoadingComplete();//完成上拉刷新,就是底部加載完畢,這個方法要調用 //移除footer,這個動作不能少 listview.removeFooterView(footer); super.onPostExecute(result); } }.execute(); } }); } }
下面上listview的代碼,有點長...
/** * 支持下拉刷新和上拉刷新 * 可自定義上啦和下拉過程的操作,推薦使用AsyncTask * 需自定義Foot的View,然后只需在addFoot方法中添加即可 * @author lxj * */ public class CustomListView extends ListView implements OnScrollListener { private static final int DONE = 0; private static final int PULL_TO_REFRESH = 1; private static final int RELEASE_TO_REFRESH = 2; private static final int REFRESHING = 3; private static final float RATIO = 3;// 用來設置實際間距和上邊距之間的比例 private int state;// 當前下拉刷新的狀態 private int firstVisibleIndex;// 在listview中第一個可以看見的item private View headView; private ImageView headArrow; private ProgressBar progressBar; private TextView headTitle; private TextView headLastUpdate; private int headContentWidth; private int headContentHeight; private Animation animation; private Animation reverseAnimation; private OnRefreshListner refreshListner;// 刷新監聽器 private boolean isRefreshable; private boolean isRecored = false;// 用來記錄第一次按下坐標點,在整個滑動的過程中 只記錄一次 private float startY; private boolean isBack = false;// 是從 松開刷新狀態 來到的 下拉刷新狀態 public CustomListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { // listview 設置滑動時緩沖背景色 setCacheColorHint(0x00000000); headView = View.inflate(context, R.layout.head, null); headArrow = (ImageView) headView.findViewById(R.id.head_arrow); progressBar = (ProgressBar) headView.findViewById(R.id.progressbar); headTitle = (TextView) headView.findViewById(R.id.head_title); headLastUpdate = (TextView) headView .findViewById(R.id.head_last_update); headArrow.setMinimumWidth(50); headArrow.setMinimumHeight(70); MeasureView(headView); headContentWidth = headView.getMeasuredWidth(); headContentHeight = headView.getMeasuredHeight(); headView.setPadding(0, -1*headContentHeight, 0, 0); // 為listView加入頂部View addHeaderView(headView); setOnScrollListener(this); animation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); animation.setDuration(250); animation.setFillAfter(true);// 設定動畫結束時,停留在動畫結束位置 (保留動畫效果) animation.setInterpolator(new LinearInterpolator());// 勻速變化 reverseAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); reverseAnimation.setDuration(200); reverseAnimation.setFillAfter(true);// 設定動畫結束時,停留在動畫結束位置 (保留動畫效果) reverseAnimation.setInterpolator(new LinearInterpolator());// 勻速變化 // 設置當前headView的狀態 state = DONE; // 設置當前下拉刷新是否可用 isRefreshable = false; } /** * 測量headView的 寬高 * * @param child */ private void MeasureView(View child) { ViewGroup.LayoutParams lp = child.getLayoutParams(); if (null == lp) { lp = new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); } int measureChildWidth = ViewGroup.getChildMeasureSpec(0, 0, lp.width); int measureChildHeight; if (lp.height > 0) { measureChildHeight = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); } else { measureChildHeight = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } child.measure(measureChildWidth, measureChildHeight); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (firstVisibleIndex == 0 && !isRecored) { startY = event.getY(); isRecored = true; } break; case MotionEvent.ACTION_MOVE: float tempY = event.getY(); if (firstVisibleIndex == 0 && !isRecored) { startY = tempY; isRecored = true; } if (state != REFRESHING) { if (state == PULL_TO_REFRESH) { // 向下拉了 從下拉刷新的狀態 來到 松開刷新的狀態 if ((tempY - startY) / RATIO >= headContentHeight && (tempY - startY) > 0) { state = RELEASE_TO_REFRESH; changeHeadViewOfState(); } // 向上推了 從下拉刷新的狀態 來到 刷新完成的狀態 else if ((tempY - startY) <= 0) { state = DONE; changeHeadViewOfState(); } } else if (state == RELEASE_TO_REFRESH) { // 向上推了 還沒有完全將HEADVIEW 隱藏掉(可以看到一部分) // 從松開刷新的狀態 來到 下拉刷新的狀態 if ((tempY - startY) / RATIO < headContentHeight && (tempY - startY) > 0) { state = PULL_TO_REFRESH; changeHeadViewOfState(); isBack = true; } // 向上推了 一下子推到了最上面 從松開刷新的狀態 來到 刷新完成的狀態 (數據不刷新的) else if ((tempY - startY) <= 0) { state = DONE; changeHeadViewOfState(); } } else if (state == DONE) { // 刷新完成的狀態 來到 下拉刷新的狀態 if ((tempY - startY) > 0) { state = PULL_TO_REFRESH; changeHeadViewOfState(); } } if (state == PULL_TO_REFRESH) { headView.setPadding( 0, (int) ((tempY - startY) / RATIO - headContentHeight), 0, 0); } if (state == RELEASE_TO_REFRESH) { headView.setPadding( 0, (int) ((tempY - startY) / RATIO - headContentHeight), 0, 0); } } break; case MotionEvent.ACTION_UP: if (state != REFRESHING) { if (state == PULL_TO_REFRESH) { // 松手 state = DONE; changeHeadViewOfState(); } else if (state == RELEASE_TO_REFRESH) { // 松手 state = REFRESHING; changeHeadViewOfState(); // 執行數據刷新方法 onRefresh(); } } isRecored = false; isBack = false; break; } return super.onTouchEvent(event); } /** * 執行下拉刷新 */ private void onRefresh() { if (refreshListner != null) { refreshListner.onRefresh(); } } /** * HeadView的狀態變化效果 */ private void changeHeadViewOfState() { // switch (state) { case PULL_TO_REFRESH: headArrow.setVisibility(View.VISIBLE); progressBar.setVisibility(View.GONE); headTitle.setVisibility(View.VISIBLE); headLastUpdate.setVisibility(View.VISIBLE); headArrow.clearAnimation(); headTitle.setText("下拉可以刷新"); //由 松開刷新 到 下拉刷新 if(isBack){ headArrow.startAnimation(animation); isBack = false; } break; case RELEASE_TO_REFRESH: headArrow.setVisibility(View.VISIBLE); progressBar.setVisibility(View.GONE); headTitle.setVisibility(View.VISIBLE); headLastUpdate.setVisibility(View.VISIBLE); headArrow.clearAnimation(); headArrow.startAnimation(reverseAnimation); headTitle.setText("松開可以刷新"); break; case REFRESHING: headArrow.setVisibility(View.GONE); progressBar.setVisibility(View.VISIBLE); headTitle.setVisibility(View.VISIBLE); headLastUpdate.setVisibility(View.VISIBLE); headArrow.clearAnimation(); headTitle.setText("正在刷新..."); headView.setPadding(0, 0, 0, 0); break; case DONE: headArrow.setVisibility(View.VISIBLE); progressBar.setVisibility(View.GONE); headTitle.setVisibility(View.VISIBLE); headLastUpdate.setVisibility(View.VISIBLE); headArrow.clearAnimation(); headTitle.setText("下拉可以刷新"); headView.setPadding(0, -1 * headContentHeight, 0, 0); break; } } private int lastPos;//最后一個可見的item的位置 private int count;//item總數,注意不是當前可見的item總數 private boolean hasFoot = false;//是否有了Foot @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { firstVisibleIndex = firstVisibleItem; lastPos = getLastVisiblePosition(); count = totalItemCount; //因為剛進入的時候,lastPos=-1,count=0,這個時候不能讓它執行onAddFoot方法 if(lastPos==count-1 && !hasFoot && lastPos != -1){ hasFoot = true; onAddFoot(); Log.d("addFoot================","執行添加Foot...."); } Log.d("count================", count+""); Log.d("lastPos================", lastPos+""); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if(isFootLoading) return; if(hasFoot && scrollState==SCROLL_STATE_IDLE){ isFootLoading = true; onFootLoading(); } } /** * 設置下拉刷新監聽 * * @param listener */ public void setOnRefreshListner(OnRefreshListner listener) { // 設置下拉刷新可用 isRefreshable = true; refreshListner = listener; } //執行底部加載 public void onFootLoading(){ if(footLoadingListener!=null && isFootLoading) footLoadingListener.onFootLoading(); } public void setOnAddFootListener(OnAddFootListener addFootListener){ onAddFootListener = addFootListener; } //執行添加foot public void onAddFoot(){ if(onAddFootListener!=null && hasFoot) onAddFootListener.addFoot(); } //是否添加Foot的監聽器,如果寫在OnFootLoadingListener中會有延遲,效果不好 //應該是先進入添加Foot的狀態,再進入FootLoading的狀態 public OnAddFootListener onAddFootListener; //是否進入從底部加載數據的狀態的監聽器 public OnFootLoadingListener footLoadingListener; //正在加載底部數據 private boolean isFootLoading = false; public void setOnFootLoadingListener(OnFootLoadingListener footLoading){ footLoadingListener = footLoading; } /** * 下拉刷新監聽器 * @author lxj * */ public interface OnRefreshListner { /** * 下拉刷新的時候,在這里執行獲取數據的過程 */ void onRefresh(); } /** * 上拉刷新監聽器 * @author lxj * */ public interface OnFootLoadingListener{ /** * 這里是執行后臺獲取數據的過程 */ void onFootLoading(); } /** * 添加Foot的監聽器 * @author lxj * */ public interface OnAddFootListener{ /** * 這里是用戶addFootView的操作 */ void addFoot(); } /** * 底部數據加載完成,用戶需要加入一個removeFootView的操作 */ public void onFootLoadingComplete(){ hasFoot = false; isFootLoading = false; } /** * 上拉刷新完成時 所執行的操作,更改狀態,隱藏head */ public void onRefreshComplete() { state = DONE; changeHeadViewOfState(); headLastUpdate.setText("最后刷新時間: " + new Date().toLocaleString()); } @Override public void setAdapter(ListAdapter adapter) { headLastUpdate.setText("最后刷新時間: " + new Date().toLocaleString()); super.setAdapter(adapter); } }
下面是布局文件:
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <com.test.custom.CustomListView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/listview" /> </LinearLayout>
head.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true" >
<ImageView
android:id="@+id/head_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/arrow" />
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:orientation="vertical" >
<TextView
android:id="@+id/head_title"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下拉可以刷新" android:textColor="#666666" android:textSize="20sp" /> <TextView android:id="@+id/head_last_update" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:text="最后更新時間:" android:textColor="#666666" android:textSize="10sp" /> </LinearLayout> </RelativeLayout> </LinearLayout>
footer.xml
<?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="match_parent" android:orientation="horizontal" android:gravity="center" > <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="10dip" android:text="正在加載中..." android:textSize="20sp"/> </LinearLayout>
本著一條龍服務的原則, 下面連箭頭圖片都給你搞上...箭頭就在前面那個空格區域(3個點的后面),暈啊,箭頭是白色的看不到,,,你在那里用鼠標拖一下就出來了,或者到我空間相冊下載....
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。