Android ListView收縮與展開的封裝實現
常有這種需求,即ListView中資料較多(不涉及分頁),如果都展開,資料量較多,體驗不好,所以需要提供使用者檢視更多、收縮資料的互動
截圖如下:
如圖所示,點選更多,則展開所有資料。點選收起,則自動收縮。
程式碼如下(主要通過繼承Adapetr,控制展示的資料量getCount()方法實現,當資料量大於預設值(2)時,自動只展示2條資料,當點選更多時,則展示全部資料):
(在使用這種方法前曾想自定義ListView實現,但遇到較多問題,如:
1.由於我們通過adapter設定資料,不直接呼叫listview的方法,所以需要了解Adapter中notifyDataSetChanged方法的回撥函式,通過分析原始碼瞭解到notifyDataSetChanged方法會回撥ListView的requestLayout方法。所以通過在requestLayout中新增動態設定listview高度的方法,但設定高度會回撥requestLayout,從而造成死迴圈,可通過設計標誌位解決
2.動態設定listview高度並沒有實現把多餘的listitem隱藏,導致本該顯示footview的高度顯示了部分listitem。隱藏多餘的listitem後,目前還是未顯示出footview,通過網上了解到的一些解決辦法,還是沒有解決
3.此外還有其他問題,所以後來索性轉為繼承BaseAdapter實現)
package com.example.android_train.adapter; import java.util.ArrayList; import android.annotation.SuppressLint; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.ListView; import com.example.android_train.R; public abstract class BaseFootviewAdapter<E> extends BaseAdapter { public static final int DEFAULT_SHOW_COUNT = 2; protected Context mContext; protected ListView mListView; protected LayoutInflater inflater; protected LinearLayout headView; protected Button btn_loadmore; protected ArrayList<E> mShowObjects = new ArrayList<E>(); protected ArrayList<E> mAllObjects = null; protected boolean shrink = true; @SuppressWarnings("unused") private BaseFootviewAdapter() { } @SuppressLint("InflateParams") public BaseFootviewAdapter( Context mContext, ListView mListView) { this.mContext = mContext; this.mListView = mListView; inflater = LayoutInflater.from(mContext); headView = (LinearLayout) inflater.inflate(R.layout.lv_footer_button, null); btn_loadmore = (Button) headView.findViewById(R.id.btn_loadmore); btn_loadmore.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { changeShow(); } }); mListView.addFooterView(headView, null, false); } public void setAdapterData( ArrayList<E> mAllObjects ) { this.mAllObjects = mAllObjects; mShowObjects.clear(); if( mAllObjects != null ) { if( mAllObjects.size() <= DEFAULT_SHOW_COUNT ) { headView.setVisibility(View.GONE); mShowObjects.addAll(mAllObjects); } else { headView.setVisibility(View.VISIBLE); for (int i = 0; i < DEFAULT_SHOW_COUNT; i++) { mShowObjects.add(mAllObjects.get(i)); } } } notifyDataSetChanged(); setListViewHeightBasedOnChildren(mListView); } @Override public int getCount() { int showCount = 0; if( mShowObjects != null ) { showCount = mShowObjects.size(); } return showCount; } @Override public E getItem(int position) { E object = null; if( mShowObjects != null ) { object = mShowObjects.get(position); } return object; } @Override public long getItemId(int position) { return position; } private void changeShow() { if( headView.getVisibility() == View.GONE ) { headView.setVisibility(View.VISIBLE); } mShowObjects.clear(); if( shrink ) { shrink = false; mShowObjects.addAll(mAllObjects); btn_loadmore.setText("收起"); } else { shrink = true; for (int i = 0; i < DEFAULT_SHOW_COUNT; i++) { mShowObjects.add(mAllObjects.get(i)); } btn_loadmore.setText("更多"); } notifyDataSetChanged(); setListViewHeightBasedOnChildren(mListView); } /** * 當ListView外層有ScrollView時,需要動態設定ListView高度 * @param listView */ protected void setListViewHeightBasedOnChildren(ListView listView) { if(listView == null) return; ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); } }
資原始檔lv_footer_button.xml(此處需注意,不要在fl_loadmore這個外部LinearLayout設定高度,而應在Button中設定,否則listview展示的高度與設定的不符(暫不瞭解原因))
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fl_loadmore" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="1px" android:orientation="vertical" android:background="#000000"/> <Button android:id="@+id/btn_loadmore" android:layout_width="match_parent" android:layout_height="32dp" android:gravity="center" android:background="#00000000" android:text="更多" android:textSize="14sp" /> </LinearLayout>
外部呼叫例子:
物件Bean(StationImage):
package com.example.android_train.bean; public class StationImage { public String img_name = ""; public String img_url_s = ""; public String img_url_l = ""; public String getImg_name() { return img_name; } public void setImg_name(String img_name) { this.img_name = img_name; } public String getImg_url_s() { return img_url_s; } public void setImg_url_s(String img_url_s) { this.img_url_s = img_url_s; } public String getImg_url_l() { return img_url_l; } public void setImg_url_l(String img_url_l) { this.img_url_l = img_url_l; } }
FootviewAdapter繼承BaseFootviewAdapter,並實現getView()方法
package com.example.android_train.adapter; import android.content.Context; import android.graphics.Paint; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import com.example.android_train.R; import com.example.android_train.bean.StationImage; public class FootviewAdapter extends BaseFootviewAdapter<StationImage>{ private ListItemView listItemView = null; public final class ListItemView { public LinearLayout gas_station_groupon_ll; public TextView gpn_name; public TextView gpn_price; public TextView gpn_old_price; } public FootviewAdapter( Context mContext, ListView mListView) { super(mContext, mListView); } @Override public View getView(int position, View convertView, ViewGroup parent) { final StationImage object = (StationImage)getItem(position); if (convertView == null) { convertView = inflater.inflate(R.layout.lv_gas_station_detail_groupon, parent, false); listItemView = new ListItemView(); creatView(convertView, listItemView); convertView.setTag(listItemView); } else { listItemView = (ListItemView) convertView.getTag(); } listItemView.gpn_name.setText(object.getImg_name()); listItemView.gpn_price.setText("¥" + object.getImg_url_l()); listItemView.gpn_old_price.setText("¥" + object.getImg_url_s()); listItemView.gpn_old_price.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG); //中劃線 return convertView; } private void creatView(View rowView, ListItemView listItemView) { listItemView.gas_station_groupon_ll = (LinearLayout) rowView.findViewById(R.id.gas_station_groupon_ll); listItemView.gpn_name = (TextView) rowView.findViewById(R.id.gpn_name); listItemView.gpn_price = (TextView) rowView.findViewById(R.id.gpn_price); listItemView.gpn_old_price = (TextView) rowView.findViewById(R.id.gpn_old_price); } }
資原始檔(lv_gas_station_detail_groupon)如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gas_station_groupon_ll" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <RelativeLayout android:layout_width="match_parent" android:layout_height="48dp" android:paddingLeft="16dp" android:paddingRight="16dp" > <TextView android:id="@+id/gpn_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:text="ahah" android:textSize="16sp" /> <TextView android:id="@+id/gpn_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginRight="16dp" android:singleLine="true" android:text="abc" /> <TextView android:id="@+id/gpn_old_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_toRightOf="@id/gpn_price" android:singleLine="true" android:text="qew" android:textSize="16sp" /> </RelativeLayout> </LinearLayout>
Activity中的呼叫(例項化FootviewAdapter子類,然後設定相應資料即可):
ArrayList<StationImage> mStationImages = new ArrayList<StationImage>(); ListView listview = null; for (int i = 0; i < 5; i++) { StationImage mStationImage = new StationImage(); mStationImage.setImg_name("第" + i + "個專案的名字"); mStationImage.setImg_url_l("第" + i + "個專案的長URL"); mStationImage.setImg_url_s("第" + i + "個專案的短URL"); mStationImages.add(mStationImage); } listview = (ListView) findViewById(R.id.listview); FootviewAdapter mFootviewAdapter = new FootviewAdapter(this, listview); listview.setAdapter(mFootviewAdapter); mFootviewAdapter.setAdapterData(mStationImages);
相關文章
- 封裝ListView,實現自動載入更多封裝View
- vue實現 可展開 且 可多選table 元件封裝Vue元件封裝
- ListView 通用 Adapter 封裝ViewAPT封裝
- 一個簡單的可展開和收縮的tableviewView
- jQuery實現的表格展開伸縮效果例項jQuery
- android開發(3):列表listview的實現 | 下拉重新整理AndroidView
- 小程式迴圈列表點選展開收縮
- Android實現Rxjava2+Retrofit完美封裝AndroidRxJava封裝
- Android 支付寶支付功能封裝實現Android封裝
- android 用ListView實現表格樣式AndroidView
- Android:Fragment懶載入的實現以及自己的封裝思路AndroidFragment封裝
- jQuery 動畫方式展開或者收縮垂直導航選單jQuery動畫
- JavaScript點選div塊展開和收縮效果詳解JavaScript
- jquery實現的下拉和收縮程式碼例項jQuery
- Android ListView實現品種分類效果AndroidView
- css3實現的箱子拆開和封裝效果CSSS3封裝
- jQuery手風琴風格收縮展開導航選單jQuery
- css3滑鼠懸浮展開收縮導航選單CSSS3
- 點選側邊欄展開和收縮程式碼例項
- (轉)Android 自定義Dialog實現步驟及封裝Android封裝
- Android:ListView的擴充與進階AndroidView
- Android之ListView與SimpleAdapter的使用AndroidViewAPT
- Android listview與adapter用法AndroidViewAPT
- 深度殘差收縮網路:(六)程式碼實現
- Android的ListViewAndroidView
- 實現帶圖示的ListViewView
- 【JavaScript框架封裝】實現一個類似於JQuery的動畫框架的封裝JavaScript框架封裝jQuery動畫
- UIColletionView瀑布流佈局實現思路以及封裝的實現UIView封裝
- Android------Anndroid中ListView在劃屏到底部的時候動態新增ListView的Item實現AndroidView
- 編寫自己的程式碼庫(javascript常用例項的實現與封裝)JavaScript封裝
- Android 友盟社會化分享的整合與封裝Android封裝
- Swift - Alamofire與Cache封裝實現網路快取、下載Swift封裝快取
- android volley解析與二次封裝Android封裝
- android中的ListViewAndroidView
- App啟動廣告頁的實現和封裝APP封裝
- 【JavaScript框架封裝】實現一個類似於JQuery的CSS樣式框架的封裝JavaScript框架封裝jQueryCSS
- Android中Retrofit的封裝使用Android封裝
- 編寫自己的程式碼庫(javascript常用例項的實現與封裝–續)JavaScript封裝