天天看點

ListView資料項隔行換色控制實作詳解

    看到有朋友在群裡問過ListView項達到一定數量時加不同色選項的功能,有時間就學習了下ListView隔行換色的效果,大體效果實作出來了,吼吼,寫部落格裡面,跟大家學習交流,一樣的,先貼效果,再上代碼,效果圖如下:

一:五行換色效果 

<a target="_blank" href="http://blog.51cto.com/attachment/201203/141047999.jpg"></a>

二:快速拖動塊顯示效果

<a target="_blank" href="http://blog.51cto.com/attachment/201203/141107448.gif"></a>

三:循環從0開始時的效果圖三 這個地方貼此圖原因大家看主要制代碼中的注釋

<a target="_blank" href="http://blog.51cto.com/attachment/201203/141120395.jpg"></a>

四:循環從0開始時的效果圖四

<a target="_blank" href="http://blog.51cto.com/attachment/201203/141158488.jpg"></a>

五:單擊按鈕後觸發事件(小工具做的,有點失真,真機上正常的,大家放心)

<a target="_blank" href="http://blog.51cto.com/attachment/201203/142309788.gif"></a>

六:工程結構圖如下

<a target="_blank" href="http://blog.51cto.com/attachment/201203/141226898.jpg"></a>

七:主要制類代碼如下:

package com.xiaoma.listviewbackground; 

import java.util.ArrayList; 

import java.util.HashMap; 

import java.util.HashSet; 

import java.util.List; 

import java.util.Map; 

import java.util.Set; 

import java.util.TreeSet; 

import android.app.Activity; 

import android.app.Dialog; 

import android.app.ProgressDialog; 

import android.content.Context; 

import android.graphics.drawable.Drawable; 

import android.os.Bundle; 

import android.util.Log; 

import android.view.LayoutInflater; 

import android.view.View; 

import android.view.View.OnClickListener; 

import android.view.ViewGroup; 

import android.widget.AdapterView; 

import android.widget.AdapterView.OnItemSelectedListener; 

import android.widget.BaseAdapter; 

import android.widget.Button; 

import android.widget.ImageView; 

import android.widget.ListView; 

import android.widget.TextView; 

import android.widget.Toast; 

/**   

* @Title: ListViewBackgroundDemoActivity.java 

* @Package com.xiaoma.listviewbackground 

* @Description: 小馬學習隔行換色,一定仔細看注釋 

* @author XiaoMa 

*/ 

