Android—萬能ListView適配器

来源:http://www.cnblogs.com/yunfang/archive/2016/08/16/5777014.html
-Advertisement-
Play Games

ListView是開發中最常用的控制項了,但是總是會寫重覆的代碼,浪費時間又沒有意義。 最近參考一些資料,發現一個萬能ListView適配器,代碼量少,節省時間,總結一下分享給大家。 首先有一個自定義的Adapter繼承於BaseAdapter,下麵是自定義的Adapter,精華在getView()方 ...


ListView是開發中最常用的控制項了,但是總是會寫重覆的代碼,浪費時間又沒有意義。

最近參考一些資料,發現一個萬能ListView適配器,代碼量少,節省時間,總結一下分享給大家。

首先有一個自定義的Adapter繼承於BaseAdapter,下麵是自定義的Adapter,精華在getView()方法中

package com.example.mylistview.util;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public abstract class CommonAdapter<T> extends BaseAdapter {
    /**
     * 上下文
     */
    private Context mContext;
    /**
     * 實體類集合
     */
    private List<T> mDatas;
    private LayoutInflater mInflater;
    /**
     * 控制項id
     */
    private int mlayoutId;

    public CommonAdapter(Context context, List<T> datas, int layoutId) {
        this.mContext = context;
        this.mDatas = datas;
        this.mlayoutId = layoutId;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return mDatas.size();
    }

    @Override
    public T getItem(int arg0) {
        // TODO Auto-generated method stub
        return mDatas.get(arg0);
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return arg0;
    }

    @Override
    public View getView(int arg0, View arg1, ViewGroup arg2) {
        // TODO Auto-generated method stub
        ViewHolder holder = ViewHolder.get(mContext, arg1, arg2, mlayoutId,
                arg0);
        convert(holder, getItem(arg0));

        return holder.getConvertView();
    }

    public abstract void convert(ViewHolder holder, T t);
}

以上的抽象方法convert(ViewHolder holder, T t);就相當於以前通用代碼中的

viewHolder.mTextView = (TextView) convertView .findViewById(R.id.id_tv_title);

viewHolder.mTextView.setText(Bean.getName());

找到控制項的id再去設施setText等重覆的代碼方法中的參數ViewHolder holder, T t    holder就相當於以前通用代碼中的viewHolder,t就相當於一個自己定義的實體類Bean。

以上代碼中getView()方法中有一個ViewHolder是需要自己聲明的,以下是代碼以及詳細註釋:

package com.example.mylistview.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Type;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

public class ViewHolder {
    /**
     * SparseArray類存放View集合
     */
    private SparseArray<View> mViews;
    /**
     * 
     */
    private int mPosition;
    /**
     * 佈局文件
     */
    private View mConvertView;

    public View getConvertView() {
        return mConvertView;
    }

    public ViewHolder(Context context, ViewGroup parent, int layoutId,
            int position) {
        this.mViews = new SparseArray<View>();
        this.mPosition = position;
        this.mConvertView = LayoutInflater.from(context).inflate(layoutId,
                parent, false);
        this.mConvertView.setTag(this);
    }
    /**
     * 拿到一個ViewHolder對象
     * @param context
     * @param convertView
     * @param parent
     * @param layoutId
     * @param position
     * @return
     */
    public static ViewHolder get(Context context, View convertView,
            ViewGroup parent, int layoutId, int position) {
        if (null == convertView) {
            return new ViewHolder(context, parent, layoutId, position);
        } else {
            ViewHolder holder = (ViewHolder) convertView.getTag();
            holder.mPosition = position;
            return holder;
        }
    }
    /**
     * 通過控制項的id獲取對應的控制項,如果沒有則加入views
     * @param viewId
     * @return
     */
    public <T extends View> T getView(int viewId) {
        View view = mViews.get(viewId);

        if (null == view) {
            view = mConvertView.findViewById(viewId);
            mViews.put(viewId, view);
        }

        return (T) view;
    }
    /**
     * 為TextView設置字元串 
     * @param viewId
     * @param text
     * @return
     */
    public ViewHolder setText(int viewId, String text) {
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }
    /** 
     * 為ImageView設置圖片 
     *  
     * @param viewId 
     * @param drawableId 
     * @return 
     */  
    public ViewHolder setImageResource(int viewId, int drawableId)  
    {  
        ImageView view = getView(viewId);  
        view.setImageResource(drawableId);  
        return this;  
    }  
  
  
    public int getPosition()  
    {  
        return mPosition;  
    }  
}

