Android中適用於ListView、GridView等組件的通用Adapter,androidgridview

來源:互聯網
上載者:User

Android中適用於ListView、GridView等組件的通用Adapter,androidgridview

    今天隨便逛逛CSDN,看到首頁上推薦了一篇文章Android 快速開發系列 打造萬能的ListView GridView 適配器,剛好這兩天寫項目自己也封裝了類似的CommonAdapter,以前也在github上看到過這樣的庫,於是自己也把自己的代碼再次整理出來與大家分享,也希望能夠在CSDN這個平台上學到更多的東西,下面就一起來看看吧。

    平時我們在項目中使用到ListView和GridView組件都是都會用到Adapter,比較多的情況是繼承自BaseAdapter,然後實現getCount、getView等方法,再使用ViewHolder來提高一下效率.我們看下面一個簡單的例子 :

ListView布局檔案

fragment_main.xml :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.push_demo_1.MainActivity$PlaceholderFragment" >    <ListView        android:id="@+id/my_listview"        android:layout_width="match_parent"        android:layout_height="match_parent" /></RelativeLayout>
ListView子項的布局檔案

listview_item_layout.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" >    <ImageView        android:id="@+id/my_imageview"        android:layout_width="64dp"        android:layout_height="64dp"        android:contentDescription="@string/app_name" />    <TextView        android:id="@+id/my_textview"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginLeft="20dp"        android:textSize="18sp" /></LinearLayout>

曾經我們要寫下的Adapter代碼
public class NormalAdapter extends BaseAdapter {    Context mContext;    LayoutInflater mInflater;    List<ListViewItem> mDataList;    /**     * @param context     * @param data     */    public NormalAdapter(Context context, List<ListViewItem> data) {        mContext = context;        mInflater = LayoutInflater.from(context);        mDataList = data;    }    @Override    public int getCount() {        return mDataList.size();    }    @Override    public ListViewItem getItem(int position) {        return mDataList.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder viewHolder = null;        if (convertView == null) {            convertView = mInflater.inflate(R.layout.listview_item_layout, null, false);            viewHolder = new ViewHolder();            viewHolder.mImageView = (ImageView) convertView.findViewById(R.id.my_imageview);            viewHolder.mTextView = (TextView) convertView.findViewById(R.id.my_textview);            convertView.setTag(viewHolder);        } else {            viewHolder = (ViewHolder) convertView.getTag();        }        viewHolder.mImageView.setImageResource(getItem(position).mDrawableId);        viewHolder.mTextView.setText(getItem(position).mText);        return convertView;    }    /**     * ViewHolder     *      * @author mrsimple     */    static class ViewHolder {        ImageView mImageView;        TextView mTextView;    }}

    然而寫過多遍以後我們發現我們總是重複地在寫這些getCount、getItem、getView方法以及ViewHolder,導致了很多重複工作,而且及其無聊,於是我把這些重複工作抽象起來(以前也有在github上看到這樣的通用Adapter實現),整理一下也便於自己使用,也是自己學習的一個過程。下面我們看看使用CommonAdapter後我們做與上面同樣的工作需要怎麼寫。