public class ListViewBackgroundDemoActivity extends Activity 

            implements OnItemSelectedListener{ 

    private ListView lv = null; 

    /** Called when the activity is first created. */ 

    @Override 

    public void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        setContentView(R.layout.main); 

        lv = (ListView)findViewById(R.id.listview); 

        /** 

         * 設定快速滾動塊可用,這個大家注意下,就是設定之後,ListView 

         * 裡面的資料條數必須大于一定數量(小馬試了下,這個數量是大于一屏) 

         * 才會顯示這個小拖塊,不然無效 

         */ 

        lv.setFastScrollEnabled(true); 

        lv.setOnItemSelectedListener(this); 

        lv.setAdapter(new ListDemoAdapter(getApplicationContext())); 

    } 

    /** 

    * @Title: ListViewBackgroundDemoActivity.java 

    * @Package com.xiaoma.listviewbackground 

    * @Description:擴充卡實作  

    * @author XiaoMa 

     */ 

    private class ListDemoAdapter extends BaseAdapter{ 

        private static final int ITEM = 0; 

        private static final int SEPARATOR = 1; 

        private static final int TYPE_MAX_COUNT = SEPARATOR + 1; 

        private LayoutInflater inflater = null ; 

        private List&lt;String&gt; listItem = new ArrayList&lt;String&gt;(); 

        /* 

         * 用這個set來儲存分隔線的位置,這個地方必須注意,小馬寫兩個不同類型的Set來跟大家複習下 

         * 這兩個小東東的不同之處,效果太神奇了,這個Set你該用哪個會直接影響到換色效果的,不同之 

         * 處是: 

         *  

         * TreeSet:基于 TreeMap 的 NavigableSet 實作。使用元素的自然順序對元素進行排序 

         *               或者根據建立 set 時提供的 Comparator 進行排序,具體取決于使用的構造方法 

         * Set:一個不包含重複元素的 collection。更确切地講,set 不包含滿足 e1.equals(e2)  

         *     的元素對 e1 和 e2,并且最多包含一個 null 元素。正如其名稱所暗示的,此接口模仿了數學 

         *     上的 set 抽象 

        @SuppressWarnings("rawtypes") 

        //private Set set = new HashSet(); 

        private TreeSet set = new TreeSet(); 

        private Map map = new HashMap(); 

        public ListDemoAdapter(Context context ){ 

            this.inflater = LayoutInflater.from(context); 

            /** 

             * 大家稍微注意下這個循環,i從1開始?為什麼?  小馬在這犯的錯 

             * 每5條資料加一條換色Item是用 i%6 == 0來控制的,如果這 

             * 個i值從0開始的話,會出現上面貼圖中錯誤的換色,看圖三,圖四, 

             * 原因是取餘的時候小馬犯了低級錯誤,小錯,記下:兩數取餘,前者 

             * 大于後者時,取餘會按正常取餘來取,如果前者小于後者時,取餘 

             * 後的值始終是前者,如果這個地方的i從0開始取的話,正好是滿 

             * 足取餘後的值等于0這個情況,就出現上面兩圖中的錯誤隔色圖了, 

             * 目前者大于等于後者時,這個隔色就又正常了,一定注意下,記在這, 

             * 提醒大家也提醒自己,吼吼,聽不明白的可以看下小馬在工程中加的 

             * 一個測試類(測試取餘規律的類PercentTest.java) 

             */ 

            //填充ListView 

            for(int i=1;i&lt;=50;i++){ 

                this.listItem.add("添加的第"+i+"條資料"); 

                if(i%6 == 0){ 

                    addSeparatorItem(); 

                } 

                Log.i("KKK", "添加的第"+i+"條資料"); 

            } 

        } 

         * 添加換色項方法實作 

         * @param item 

        @SuppressWarnings("unchecked") 

        public void addSeparatorItem() { 

            set.add(listItem.size()-1); 

            notifyDataSetChanged(); 

         * 此處是根據特定值(在getView方法中加入) 

         * 來判斷應該繪制選項還是換色選項的分支值 

         * 由position傳回view type id 

        @Override 

        public int getItemViewType(int position) { 

            return set.contains(position) ? SEPARATOR : ITEM; 

         * 傳回你有多少個不同的布局 

        public int getViewTypeCount() { 

            return TYPE_MAX_COUNT; 

        public int getCount() { 

            return listItem.size(); 

        public Object getItem(int position) { 

            return listItem.get(position); 

        public long getItemId(int position) { 

            return position; 

         * 這個地方也需要注意下,小馬這個方法裡面寫的有點多了,其實官方是不支援在 

         * getView()方法中寫太多的邏輯因為你手拖下螢幕,這個方法是逛調用 

         * 的,是以太多邏輯不适合放在這個地方,大家可自行調整下,但有些還是必 

         * 須的,寫在這無防...吼吼 

        public View getView(int position, View convertView, ViewGroup parent) { 

            int type = getItemViewType(position); 

            XiaoMa xiaoMa = null; 

            final int location = position; 

            if(convertView == null){ 

                switch (type) { 

                //如果需要繪制選項時分支 

                case ITEM: 

                    xiaoMa = new XiaoMa(); 

                    convertView = inflater.inflate(R.layout.listview_items, null); 

                    xiaoMa.iv = (ImageView)convertView.findViewById(R.id.ItemImage); 

                    xiaoMa.tv = (TextView)convertView.findViewById(R.id.ItemTitle); 

                    xiaoMa.text = (TextView)convertView.findViewById(R.id.itemtext); 

                    xiaoMa.btn = (Button)convertView.findViewById(R.id.view_btn); 

                    break; 

                //如果需要繪制換色選項時分支 

                case SEPARATOR: 

                    convertView = inflater.inflate(R.layout.separator, null); 

                    /* 

                     * 這個地方的drawable2用法跟在ListView換色選項布局中的 

                     * android:background="@drawable/gradient_box" 

                     * 效果是一樣的,小馬寫在這,熟悉下兩種方式,大家根據自己需要改 

                     */ 

                    Drawable drawable2 = getResources().getDrawable(R.drawable.gradient_box); 

                    xiaoMa.sep = (TextView)convertView.findViewById(R.id.sep); 

                    xiaoMa.sep.setBackgroundDrawable(drawable2); 

                /*  

                 * 此處小馬犯錯了,如果下面這句不加的話, 

                 * 加載時正常,拖動清單時就會報空指針了, 

                 * 小點注意下 

                 */ 

                convertView.setTag(xiaoMa); 

            }else{ 

                xiaoMa = (XiaoMa)convertView.getTag(); 

            xiaoMa.iv.setBackgroundResource(R.drawable.xiaolvzi); 

            xiaoMa.tv.setText("這是第"+(position+1)+"個标題"); 

            xiaoMa.text.setText("這是第"+(position+1)+"個概述"); 

             * 按鈕事件監聽實作 

            xiaoMa.btn.setOnClickListener(new OnClickListener() { 

                @Override 

                public void onClick(View v) { 

                    //單擊Item按鈕後,彈出提示 

                    ShowDialog(location);    

            }); 

            return convertView; 

     * 彈出提示實作,這個地方擴充一下,細心的話大家會發現小馬違反了方法命名規範,其實不是的, 

     * 安卓Activity有臨時彈出對話框方法的,跟下面這個方法隻有一個字母之差(小馬故意 

     * 首字母大寫的),安卓自帶彈出方法在這個方法下面的注釋中 

     * @param posi 

    private void ShowDialog(int posi){ 

        Toast.makeText(getApplicationContext(), "單擊了第"+(posi+1) 

                +"個按鈕", Toast.LENGTH_SHORT).show(); 

         * 下面這兩個方法大家熟悉吧?調用系統提供的臨時彈出對話框,必須實作下面的 

         * onCreateDialog(int id)方法 

        showDialog(1);//彈出時可以做如:從伺服器取資料等操作 

         * 這個地方小馬就簡單的睡眠5秒種來模拟從伺服器下載下傳資料完成後關閉對話框 

        new Thread(new Runnable() { 

            @Override 

            public void run() { 

                try { 

                    Log.i("KKK", "已進入睡眠"); 

                    Thread.sleep(3000); 

                    dismissDialog(1);//隐藏 表示資料下載下傳完畢等的... 

                } catch (Exception e) { 

                    e.printStackTrace(); 

        }).start(); 

    protected Dialog onCreateDialog(int id) { 

         * 下面這個構造器中的this不能用getApplicationContext()來代替, 

         * 但可用類名.this來代替,沒有為什麼, 必須這樣寫!!!這個地方小馬暈了 

         * 不少時間,如果直接get....代碼沒錯,但還是會報錯,很邪門的哦 ... 

        ProgressDialog dialog = new ProgressDialog(this); 

        //小測試,中文就臨時寫這了,大家要注意把内容都寫到string.xml中去,好習慣從小開始養,嘿嘿 

        dialog.setCancelable(false);//設定使用者不能用傳回鍵取消對話框 

        dialog.setIcon(getResources().getDrawable(R.drawable.xiaolvzi)); 

        dialog.setTitle("那些年,我們一起追的女孩"); 

        dialog.setMessage("小馬果 呆丫頭 O_O"); 

        dialog.show(); 

        return dialog; 

    * @Description: 為提高加載效率而寫的類,可以看下ListView優化 

    public final class XiaoMa{ 

        public  ImageView iv ; 

        public TextView tv ;  

        public Button btn ; 

        public TextView text; 

        public TextView sep; 

    public void onItemSelected(AdapterView&lt;?&gt; parent, View view, int position, 

            long id) { 

    public void onNothingSelected(AdapterView&lt;?&gt; parent) { 

八:臨時測試類代碼如下(小兒科的東西,但還是注意下):

* @Title: PercentTest.java 

* @Description: 測試取餘規律,必須在JAVA工程下Run,别直接在這跑 

public class PercentTest { 

 public static void main(String[] args) { 

    int a = 15; 

    int b = 9; 

    System.out.println("9%15 = "+9%15); 

    System.out.println("15%9 = "+15%9); 

九:看代碼大家一定注意仔細看下小馬注釋部分,主布局代碼如下:

&lt;?xml version="1.0" encoding="utf-8"?&gt; 

&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 

    android:layout_width="fill_parent" 

    android:layout_height="fill_parent" 

    android:orientation="vertical" &gt; 

   &lt;!--  Back Up &lt;ListView  

        android:id="@+id/listview" 

        android:layout_width="wrap_content" 

        android:layout_height="fill_parent" 

        android:smoothScrollbar="true" 

        android:drawSelectorOnTop="false" 

        android:listSelector="#00000000" 

        /&gt; 

   --&gt; 

    &lt;ListView  

        android:layout_width="fill_parent" 

        android:choiceMode="none" 

        android:focusable="false" android:scrollingCache="false" 

        android:clickable="false" android:dividerHeight="0.5dip" 

   &lt;!--   &lt;ListView android:id="@+id/list_coupon"  

        android:layout_height="wrap_content" 

        android:drawSelectorOnTop="false" android:choiceMode="none" 

        android:fadingEdge="none" android:focusableInTouchMode="false" 

        android:divider="@drawable/separator" /&gt; 

    --&gt; 

&lt;/LinearLayout&gt; 

      最後,還是跟往常一樣,如果代碼沒詳細看的,可以下載下傳下此小DEMO源碼,共同學習交流下,這個裡面還是有很多地方可以改進的,隻是寫個思路,這裡面問題還是蠻多的,如果覺得代碼不清楚,有問題了還請大家多指點指點,小馬在此先謝過啦,謝謝...加油!

<a href="http://down.51cto.com/data/2360085" target="_blank">附件:http://down.51cto.com/data/2360085</a>

     本文轉自華華世界 51CTO部落格,原文連結:http://blog.51cto.com/mzh3344258/810411,如需轉載請自行聯系原作者

繼續閱讀