再寫一個Adapter繼承於萬能適配器CommonAdapter,還是要寫一個自己的Adapter,因為一個項目可能會有多個ListView,但是每個的item元素,佈局都會有所不同的,這個淚用來區分不同的ListView與自己所對應的item.這個代碼量較少完全可以寫成內部類在Activity.java中.

package com.example.mylistview.adapter;

import java.util.List;

import android.content.Context;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;

import com.example.mylistview.R;
import com.example.mylistview.domain.Bean;
import com.example.mylistview.util.CommonAdapter;
import com.example.mylistview.util.ViewHolder;

public class MyAdapter extends CommonAdapter<Bean> {

    public MyAdapter(Context context, List<Bean> datas, int layoutId) {
        super(context, datas, layoutId);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void convert(ViewHolder holder, final Bean bean) {
        // TODO Auto-generated method stub
        holder.setText(R.id.tv_title, bean.getTitle())
                .setText(R.id.tv_desc, bean.getDesc())
                .setText(R.id.tv_time, bean.getTime())
                .setText(R.id.tv_phone, bean.getPhone());
        /**
         * 防止CheckBox混亂
         */
        final CheckBox cBox = (CheckBox)(holder.getView(R.id.cb));
        if (cBox != null)
        {
            cBox.setChecked(bean.isChecked());

            cBox.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    bean.setChecked(cBox.isChecked());
                }
            });
        }
    }

}

 

優化之後用適配器的時候就簡單多了下麵是實體類,item和MainActivity.java中的代碼:

實體類:

package com.example.mylistview.domain;

public class Bean {
    private String title;
    private String desc;
    private String time;
    private String phone;
    private boolean isChecked;

    public boolean isChecked() {
        return isChecked;
    }

    public void setChecked(boolean isChecked) {
        this.isChecked = isChecked;
    }

    /**
     * @param title
     * @param desc
     * @param time
     * @param phone
     */
    public Bean(String title, String desc, String time, String phone) {
        this.title = title;
        this.desc = desc;
        this.time = time;
        this.phone = phone;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

}

MainActivity.java:

重點代碼:

參數有上下文,集合,和自己對應的item就可以了
 adapter = new MyAdapter(this, mDatas, R.layout.item);
package com.example.mylistview.ui;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

import com.example.mylistview.R;
import com.example.mylistview.adapter.MyAdapter;
import com.example.mylistview.domain.Bean;

public class MainActivity extends Activity {
    private ListView listView;
    private List<Bean> mDatas;
    /**
     * 適配器
     */
    private MyAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        listener();
    }

    private void listener() {
        // TODO Auto-generated method stub
        listView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
                // TODO Auto-generated method stub
                startActivity(new Intent(MainActivity.this, SecondActivity.class));
            }
        });
    }

    private void initData() {
        // TODO Auto-generated method stub
        mDatas = new ArrayList<Bean>();
        Bean bean = new Bean("Android新技能 Get",
                "Android-打造萬能的ListView和GridView適配器", "2015-08-05", "10086");
        mDatas.add(bean);
        bean = new Bean("撿到權志龍一個",
                "在星巴克撿到權志龍一個", "2015-08-06", "10086");
        mDatas.add(bean);
        bean = new Bean("GetTOP一個",
                "在南韓首爾撿到TOP一個", "2015-08-07", "10086");
        mDatas.add(bean);
    
        adapter = new MyAdapter(this, mDatas, R.layout.item);
        listView.setAdapter(adapter);
        
    }

    private void initView() {
        // TODO Auto-generated method stub
        listView = (ListView) findViewById(R.id.listView);
    }

}

