android自定義控件-02listview下拉刷新加載黑馬新聞_第1頁(yè)
android自定義控件-02listview下拉刷新加載黑馬新聞_第2頁(yè)
android自定義控件-02listview下拉刷新加載黑馬新聞_第3頁(yè)
android自定義控件-02listview下拉刷新加載黑馬新聞_第4頁(yè)
android自定義控件-02listview下拉刷新加載黑馬新聞_第5頁(yè)
已閱讀5頁(yè),還剩19頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、寶貴建議請(qǐng)發(fā)送至:wangz-編程,始于Android 課程同步筆記Beta 0.01 版ByAndroid 自定義控件-2ListView 下拉刷新&加載&1. ListView 下拉刷新&分頁(yè)加載()1.1 簡(jiǎn)介如上圖所示為本文檔中要實(shí)現(xiàn)的效果,這也是在使用 Android時(shí)經(jīng)常見(jiàn)到的效果。當(dāng)往下拉 ListView 的時(shí)候在 ListView 頭部添加一個(gè)視圖,當(dāng)往上拉 ListView 的時(shí)候在 ListView 腳部添加一個(gè)視圖。1.2 布局實(shí)現(xiàn)的演示工程共用到三個(gè)布局文件,分別是主 Activity 布局、ListView 頭布局、ListView 腳布局。布局文件名如下圖所示:1

2、activity_main.xml 文件如下:該布局非常的簡(jiǎn)單,只有一個(gè)自定義的 ListView 對(duì)象。listview_header.xml 文件如下:2ProgressBarandroid:id=+id/pb_listview_header android:layout_width=wrap_content android:layout_height=wrap_content android:layout_gravity=centerlistview_footer.xml 文件如下:31.3 業(yè)務(wù)邏輯實(shí)現(xiàn)1.3.1 自定義 ListView 對(duì)象因?yàn)槭褂玫?ListView 需要添加上頭

3、部視圖和腳部視圖,因此 Android 原生的 ListView 并不能滿足的需求,這時(shí)可以自定義一個(gè) ListView 對(duì)象,并繼承原生 ListView 對(duì)象。RefreshListView.java 代碼如下:4/* 自定義 ListView 的下拉刷新頭和加載尾*/public class RefreshListView extends ListView implements OnScrollListener privatedownY; / 按下時(shí) y 軸的偏移量 privateheaderViewHeight; / 頭布局的高度 private View headerView; /

4、頭布局對(duì)象private finalDOWN_PULL = 0;/ 頭布局狀態(tài): 下拉刷新 private finalRELEASE_REFRESH = 1;/ 頭布局狀態(tài):刷新 private finalREFRESHING = 2; / 頭布局狀態(tài): 正在刷新中.privatecurrentSe = DOWN_PULL; / 頭布局當(dāng)前的狀態(tài), 默認(rèn)為: 下拉刷新private RoeAnimation upAnimation; / 頭布局向上旋轉(zhuǎn)的動(dòng)畫(huà)private RoeAnimation downAnimation; / 頭布局向下旋轉(zhuǎn)的動(dòng)畫(huà)android:layout_margin

5、=5dip android:indeterminateDrawable=drawable/custom_progressbar /ImageView ivArrow; / 頭布局的箭頭ProgressBar mProgressBar; / 頭布局的進(jìn)度圈privateprivate private privatee; / 頭布局的狀態(tài)TextView tvSTextView tvLastUpdateTime; / 頭布局最后刷新時(shí)間/ 使用者的回調(diào)事件privateprivate private privateOnRefreshListener mOnRefreshListener;View

