看到有朋友在群里问过ListView项达到一定数量时加不同色选项的功能,有时间就学习了下ListView隔行换色的效果,大体效果实现出来了,吼吼,写博客里面,跟大家学习交流,一样的,先贴效果,再上代码,效果图如下:

一:五行换色效果 

二:快速拖动块显示效果

三:循环从0开始时的效果图三 这个地方贴此图原因大家看主控制代码中的注释

四:循环从0开始时的效果图四

五:单击按钮后触发事件(小工具做的,有点失真,真机上正常的,大家放心)

六:工程结构图如下

七:主控制类代码如下:

  1. package com.xiaoma.listviewbackground; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.HashMap; 
  5. import java.util.HashSet; 
  6. import java.util.List; 
  7. import java.util.Map; 
  8. import java.util.Set; 
  9. import java.util.TreeSet; 
  10.  
  11. import android.app.Activity; 
  12. import android.app.Dialog; 
  13. import android.app.ProgressDialog; 
  14. import android.content.Context; 
  15. import android.graphics.drawable.Drawable; 
  16. import android.os.Bundle; 
  17. import android.util.Log; 
  18. import android.view.LayoutInflater; 
  19. import android.view.View; 
  20. import android.view.View.OnClickListener; 
  21. import android.view.ViewGroup; 
  22. import android.widget.AdapterView; 
  23. import android.widget.AdapterView.OnItemSelectedListener; 
  24. import android.widget.BaseAdapter; 
  25. import android.widget.Button; 
  26. import android.widget.ImageView; 
  27. import android.widget.ListView; 
  28. import android.widget.TextView; 
  29. import android.widget.Toast; 
  30.  
  31. /**   
  32. * @Title: ListViewBackgroundDemoActivity.java 
  33. * @Package com.xiaoma.listviewbackground 
  34. * @Description: 小马学习隔行换色,一定仔细看注释 
  35. * @author XiaoMa 
  36. */ 
  37. public class ListViewBackgroundDemoActivity extends Activity 
  38.             implements OnItemSelectedListener{ 
  39.      
  40.     private ListView lv = null
  41.      
  42.     /** Called when the activity is first created. */ 
  43.     @Override 
  44.     public void onCreate(Bundle savedInstanceState) { 
  45.         super.onCreate(savedInstanceState); 
  46.         setContentView(R.layout.main); 
  47.          
  48.         lv = (ListView)findViewById(R.id.listview); 
  49.          
  50.         /** 
  51.          * 设置快速滚动块可用,这个大家注意下,就是设置之后,ListView 
  52.          * 里面的数据条数必须大于一定数量(小马试了下,这个数量是大于一屏) 
  53.          * 才会显示这个小拖块,不然无效 
  54.          */ 
  55.         lv.setFastScrollEnabled(true); 
  56.         lv.setOnItemSelectedListener(this); 
  57.         lv.setAdapter(new ListDemoAdapter(getApplicationContext())); 
  58.     } 
  59.      
  60.     /** 
  61.     * @Title: ListViewBackgroundDemoActivity.java 
  62.     * @Package com.xiaoma.listviewbackground 
  63.     * @Description:适配器实现  
  64.     * @author XiaoMa 
  65.      */ 
  66.     private class ListDemoAdapter extends BaseAdapter{ 
  67.          
  68.         private static final int ITEM = 0
  69.         private static final int SEPARATOR = 1
  70.         private static final int TYPE_MAX_COUNT = SEPARATOR + 1
  71.         private LayoutInflater inflater = null ; 
  72.         private List<String> listItem = new ArrayList<String>(); 
  73.          
  74.         /* 
  75.          * 用这个set来保存分隔线的位置,这个地方必须注意,小马写两个不同类型的Set来跟大家复习下 
  76.          * 这两个小东东的不同之处,效果太神奇了,这个Set你该用哪个会直接影响到换色效果的,不同之 
  77.          * 处是: 
  78.          *  
  79.          * TreeSet:基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序 
  80.          *               或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法 
  81.          *  
  82.          * Set:一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2)  
  83.          *     的元素对 e1 和 e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学 
  84.          *     上的 set 抽象 
  85.          */ 
  86.         @SuppressWarnings("rawtypes"
  87.         //private Set set = new HashSet(); 
  88.         private TreeSet set = new TreeSet(); 
  89.         private Map map = new HashMap(); 
  90.          
  91.         public ListDemoAdapter(Context context ){ 
  92.             this.inflater = LayoutInflater.from(context); 
  93.              
  94.             /** 
  95.              * 大家稍微注意下这个循环,i从1开始?为什么?  小马在这犯的错 
  96.              * 每5条数据加一条换色Item是用 i%6 == 0来控制的,如果这 
  97.              * 个i值从0开始的话,会出现上面贴图中错误的换色,看图三,图四, 
  98.              * 原因是取余的时候小马犯了低级错误,小错,记下:两数取余,前者 
  99.              * 大于后者时,取余会按正常取余来取,如果前者小于后者时,取余 
  100.              * 后的值始终是前者,如果这个地方的i从0开始取的话,正好是满 
  101.              * 足取余后的值等于0这个情况,就出现上面两图中的错误隔色图了, 
  102.              * 当前者大于等于后者时,这个隔色就又正常了,一定注意下,记在这, 
  103.              * 提醒大家也提醒自己,吼吼,听不明白的可以看下小马在工程中加的 
  104.              * 一个测试类(测试取余规律的类PercentTest.java) 
  105.              */ 
  106.             //填充ListView 
  107.             for(int i=1;i<=50;i++){ 
  108.                 this.listItem.add("添加的第"+i+"条数据"); 
  109.                 if(i%6 == 0){ 
  110.                     addSeparatorItem(); 
  111.                 } 
  112.                 Log.i("KKK""添加的第"+i+"条数据"); 
  113.             } 
  114.         } 
  115.          
  116.         /** 
  117.          * 添加换色项方法实现 
  118.          * @param item 
  119.          */ 
  120.         @SuppressWarnings("unchecked"
  121.         public void addSeparatorItem() { 
  122.             set.add(listItem.size()-1); 
  123.             notifyDataSetChanged(); 
  124.         } 
  125.          
  126.         /** 
  127.          * 此处是根据特定值(在getView方法中加入) 
  128.          * 来判断应该绘制选项还是换色选项的分支值 
  129.          * 由position返回view type id 
  130.          */ 
  131.         @Override 
  132.         public int getItemViewType(int position) { 
  133.             return set.contains(position) ? SEPARATOR : ITEM; 
  134.         } 
  135.          
  136.         /** 
  137.          * 返回你有多少个不同的布局 
  138.          */ 
  139.         @Override 
  140.         public int getViewTypeCount() { 
  141.             return TYPE_MAX_COUNT; 
  142.         } 
  143.          
  144.         @Override 
  145.         public int getCount() { 
  146.             return listItem.size(); 
  147.         } 
  148.  
  149.         @Override 
  150.         public Object getItem(int position) { 
  151.             return listItem.get(position); 
  152.         } 
  153.  
  154.         @Override 
  155.         public long getItemId(int position) { 
  156.             return position; 
  157.         } 
  158.          
  159.         /** 
  160.          * 这个地方也需要注意下,小马这个方法里面写的有点多了,其实官方是不支持在 
  161.          * getView()方法中写太多的逻辑因为你手拖下屏幕,这个方法是逛调用 
  162.          * 的,所以太多逻辑不适合放在这个地方,大家可自行调整下,但有些还是必 
  163.          * 须的,写在这无防...吼吼 
  164.          */ 
  165.         @Override 
  166.         public View getView(int position, View convertView, ViewGroup parent) { 
  167.             int type = getItemViewType(position); 
  168.             XiaoMa xiaoMa = null
  169.             final int location = position; 
  170.             if(convertView == null){ 
  171.                 switch (type) { 
  172.                 //如果需要绘制选项时分支 
  173.                 case ITEM: 
  174.                     xiaoMa = new XiaoMa(); 
  175.                     convertView = inflater.inflate(R.layout.listview_items, null); 
  176.                     xiaoMa.iv = (ImageView)convertView.findViewById(R.id.ItemImage); 
  177.                     xiaoMa.tv = (TextView)convertView.findViewById(R.id.ItemTitle); 
  178.                     xiaoMa.text = (TextView)convertView.findViewById(R.id.itemtext); 
  179.                     xiaoMa.btn = (Button)convertView.findViewById(R.id.view_btn); 
  180.                     break
  181.                 //如果需要绘制换色选项时分支 
  182.                 case SEPARATOR: 
  183.                     xiaoMa = new XiaoMa(); 
  184.                     convertView = inflater.inflate(R.layout.listview_items, null); 
  185.                     xiaoMa.iv = (ImageView)convertView.findViewById(R.id.ItemImage); 
  186.                     xiaoMa.tv = (TextView)convertView.findViewById(R.id.ItemTitle); 
  187.                     xiaoMa.text = (TextView)convertView.findViewById(R.id.itemtext); 
  188.                     xiaoMa.btn = (Button)convertView.findViewById(R.id.view_btn); 
  189.                     convertView = inflater.inflate(R.layout.separator, null); 
  190.                     /* 
  191.                      * 这个地方的drawable2用法跟在ListView换色选项布局中的 
  192.                      * android:background="@drawable/gradient_box" 
  193.                      * 效果是一样的,小马写在这,熟悉下两种方式,大家根据自己需要改 
  194.                      */ 
  195.                     Drawable drawable2 = getResources().getDrawable(R.drawable.gradient_box); 
  196.                     xiaoMa.sep = (TextView)convertView.findViewById(R.id.sep); 
  197.                     xiaoMa.sep.setBackgroundDrawable(drawable2); 
  198.                     break
  199.             } 
  200.                 /*  
  201.                  * 此处小马犯错了,如果下面这句不加的话, 
  202.                  * 加载时正常,拖动列表时就会报空指针了, 
  203.                  * 小点注意下 
  204.                  */ 
  205.                 convertView.setTag(xiaoMa); 
  206.             }else
  207.                 xiaoMa = (XiaoMa)convertView.getTag(); 
  208.             } 
  209.             xiaoMa.iv.setBackgroundResource(R.drawable.xiaolvzi); 
  210.             xiaoMa.tv.setText("这是第"+(position+1)+"个标题"); 
  211.             xiaoMa.text.setText("这是第"+(position+1)+"个概述"); 
  212.             /** 
  213.              * 按钮事件监听实现 
  214.              */ 
  215.             xiaoMa.btn.setOnClickListener(new OnClickListener() { 
  216.                 @Override 
  217.                 public void onClick(View v) { 
  218.                     //单击Item按钮后,弹出提示 
  219.                     ShowDialog(location);    
  220.                 } 
  221.             }); 
  222.              
  223.             return convertView; 
  224.         } 
  225.          
  226.     } 
  227.      
  228.     /** 
  229.      * 弹出提示实现,这个地方扩展一下,细心的话大家会发现小马违反了方法命名规范,其实不是的, 
  230.      * 安卓Activity有临时弹出对话框方法的,跟下面这个方法只有一个字母之差(小马故意 
  231.      * 首字母大写的),安卓自带弹出方法在这个方法下面的注释中 
  232.      * @param posi 
  233.      */ 
  234.     private void ShowDialog(int posi){ 
  235.         Toast.makeText(getApplicationContext(), "单击了第"+(posi+1
  236.                 +"个按钮", Toast.LENGTH_SHORT).show(); 
  237.         /* 
  238.          * 下面这两个方法大家熟悉吧?调用系统提供的临时弹出对话框,必须实现下面的 
  239.          * onCreateDialog(int id)方法 
  240.          */ 
  241.         showDialog(1);//弹出时可以做如:从服务器取数据等操作 
  242.          
  243.         /** 
  244.          * 这个地方小马就简单的睡眠5秒种来模拟从服务器下载数据完成后关闭对话框 
  245.          */ 
  246.         new Thread(new Runnable() { 
  247.             @Override 
  248.             public void run() { 
  249.                 try { 
  250.                     Log.i("KKK""已进入睡眠"); 
  251.                     Thread.sleep(3000); 
  252.                     dismissDialog(1);//隐藏 表示数据下载完毕等的... 
  253.                 } catch (Exception e) { 
  254.                     e.printStackTrace(); 
  255.                 } 
  256.             } 
  257.         }).start(); 
  258.     } 
  259.      
  260.      
  261.     @Override 
  262.     protected Dialog onCreateDialog(int id) { 
  263.         /* 
  264.          * 下面这个构造器中的this不能用getApplicationContext()来代替, 
  265.          * 但可用类名.this来代替,没有为什么, 必须这样写!!!这个地方小马晕了 
  266.          * 不少时间,如果直接get....代码没错,但还是会报错,很邪门的哦 ... 
  267.          */ 
  268.         ProgressDialog dialog = new ProgressDialog(this); 
  269.         //小测试,中文就临时写这了,大家要注意把内容都写到string.xml中去,好习惯从小开始养,嘿嘿 
  270.         dialog.setCancelable(false);//设置用户不能用返回键取消对话框 
  271.         dialog.setIcon(getResources().getDrawable(R.drawable.xiaolvzi)); 
  272.         dialog.setTitle("那些年,我们一起追的女孩"); 
  273.         dialog.setMessage("小马果 呆丫头 O_O"); 
  274.         dialog.show(); 
  275.         return dialog; 
  276.     } 
  277.      
  278.      
  279.     /** 
  280.     * @Title: ListViewBackgroundDemoActivity.java 
  281.     * @Package com.xiaoma.listviewbackground 
  282.     * @Description: 为提高加载效率而写的类,可以看下ListView优化 
  283.     * @author XiaoMa 
  284.      */ 
  285.     public final class XiaoMa{ 
  286.         public  ImageView iv ; 
  287.         public TextView tv ;  
  288.         public Button btn ; 
  289.         public TextView text; 
  290.         public TextView sep; 
  291.     } 
  292.  
  293.     @Override 
  294.     public void onItemSelected(AdapterView<?> parent, View view, int position, 
  295.             long id) { 
  296.     } 
  297.     @Override 
  298.     public void onNothingSelected(AdapterView<?> parent) { 
  299.     } 

八:临时测试类代码如下(小儿科的东西,但还是注意下):

  1. package com.xiaoma.listviewbackground; 
  2.  
  3.  
  4. /**   
  5. * @Title: PercentTest.java 
  6. * @Package com.xiaoma.listviewbackground 
  7. * @Description: 测试取余规律,必须在JAVA工程下Run,别直接在这跑 
  8. * @author XiaoMa 
  9. */ 
  10. public class PercentTest { 
  11.  public static void main(String[] args) { 
  12.     int a = 15
  13.     int b = 9
  14.     System.out.println("9%15 = "+9%15); 
  15.     System.out.println("15%9 = "+15%9); 

九:看代码大家一定注意仔细看下小马注释部分,主布局代码如下:

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="fill_parent" 
  4.     android:layout_height="fill_parent" 
  5.     android:orientation="vertical" > 
  6.      
  7.    <!--  Back Up <ListView  
  8.         android:id="@+id/listview" 
  9.         android:layout_width="wrap_content" 
  10.         android:layout_height="fill_parent" 
  11.         android:smoothScrollbar="true" 
  12.         android:drawSelectorOnTop="false" 
  13.         android:listSelector="#00000000" 
  14.         /> 
  15.    --> 
  16.     
  17.     
  18.     <ListView  
  19.         android:id="@+id/listview" 
  20.         android:layout_width="fill_parent" 
  21.         android:layout_height="fill_parent" 
  22.         android:smoothScrollbar="true" 
  23.         android:choiceMode="none" 
  24.         android:focusable="false" android:scrollingCache="false" 
  25.         android:clickable="false" android:dividerHeight="0.5dip" 
  26.         /> 
  27.      
  28.    <!--   <ListView android:id="@+id/list_coupon"  
  29.         android:layout_height="wrap_content" 
  30.         android:drawSelectorOnTop="false" android:choiceMode="none" 
  31.         android:focusable="false" android:scrollingCache="false" 
  32.         android:fadingEdge="none" android:focusableInTouchMode="false" 
  33.         android:clickable="false" android:dividerHeight="0.5dip" 
  34.         android:divider="@drawable/separator" /> 
  35.     --> 
  36. </LinearLayout> 

      最后,还是跟往常一样,如果代码没详细看的,可以下载下此小DEMO源码,共同学习交流下,这个里面还是有很多地方可以改进的,只是写个思路,这里面问题还是蛮多的,如果觉得代码不清楚,有问题了还请大家多指点指点,小马在此先谢过啦,谢谢...加油!