item佈局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp" >

    <CheckBox
        android:focusable="false"
        android:id="@+id/cb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerInParent="true" />

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:singleLine="true"
        android:text="Android新技能 Get" />

    <TextView
        android:id="@+id/tv_desc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_title"
        android:layout_marginTop="10dp"
        android:layout_toLeftOf="@id/cb"
        android:maxLines="2"
        android:text="Android-打造萬能的ListView和GridView適配器"
        android:textColor="#898989" />

    <TextView
        android:id="@+id/tv_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_desc"
        android:layout_marginTop="10dp"
        android:text="2015-08-05"
        android:textColor="#898989"
        android:textSize="12sp" />

    <TextView
        android:id="@+id/tv_phone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@id/tv_desc"
        android:layout_marginTop="10dp"
        android:background="#20793D"
        android:maxLines="1"
        android:text="10086"
        android:padding="4dp"
        android:textColor="#FFF" />

</RelativeLayout>

效果圖:

用這個去適配另一個不同的佈局:

新佈局的Adapter一樣繼承自己的萬能adapter:CommonAdapter

package com.example.mylistview.adapter;

import java.util.List;
import java.util.Map;


import android.content.Context;

import com.example.mylistview.R;
import com.example.mylistview.util.CommonAdapter;
import com.example.mylistview.util.ViewHolder;

public class SecondAdapter extends CommonAdapter<Map<String, String>> {

    public SecondAdapter(Context context, List<Map<String, String>> datas,
            int layoutId) {
        super(context, datas, layoutId);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void convert(ViewHolder holder, Map<String, String> t) {
        // TODO Auto-generated method stub
        holder.setText(R.id.tv_item2values, t.get("values"));
    }

}

Activity.java代碼:

package com.example.mylistview.ui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;


              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • CSS常用樣式之自定義動畫(關鍵幀、動畫名稱、動畫時間、動畫過渡速度、動畫延遲時間、動畫執行次數、動畫的順序、動畫的狀態、動畫時間之外的狀態) ...
  • canvas也有css3里transform的變換功能,transform的底層運算的方式是運用了線性代數里矩陣, 而矩陣是在我們的生活實踐中會經常被使用,它可以把複雜的空間問題呈現出來,它還有很多實踐的 地方,然後不懂它的人會覺得很難,如果要鑽研,這方面知識是不能少的。 canvas里封裝好的變換 ...
  • Ajax的伺服器端用PrintWriter out=resp.getWriter()來響應數據的時候,out.print(0)、out.print(1)來表示成功或失敗,而不用out.write是有原因的,首先來看一下print和write兩者的異同點。 共同點是:兩者都不刷新頁面,只在原來的頁面寫 ...
  • 1、對於string,number等基礎類型,==和 是有區別的 1)不同類型間比較,==之比較“轉化成同一類型後的值”看“值”是否相等, 如果類型不同,其結果就是不等 2)同類型比較,直接進行“值”比較,兩者結果一樣 2、對於Array,Object等高級類型,==和 是沒有區別的 進行“指針地址 ...
  • Devrama Slider 是個圖像滑塊,帶有許多非常有趣的特性。 它不僅支持圖像還支持 HTML 內容。 響應式 方便 CSS3 轉換 轉換效果 進度條 高級的預載入和延遲載入 CSS 自定義 用戶可以定義導航或者控制器 線上實例 實例演示 使用方法 複製 複製 下載 ...
  • 在 jQuery3.0中,buildFragment 是一個私有函數,用來構建一個包含子節點 fragment 對象。這個 fragment 在 DOM1 中就已經有了,所有瀏覽器都支持。當頻繁操作(添加、插入) DOM 時使用該方法可以提高性能,John resig 做過一個測試及一篇博客。 jQ ...
  • CSS常用樣式之變形樣式(2D平移、2D旋轉、2D縮放、斜切扭曲),過渡動畫(過渡屬性、過渡時間、過渡函數、過渡延遲時間) ...
  • 這是個css3動畫框架,現在很流行,在小動畫效果有很多,使用的方式 一、atention Seekers 1、bounce 2、flash 3、pulse 4、rubberBand 5、shake 6、swing 7、tada 8、wobble 9、jello 二、Bouncing Entrance ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...