6、footerView; / 腳布局對(duì)象footerViewHeight; / 腳布局的高度isLoadingMore = false; / 是否正在加載中, 默認(rèn)為:沒(méi)有正在加載public RefreshListView(Context context) super(context); initHeaderView(); initFooterView(); setOnScrollListener(this);public RefreshListView(Context context, AttributeSesuper(context, attrs); initHeaderView(); i

7、nitFooterView(); setOnScrollListener(this);trs) /* 初始化腳布局*/private void initFooterView() footerView = View.inflate(getContext(), R.layout.listview_footer,null);/ 設(shè)置腳布局的 paddingTop 為自己高度的負(fù)數(shù)footerView.measure(0, 0);footerViewHeight = footerView.getMeasuredHeight(); footerView.setPadding(0, -footerView

8、Height, 0, 0);this.addFooterView(footerView);/* 初始化 ListView 下拉刷新頭*/private void initHeaderView() headerView = View.inflate(getContext(), R.layout.listview_header,null);5ivArrow = (ImageView)headerView.findViewById(R.id.iv_listview_header_arrow); mProgressBar = (ProgressBar)headerView.findViewById(R

9、.id.pb_listview_header);tvSe = (TextView) headerView.findViewById(R.id.tv_listview_header_se);tvLastUpdateTime = (TextView)headerView.findViewById(R.id.tv_listview_header_last_update_time);tvLastUpdateTime.setText(最后刷新時(shí)間: + getCurrentTime();/ 測(cè)量頭布局的高度.headerView.measure(0, 0); / 讓系統(tǒng)框架去幫測(cè)量頭布局的寬和高./ 取

10、出頭布局的高度.headerView.getHeight(); / 此方法是控件沒(méi)有顯示到屏幕上之前是獲取不到值的, 一直/都是 0headerViewHeight = headerView.getMeasuredHeight(); / 獲得一個(gè)測(cè)量后的高度,有在 measure 方法被調(diào)用完畢后才可以得到具體高度.System.out.prln(頭布局的高度: + headerViewHeight);只/ 隱藏頭布局. paddingTopheaderView.setPadding(0, -headerViewHeight, 0, 0);/ 向 ListView 的頂部追加一個(gè)布局.this

11、.addHeaderView(headerView);initAnimation();/* 初始化動(dòng)畫(huà)*/private void initAnimation() upAnimation = new Ro0, -180,eAnimation(Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f); upAnimation.setDuration(500); upAnimation.setFillAfter(true); / 讓控件停止在動(dòng)畫(huà)結(jié)束的狀態(tài)下downAnimation = new Ro-180, -360,

12、eAnimation(Animation.RELATIVE_TO_SELF, 0.5f,6Animation.RELATIVE_TO_SELF, 0.5f);downAnimation.setDuration(500); downAnimation.setFillAfter(true); / 讓控件停止在動(dòng)畫(huà)結(jié)束的狀態(tài)下OverridepubliconTouchEvent(MotionEvent ev) switch (ev.getAction() case MotionEvent.ACTION_DOWN:downY =break;) ev.getY();case MotionEvent.AC

13、TION_MOVE:/ 當(dāng)前的狀態(tài)是否是正在刷新中, 如果是, 直接跳出.if(currentSebreak;= REFRESHING) moveY = () ev.getY();/ 間距 = 移動(dòng) y- 按下 y;diffY = moveY - downY;/ 計(jì)算頭布局paddingTop System.out.pr的 paddingTop = -頭布局高度 + 間距.= -headerViewHeight + diffY; ln(paddingTop: + paddingTop);/ 如果 paddingTop 的值 -headerViewHeightVisibleition = 0)