使用CommonAdapter後要寫的代碼
CommonAdapter<ListViewItem> listAdapter = new CommonAdapter<ListViewItem>(getActivity(),                    R.layout.listview_item_layout, mockListViewItems()) {                @Override                protected void fillItemData(CommonViewHolder viewHolder, ListViewItem item) {                    // 設定圖片                    viewHolder.setImageForView(R.id.my_imageview, item.mDrawableId);                    // 設定text                    viewHolder.setTextForTextView(R.id.my_textview, item.mText);                }            }

其中mockListViewImtes是準備了一些資料, 代碼如下 : 
        /**         * 類比一些資料         *          * @return         */        private List<ListViewItem> mockListViewItems() {            List<ListViewItem> dataItems = new ArrayList<ListViewItem>();            dataItems.add(new ListViewItem(R.drawable.girl_96, "girl_96.png"));            dataItems.add(new ListViewItem(R.drawable.fire_96, "fire_96.png"));            dataItems.add(new ListViewItem(R.drawable.grimace_96, "grimace_96.png"));            dataItems.add(new ListViewItem(R.drawable.laugh_96, "laugh_96.png"));            return dataItems;        }

可以看到,我們的代碼量減少了很多,如果一個項目中有好幾個ListView、GridView等組件,我們就不需要重複做那麼多無聊的工作了。我們看看 : 


CommonAdapter實現

/** * *created by Mr.Simple, Aug 28, 201412:26:52 PM. *Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved. * *                ##################################################### *                #                                                   # *                #                       _oo0oo_                     #    *                #                      o8888888o                    # *                #                      88" . "88                    # *                #                      (| -_- |)                    # *                #                      0\  =  /0                    #    *                #                    ___/`---'\___                  # *                #                  .' \\|     |# '.                 # *                #                 / \\|||  :  |||# \                # *                #                / _||||| -:- |||||- \              # *                #               |   | \\\  -  #/ |   |              # *                #               | \_|  ''\---/''  |_/ |             # *                #               \  .-\__  '-'  ___/-. /             # *                #             ___'. .'  /--.--\  `. .'___           # *                #          ."" '<  `.___\_<|>_/___.' >' "".         # *                #         | | :  `- \`.;`\ _ /`;.`/ - ` : | |       # *                #         \  \ `_.   \_ __\ /__ _/   .-` /  /       # *                #     =====`-.____`.___ \_____/___.-`___.-'=====    # *                #                       `=---='                     # *                #     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   # *                #                                                   # *                #               佛祖保佑         永無BUG              # *                #                                                   # *                ##################################################### */package com.uit.commons;import android.content.Context;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import java.util.List;/** * 這是一個通用、抽象的適配器類,覆寫了BaseAdapter的getCount, getItem, getItemId, * getView方法,在getView方法中通過 * 通用的CommonViewHolder來對convertView的進行處理,並且緩衝convertView中的其他View元素 * ,降低了ListView、GridView 等組件的Adapter和ViewHolder的代碼量. * 使用者只需要在fillItemData函數中將第position位置裡的資料填充到listview或者gridview的第position的view中即可 * ,具體使用執行個體參考文檔. *  * @author mrsimple * @param <T> 資料來源的類型 */public abstract class CommonAdapter<T> extends BaseAdapter {    /**     * Context     */    Context mContext;    /**     * 要展示的資料列表     */    List<T> mData;    /**     * 每一項的布局id,例如R.layout.my_listview_item.     */    private int mItemLayoutId = -1;    /**     * @param context Context     * @param itemLayoutResId     *            每一項(適用於listview、gridview等AbsListView子類)的布局資源id,例如R.layout.     *            my_listview_item.     * @param dataSource 資料來源     */    public CommonAdapter(Context context, int itemLayoutResId, List<T> dataSource) {        checkParams(context, itemLayoutResId, dataSource);        mContext = context;        mItemLayoutId = itemLayoutResId;        mData = dataSource;    }    /**     * 檢查參數的有效性     *      * @param context     * @param itemLayoutResId     * @param dataSource     */    private void checkParams(Context context, int itemLayoutResId, List<T> dataSource) {        if (context == null || itemLayoutResId < 0 || dataSource == null) {            throw new RuntimeException(                    "context == null || itemLayoutResId < 0 || dataSource == null, please check your params");        }    }    /**     * 返回資料的總數     */    @Override    public int getCount() {        return mData.size();    }    /**     * 返回position位置的資料     */    @Override    public T getItem(int position) {        return mData.get(position);    }    /**     * item id, 返回position     */    @Override    public long getItemId(int position) {        return position;    }    /**     * 返回position位置的view, 即listview、gridview的第postion個view     */    @Override    public View getView(int position, View convertView, ViewGroup parent) {        // 擷取ViewHolder        CommonViewHolder viewHolder = CommonViewHolder.getViewHolder(mContext, convertView,                mItemLayoutId);        // 填充資料        fillItemData(viewHolder, getItem(position));        // 返回convertview        return viewHolder.getConvertView();    }    /**     * 使用者必須覆寫該方法來講資料填充到視圖中     *      * @param viewHolder 通用的ViewHolder, 裡面會裝載listview,     *            gridview等組件的每一項的視圖,並且緩衝其子view     * @param item 資料來源的第position項資料     */    protected abstract void fillItemData(CommonViewHolder viewHolder, T item);}

CommonViewHolder實現

/** * *created by Mr.Simple, Aug 28, 201412:32:45 PM. *Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved. * *                ##################################################### *                #                                                   # *                #                       _oo0oo_                     #    *                #                      o8888888o                    # *                #                      88" . "88                    # *                #                      (| -_- |)                    # *                #                      0\  =  /0                    #    *                #                    ___/`---'\___                  # *                #                  .' \\|     |# '.                 # *                #                 / \\|||  :  |||# \                # *                #                / _||||| -:- |||||- \              # *                #               |   | \\\  -  #/ |   |              # *                #               | \_|  ''\---/''  |_/ |             # *                #               \  .-\__  '-'  ___/-. /             # *                #             ___'. .'  /--.--\  `. .'___           # *                #          ."" '<  `.___\_<|>_/___.' >' "".         # *                #         | | :  `- \`.;`\ _ /`;.`/ - ` : | |       # *                #         \  \ `_.   \_ __\ /__ _/   .-` /  /       # *                #     =====`-.____`.___ \_____/___.-`___.-'=====    # *                #                       `=---='                     # *                #     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   # *                #                                                   # *                #               佛祖保佑         永無BUG              # *                #                                                   # *                ##################################################### */package com.uit.commons;import android.content.Context;import android.graphics.Bitmap;import android.view.View;import android.widget.CheckBox;import android.widget.ImageView;import android.widget.TextView;import com.uit.commons.utils.ViewFinder;/** * 這是一個通用的ViewHolder, 將會裝載AbsListView子類的item View, 並且將item * view中的子視圖進行緩衝和索引,使得使用者能夠方便的擷取這些子view, 減少了代碼重複。 *  * @author mrsimple */public class CommonViewHolder {    /**     * 建構函式     *      * @param context Context     * @param layoutId ListView、GridView或者其他AbsListVew子類的 Item View的資源布局id     */    protected CommonViewHolder(Context context, int layoutId) {        // 初始化布局, 裝載ContentView        ViewFinder.initContentView(context, layoutId);        // 將ViewHolder儲存在ContentView的tag中        ViewFinder.getContentView().setTag(this);    }    /**     * 擷取CommonViewHolder,當convertView為空白的時候從布局xml裝載item view,     * 並且將該CommonViewHolder設定為convertView的tag, 便於複用convertView.     *      * @param context Context     * @param convertView Item view     * @param layoutId 布局資源id, 例如R.layout.my_listview_item.     * @return 通用的CommonViewHolder執行個體     */    public static CommonViewHolder getViewHolder(Context context, View convertView, int layoutId) {        if (convertView == null) {            return new CommonViewHolder(context, layoutId);        }        return (CommonViewHolder) convertView.getTag();    }    /**     * @return 當前項的convertView, 在建構函式中裝載     */    public View getConvertView() {        return ViewFinder.getContentView();    }    /**     * 為id為textViewId的TextView設定常值內容     *      * @param textViewId 視圖id     * @param text 要設定的常值內容     */    public void setTextForTextView(int textViewId, CharSequence text) {        TextView textView = ViewFinder.findViewById(textViewId);        if (textView != null) {            textView.setText(text);        }    }    /**     * 為ImageView設定圖片     *      * @param imageViewId ImageView的id, 例如R.id.my_imageview     * @param drawableId Drawable圖片的id, 例如R.drawable.my_photo     */    public void setImageForView(int imageViewId, int drawableId) {        ImageView imageView = ViewFinder.findViewById(imageViewId);        if (imageView != null) {            imageView.setImageResource(drawableId);        }    }    /**     * 為ImageView設定圖片     *      * @param imageViewId ImageView的id, 例如R.id.my_imageview     * @param bmp Bitmap圖片     */    public void setImageForView(int imageViewId, Bitmap bmp) {        ImageView imageView = ViewFinder.findViewById(imageViewId);        if (imageView != null) {            imageView.setImageBitmap(bmp);        }    }    /**     * 為CheckBox設定是否選中     *      * @param checkViewId CheckBox的id     * @param isCheck 是否選中     */    public void setCheckForCheckBox(int checkViewId, boolean isCheck) {        CheckBox checkBox = ViewFinder.findViewById(checkViewId);        if (checkBox != null) {            checkBox.setChecked(isCheck);        }    }}


ViewFinder輔助類

/** * view finder, 方便尋找View。使用者需要在使用時調用initContentView, * 將Context和布局id傳進來,然後使用findViewById來擷取需要的view * ,findViewById為泛型方法,返回的view則直接是你接收的類型,而不需要進行強制類型轉換.比如, * 以前我們在Activity中找一個TextView一般是這樣 :  * TextView textView = (TextView)findViewById(viewId);  * 如果頁面中的控制項比較多,就會有很多的類型轉換,而使用ViewFinder則免去了類型轉換, * 樣本如下 :  * TextView textView = ViewFinder.findViewById(viewId); *  * @author mrsimple */public final class ViewFinder {    /**     * LayoutInflater     */    static LayoutInflater mInflater;    /**     * 每項的View的sub view Map     */    private static SparseArray<View> mViewMap = new SparseArray<View>();    /**     * Content View     */    static View mContentView;    /**     * 初始化ViewFinder, 實際上是擷取到該頁面的ContentView.     *      * @param context     * @param layoutId     */    public static void initContentView(Context context, int layoutId) {        mInflater = LayoutInflater.from(context);        mContentView = mInflater.inflate(layoutId, null, false);        if (mInflater == null || mContentView == null) {            throw new RuntimeException(                    "ViewFinder init failed, mInflater == null || mContentView == null.");        }    }    /**     * @return     */    public static View getContentView() {        return mContentView;    }    /**     * @param viewId     * @return     */    @SuppressWarnings("unchecked")    public static <T extends View> T findViewById(int viewId) {        // 先從view map中尋找,如果有的緩衝的話直接使用,否則再從mContentView中找        View tagetView = mViewMap.get(viewId);        if (tagetView == null) {            tagetView = mContentView.findViewById(viewId);            mViewMap.put(viewId, tagetView);        }        return tagetView == null ? null : (T) mContentView.findViewById(viewId);    }}

         代碼都在Github上了,請猛擊這裡。


安卓中點擊listview顯示不同圖片的gridview,怎實現,效果如下

這個涉及到gridView的重新整理 當你切換listview選中項時 你要去重新整理右邊gridview的內容,具體就是重新整理adapter的資料了
 
android 怎通過ListView的索引(adapter中的position)擷取View

使用同一個資料來源,點擊某一項時,不管是listView還是gridView,比如是選中,那麼資料來源中每個item對應的資料可以添加一個選中focused欄位,只要改變共同的資料來源,然後調用adapter.notifydatasetchanged就可以了
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.