文章首發:Android程序員日記javascript
做者:賢榆的魚java
測試閱讀時間:8minandroid
有有很長一段時間沒有更新了,此次給你們帶來了一個框架Demo——仿掘金App,但願能夠經過這個Demo和你們分享一些控件的實際使用!此次呢先給你們帶來了自動隱藏佈局且帶下拉加載更多的listView!你們能夠先看看掘金app的效果圖,後面咱們把本身的放上來比較一下。
今天先放靜態的,明天放一張動的!git
經過仿掘金框架的這個listView你們能夠練習到一下幾個方面:程序員
[1] listView的基本用法github
[2] listView的viewHolder的複用優化及多條目微信
[3] listview添加headerView實現一些佈局和功能app
[4] listview經過footerview和滾動監聽實現上拉加載更多框架
[5] listview經過觸摸監聽事件實現上下bar的佈局隱藏功能異步
首先在xml文件中配置listview
<ListView android:scrollbars="none" android:id="@+id/listView" android:fadingEdge="vertical" android:overScrollMode="never" android:dividerHeight="0.5dp" android:divider="#05999999" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" />
上面用到的屬性:
android:overScrollMode="never" ——滾動越界的模式:ifcontentscroll和always纔會有越界效果!
android:dividerHeight="0.5dp" —— listview item之間間隔的高度
android:divider="#05999999" —— listview item之間間隔的背景或者顏色
android:fadingEdge="vertical" —— 上邊和下邊有黑色的陰影 值爲none的話就沒有陰影
android:scrollbars="none" —— 值爲horizontal|vertical的時候,會自動隱藏和顯示相應的滾動條,值爲none時隱藏滾動條。
部分經常使用屬性補充:
android:cacheColorHint="#00000000" —— 設置拖動背景色爲透明
android:fastScrollEnabled="true" —— 快速滾動效果屬性配置,在快速滾動的時候旁邊會出現一個小方塊的快速滾動效果,自動隱藏和顯示,
android:scrollbarTrackVertical="@color/colorAccent" —— 設置滾動條的背景色,只能設置引用不能直接填寫「#ffffff」
android:scrollbarThumbVertical="@color/colorPrimaryDark" —— 設置滾動條遊標的背景色,這裏只能引用不能直接填寫「#ffffff」
android:scrollbarStyle="outsideInset" —— 四個值的含義以下
outsideInset : 該ScrollBar顯示在視圖(view)的邊緣,增長了view的padding. 若是可能的話,該ScrollBar僅僅覆蓋這個view的背景.
outsideOverlay : 該ScrollBar顯示在視圖(view)的邊緣,不增長view的padding,該ScrollBar將被半透明覆蓋
insideInset :該ScrollBar顯示在padding區域裏面,增長了控件的padding區域,該ScrollBar不會和視圖的內容重疊.
insideOverlay : 該ScrollBar顯示在內容區域裏面,不會增長了控件的padding區域,該ScrollBar以半透明的樣式覆蓋在視圖(view)的內容上.
android:footerDividersEnabled —— 當設爲false時,ListView將不會在各個footer之間繪製divider.默認爲true。
android:headerDividersEnabled —— 當設爲false時,ListView將不會在各個header之間繪製divider.默認爲true。
在activity中初始化listview並給他設置adapter
mlistView = (ListView) findViewById(R.id.listView); mAdapter = new ViewHolderAdapter(this, mDates); mlistView.setAdapter(mAdapter);
在adapter當中利用viewholder模式對listView的複用機制進行優化,在滑動的時候會更加的順暢。以及listview多條目的使用它。經過viewholder內部類以item佈局中的控件最爲變量,能夠有效的避免每次都經過findViewById()來實例化控件,從而達到複用控件實例,優化listview的目的!
而這裏用到的多條目通常狀況下是爲增長listview條目的多樣樣行,讓listview表現的更加豐富!固然還有一個狀況就是爲了突出數據的結構分層!咱們這裏就是爲了凸顯結構,加了一個文章分類title!
public class ViewHolderAdapter extends BaseAdapter { private final Context mContext; private List<NewsItem> mDates=new ArrayList<>(); private static final int TITLE=0; private static final int CONTENT=1; public ViewHolderAdapter(Context mcontext, List<NewsItem> newsItems) { this.mContext=mcontext; //添加分類的標題 mDates.add(new NewsItem("熱門文章")); mDates.addAll(1,newsItems); } @Override public int getItemViewType(int position) { if(position==0){//position爲0是itemType爲分類Title return TITLE; }else{ return CONTENT; } } //返回listview條目類型的總數,咱們這隻有文章和分類title兩種! @Override public int getViewTypeCount() { return 2; } //返回listview中的條目數據總數 @Override public int getCount() { return mDates==null?0:mDates.size(); } //返回條目位置對應的內容 @Override public NewsItem getItem(int position) { return mDates.get(position); } @Override public long getItemId(int position) { return position; } //在getView當中對多條目的條目類型進行區分並分別作處理! @Override public View getView(int position, View convertView, ViewGroup parent) { NewsItem item = getItem(position); ContentViewHolder contentViewHolder; TieleViewHolder tieleViewHolder; int type = getItemViewType(position); if(convertView==null){ switch (type){ case TITLE: tieleViewHolder=new TieleViewHolder(); convertView=View.inflate(mContext,R.layout.lv_item_title,null); tieleViewHolder.tv_title= (TextView) convertView.findViewById(R.id.tv_top_title); tieleViewHolder.tv_title.setText(item.getTitle()); //綁定一個viewHolder方便在對convertView複用時也對viewHolder進行復用 convertView.setTag(tieleViewHolder); break; case CONTENT: contentViewHolder=new ContentViewHolder(); convertView=View.inflate(mContext,R.layout.lv_item,null); contentViewHolder.iamge= (ImageView) convertView.findViewById(R.id.iv_image); contentViewHolder.tv_articleInfo= (TextView) convertView.findViewById(R.id.tv_info); contentViewHolder.tv_title= (TextView) convertView.findViewById(R.id.tv_title); contentViewHolder.iamge.setImageResource(item.getImage()); contentViewHolder.tv_title.setText(item.getTitle()); contentViewHolder.tv_articleInfo.setText(item.getArtcileInfo()); convertView.setTag(contentViewHolder); break; } }else{ switch (type){ case TITLE: tieleViewHolder= (TieleViewHolder) convertView.getTag(); tieleViewHolder.tv_title.setText(item.getTitle()); break; case CONTENT: //複用綁定的ViewHolder contentViewHolder= (ContentViewHolder) convertView.getTag(); contentViewHolder.iamge.setImageResource(item.getImage()); contentViewHolder.tv_title.setText(item.getTitle()); contentViewHolder.tv_articleInfo.setText(item.getArtcileInfo()); } } return convertView; } public void addDate(List<NewsItem> newsItems, boolean isHead) { if(mDates==null){ this.mDates =newsItems; }else{ if (isHead){ mDates.addAll(1,newsItems); }else{ mDates.addAll(getCount(),newsItems); } } } //建立兩個不一樣itemType對應的ViewHolder內部類 public class ContentViewHolder { ImageView iamge; TextView tv_title; TextView tv_articleInfo; } public class TieleViewHolder { TextView tv_title; } }
ListView經過添加HeaderView其實能夠實現不少的效果,好比下拉刷新的動畫就能夠放在HeadView當中。固然此次仿掘金的app用了SwipeRefreshLayout實現了下拉刷新,後面會針對這個寫一篇的你們也別急!而這個app中依然也用到了headerView。這裏是添加了一個頭佈局。以下圖:
咱們在[ 2 ] 的初始化listview代碼以後設置adapter以前加上添加headerView的代碼
header = LayoutInflater.from(this).inflate(R.layout.lv_headerview, mlistView, false); //header = getLayoutInflater().inflate(R.layout.lv_headerview,null,true); //header=View.inflate(this,R.layout.lv_headerview,null); mlistView.addHeaderView(header);
注 :
關於lv_headerview.xml的代碼你們能夠在文末的github地址中獲取到,這裏就不貼出來了!不過上面代碼中也有要注意的地方,我寫了三種方式實例化headerView!第一種和第二種是同樣!而第三種方法省去了第三個參數!
你們在實例化的時候須要注意的是,若是你的headerview有預留的一段空隙,像個人不居中的同樣,那麼你的第二個參數須要填寫listview的實例對象,而第三個參數須要填寫false!不然heaaderview下面的空白就會消失(上面的第2、三個方法就會有該現象)!還有一個就第二個參數填寫了listview實例,而第三個對象填寫了true!這個時候,就會報錯崩潰報以下錯誤:
Caused by: java.lang.UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView
思路:
Step1:先加載一個帶加載標示的footerview
Step2:實現listview的滾動監聽事件
Step3:判斷是否爲最後一個條目?是,就顯示footerview而且異步加載數據!加載完畢隱藏footerveiw。
代碼實現:
在添加headerview後面添加footerview並實例化footerview裏面loading標示
footview = LayoutInflater.from(this).inflate(R.layout.lv_footview, mlistView, false); mLoadMore = (TextView) footview.findViewById(R.id.tv_loadmore); mlistView.addFooterView(footview);
實現listview的滾動監聽事件,並在onscroll()方法中完成異步加載數據的操做
mlistView.setOnScrollListener(new AbsListView.OnScrollListener(){ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { //使用isLoading布爾值做爲標識符避免每次觸底時進行屢次加載 if(view.getLastVisiblePosition()==view.getCount()-1&&!isLoading){ mLoadMore.setVisibility(View.VISIBLE); isLoading=true; //new 一個一部任務執行異步任務加載操做! new AsyncTask<Void, Void, List<NewsItem>>() { @Override protected List<NewsItem> doInBackground(Void... params) { SystemClock.sleep(1500); List<NewsItem> loadItems=refreshDate("Old"); return loadItems; } @Override protected void onPostExecute(List<NewsItem> loadItems) { isLoading=false; mLoadMore.setVisibility(View.GONE); mAdapter.addDate(loadItems,false); mAdapter.notifyDataSetChanged(); } }.execute(); } } });
最後咱們來看一下咱們的效果圖:
該項目的github地址:https://github.com/luorenyu/JuejinMoudel.git
因爲字數的限制,因此整篇不能放在一篇裏面!那就先分享前面四個點!第五點就明天繼續分享!若是着急的也可先直接去上面的git地址下載源碼本身!若是有任何問題,歡迎你們在個人微信公衆號【Android程序員日記】裏問我!
本篇未完待續,明天繼續分享!
喜歡的能夠關注個人微信公衆號!