14、e = DOWN_PULL) / 頭布局完全顯示,并if(paddingTop 0 & currentS且當(dāng)前狀態(tài)是下拉刷新, 進(jìn)入到松開(kāi)刷新的狀態(tài)System.out.prln(松開(kāi)刷新);currentSe = RELEASE_REFRESH;refreshHeaderViewSe(); else if(paddingTop 0 & currentSe = RELEASE_REFRESH) / 頭布局沒(méi)有完全顯示, 并且當(dāng)前狀態(tài)是松開(kāi)刷新, 進(jìn)入到下拉刷新的狀態(tài)System.out.prln(下拉刷新);currentSe = DOWN_PULL;7refreshHeaderViewSe(

15、);headerView.setPadding(0, paddingTop, 0, 0);return true; / 自己處理用戶觸摸滑動(dòng)的事件.break;case MotionEvent.ACTION_UP:/ 判斷當(dāng)前的狀態(tài)是哪一種e = DOWN_PULL) / 當(dāng)前是在下拉刷新?tīng)顟B(tài)下松開(kāi)了,什么都不做,if(currentS把頭布局隱藏就可以.headerView.setPadding(0, -headerViewHeight, 0, 0); else if(currentSe = RELEASE_REFRESH) / 當(dāng)前的狀態(tài)屬于且松開(kāi)了. 應(yīng)該把頭布局正常顯示, 進(jìn)入正在刷新

16、中狀態(tài).headerView.setPadding(0, 0, 0, 0);刷新,并currentSe = REFRESHING;refreshHeaderViewSe();/ 調(diào)用用戶的事件.if(mOnRefreshListener != null) mOnRefreshListener.onPullDownRefresh();break; default:break;return super.onTouchEvent(ev); / ListView 默認(rèn)的滑動(dòng)效果./* 根據(jù)當(dāng)前的狀態(tài) currentS*/e 來(lái)刷新頭布局的狀態(tài).private void refreshHeaderVie

17、wSswitch (currentSe) e() / 下拉刷新case DOWN_PULL:ivArrow.startAnimation(downAnimation);tvSe.setText(下拉刷新);break;case RELEASE_REFRESH: / 松開(kāi)刷新 ivArrow.startAnimation(upAnimation); tvSe.setText(松開(kāi)刷新);break;case REFRESHING: / 正在刷新中8ivArrow.clearAnimation(); / 把自己身上的動(dòng)畫(huà)清除掉 ivArrow.setVisibility(View.INVISIBL

18、E); mProgressBar.setVisibility(View.VISIBLE);tvSe.setText(正在刷新.);break; default:break;/* 刷新完成, 用戶調(diào)用此方法, 把對(duì)應(yīng)的頭布局或腳布局給隱藏掉*/public void onRefreshFinish() if(isLoadingMore) / 當(dāng)前屬于加載/ 隱藏腳布局中footerView.setPadding(0, -footerViewHeight, 0, 0);isLoadingMore = false; else / 下拉刷新操作/ 隱藏頭布局headerView.setPadding(

19、0, -headerViewHeight, 0, 0);currentSe = DOWN_PULL;mProgressBar.setVisibility(View.INVISIBLE);ivArrow.setVisibility(View.VISIBLE); tvSe.setText(下拉刷新);tvLastUpdateTime.setText(最后刷新時(shí)間: + getCurrentTime();/* 獲取的時(shí)間* return 1990-09-09 09:09:09*/private String getCurrentTime() SimpleDateFormat sdf = new Si

20、mpleDateFormat(yyyy-MM-dd HH:mm:ss);return sdf.format(new Date();/*提供給使用者設(shè)置刷新的param listener*/事件9public void setOnRefreshListener(OnRefreshListenermOnRefreshListener = listener;listener)/* 當(dāng) ListView 刷新時(shí)的*/事件publicerface OnRefreshListener /* 當(dāng)下拉刷新時(shí)回調(diào)此方法*/public voidonPullDownRefresh();/* 當(dāng)加載*/public

21、 void時(shí)調(diào)用此方法onLoadingMore();Overridepublic void onScroll(AbsListView view,VisibleItem,visibleItemCount,totalItemCount) /*當(dāng)滾動(dòng)狀態(tài)改變時(shí), 觸發(fā)此方法.*e 當(dāng)前滾動(dòng)的狀態(tài).scrollSE_IDLE; 停滯狀態(tài)E_TOUCH_SCROLL; 手指觸摸在屏幕上滑動(dòng). E_FLING; 手指快速的滑動(dòng)一下.OnScrollListener.SCROLL_SOnScrollListener.SCROLL_S OnScrollListener.SCROLL_S*/Overridep

22、ublic void onScrollSeChanged(AbsListView view,scrollSe)/ 當(dāng)前的狀態(tài)是停止, 并且屏幕上顯示的最后一個(gè)條目的索引是 ListView 中總條目個(gè)數(shù)-1;/System.out.prln(scrollSe: + scrollSe + , last: +getLastVisibleition() + , count: + getCount();E_IDLE / 當(dāng)前是停滯或者是快速if(scrollSe = OnScrollListener.SCROLL_S滑動(dòng)時(shí)101.3.2 MainActivity 中使用自定義的ListView 對(duì)象1

23、1public class MainActivity extendivity privaist dataList; Overrideprotected void onCreate(Bundle savedInstane) super.onCreate(savedInstane); setContentView(R.layout.activity_main);final RefreshListView mListView = (RefreshListView) findViewById(R.id.refresh_listview);dataList = new ArrayList();for (

24、i = 0; i 30; i+) dataList.add(這是 ListView 的數(shù)據(jù): + i);/ 給 ListView 設(shè)置 Adapter 數(shù)據(jù)適配器final MyAdapter mAdapter = new MyAdapter(); mListView.setAdapter(mAdapter);/ 設(shè)置一個(gè)當(dāng) ListView 刷新的mListView.setOnRefreshListener(new OnRefreshListener() | scrollSe = OnScrollListener.SCROLL_SE_FLING) & getLastVisibleition(

25、) = (getCount() -1)& !isLoadingMore) System.out.prln(滑動(dòng)到底部, 可以加載數(shù)據(jù)了.);isLoadingMore = true; footerView.setPadding(0, 0, 0, 0); setSelection(getCount(); / 滑動(dòng)到最底部if(mOnRefreshListener != null) mOnRefreshListener.onLoadingMore();Overridepublic void onPullDownRefresh() Toast.makeText(MainActivity.this,

26、開(kāi)始下拉刷新了,0).show();new Handler().tDelayed(new Runnable() Overridepublic void run() / 會(huì)在 3 秒鐘后執(zhí)行.dataList.add(0, 我是下拉刷新出來(lái)的數(shù)據(jù).); mAdapter.notifyDataSetChanged();/ 把頭布局隱藏掉mListView.onRefreshFinish();, 3000);Overridepublic void onLoadingMore() Toast.makeText(MainActivity.this, 開(kāi)始加載了,0).show();new Handler

27、().tDelayed(newOverridepublic void run() dataList.add(我是加載 dataList.add(我是加載 dataList.add(我是加載Runnable() 的數(shù)據(jù) 1);的數(shù)據(jù) 2);的數(shù)據(jù) 3);mListView.onRefreshFinish();, 5000););/* 數(shù)據(jù)適配器*/class MyAdapter extends BaseAdapter OverridepublicgetCount() return dataList.size();12:類似做的 RefreshListView 功能的開(kāi)源框架有很多,在真實(shí)的開(kāi)發(fā)中

28、,講究效率的條件下很多時(shí)候都會(huì)直接使用開(kāi)源框架。,上面可以搜索各種各樣的開(kāi)源項(xiàng)目。2.()2.1 簡(jiǎn)介主要練習(xí)的是用代碼實(shí)現(xiàn)類似 Sliding(滑動(dòng)菜單)的功能。效果圖如下所示:13Overridepublic View getView(ition, View convertView, ViewGroup parent) TextView tv = new TextView(MainActivity.this); tv.setText(dataList.get(ition);tv.setTextSize(18); tv.setTextColor(Color.BLACK); tv.setPad

29、ding(0, 5, 0, 5); return tv;Overridepublic Object getItem(ition) return null;Overridepublic long getItemId(ition) return 0;左圖為首頁(yè),向右滑動(dòng)屏幕后打開(kāi)左側(cè)菜單,效果為右圖。2.2 布局實(shí)現(xiàn)該項(xiàng)目總共使用到了三個(gè)布局文件,如下圖所示。activity_main.xml 文件14com.itheima.slidingdemo.view.Slide android:id=+id/slide:這個(gè)布局文件用到了自定義的 ViewGroup 對(duì)象 com.itheima.slid

30、ing,demo.view.Slide繼承了 ViewGroup 類的控件時(shí)可以在其嵌套子控件。slide_content.xml 文件15android:background=drawable/top_bar_divider/:該文件為主界面布局。slide_left_.xml 文件16172.3 業(yè)務(wù)邏輯實(shí)現(xiàn)2.3.2 知識(shí)點(diǎn)自定義 ViewGroup 控件Android 事件處理機(jī)制2.3.3 代碼實(shí)現(xiàn)自定義類 Slide繼承 ViewGroup。該類作為自定義控件類。Slide.java 代碼18public class Slideextends ViewGroup privatedo

31、wnX; / 按下時(shí) x 軸的偏移量 private finalSCREEN_= 0; / 菜單界面 private finalSCREEN_MAIN = 1; / 主界面privatecurrentScreen = SCREEN_MAIN; / 當(dāng)前屏幕顯示的界面, 默認(rèn)為: 主界面private Scroller scroller;privatetouchSlop;public Slide(Context context, AttributeSetrs) super(context, attrs); init();public Slide(Context context) super(co

32、ntext); init();private void init() scroller = new Scroller(getContext();touchSlop = ViewConfiguration.get(getContext().getTouchSlop();/*widthMeasureSpec 填充屏幕heightMeasureSpec 填充屏幕*/ Overrideprotected void onMeasure(widthMeasureSpec,heightMeasureSpec) super.onMeasure(widthMeasureSpec, heightMeasureSp

33、ec);/ 測(cè)量菜單的寬和高. 寬: 240dip, 高: 填充屏幕View = getChildAt(0); / 獲取菜單對(duì)象ViewView.measure(View.getLayoutParams().width, heightMeasureSpec);/ 測(cè)量主界面的寬和高. 寬: 填充屏幕, 高: 填充屏幕View mainView = getChildAt(1); mainView.measure(widthMeasureSpec, heightMeasureSpec);/*/l 左邊=0 t 上邊=0r 右邊=屏幕的寬度b 下邊=屏幕的高度Overrideprotected vo

34、id onLayout(/ 主界面的位置放置在屏幕左上角changed,l,t,r,b)View mainView = getChildAt(1);mainView.layout(l, t, r, b);/ 把菜單的位置放置在屏幕的左側(cè)ViewView = getChildAt(0);View.layout(-View.getMeasuredWidth(),t, 0,b);OverridepubliconerceptTouchEvent(MotionEventev) / 只有在橫著滑動(dòng)時(shí)才可以. switch (ev.getAction() case MotionEvent.ACTION_DO

35、WN:downX =break;) ev.getX();case MotionEvent.ACTION_MOVE:moveX = () ev.getX();19diff = Mabs(downX - moveX);if(diff touchSlop) return true;break; default:break;return super.onerceptTouchEvent(ev);OverridepubliconTouchEvent(MotionEvent event)scrollX;switch (event.getAction() case MotionEvent.ACTION_DO

36、WN:downX =break;) event.getX();case MotionEvent.ACTION_MOVE:moveX = () event.getX();deltaX = downX - moveX;/ 判斷給定當(dāng)前的增量移動(dòng)后, 是否能夠超出邊界. scrollX = getScrollX() + deltaX;if(scrollX 0) / 當(dāng)前超出了右邊界, 應(yīng)該設(shè)置為 0 scrollTo(0, 0); else scrollBy(deltaX, 0);downX = moveX;break;case MotionEvent.ACTION_UP:/ 獲取菜單寬度的一半ce

37、nter = -getChildAt(0).getMeasuredWidth() / 2; scrollX = getScrollX(); / 當(dāng)前屏幕左上角的值20/Toast.makeText(getContext(), scrollX=+getScrollX(), 0).show();Toast.makeText(getContext(), center =+center*2+&layout.parameters=+getChildAt(0).getLayoutParams().width, 0).show();if(scrollX center) System.out.prln(當(dāng)前切

38、換到主界面); currentScreen = SCREEN_MAIN; else System.out.prln(當(dāng)前切換到菜單界面);currentScreen = SCREEN_;switchScreen();break; default:break;return true;/* 根據(jù) currentScreen 變量來(lái)切換屏幕顯示*/private void switchScreen() startX = getScrollX(); / 開(kāi)始的位置dx = 0; / 增量值 = 目的地位置 - 開(kāi)始的位置;if(currentScreen = SCREEN_MAIN) scrollTo(0, 0); dx = 0 - startX; else if(currentScreen = SCREEN_/) /scrollTo(-getChildAt(0).getMeasuredWidth(),0);dx = -getChildAt(0).getMeasuredWidth() - startX;duration = Maif(duration 1000) duration = 1000;bs(dx) * 10;scroller.startScroll

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論