AndroidUI效果--开源项目IndexableListView(字母索引)

来源:互联网 发布:淘宝开店怎么关闭店铺 编辑:程序博客网 时间:2024/06/06 09:08

AndroidUI效果--开源项目IndexableListView(字母索引)




开发通讯录相关的应用的时候可能会需要这种效果,索引这种效果根据人性化和美观,我下了一个关于字母索引的Demo,里面很好实现了这种效果,不过这只是个Demo,在实际的项目当中,可能会增加分组效果,我们可能在这个基础上进行扩展。

下面我把源代码贴一下,我下下来的项目是完全没有注释的,我稍微研究了一下代码,并加上了注释,希望对大伙有帮助。





布局

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent">  
  6.     <com.woozzu.android.widget.IndexableListView  
  7.         android:layout_width="fill_parent"   
  8.         android:layout_height="fill_parent"   
  9.         android:id="@+id/listview" />  
  10. </LinearLayout>  



Activity

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.woozzu.android.indexablelistview;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Collections;  
  5. import java.util.List;  
  6.   
  7. import android.app.Activity;  
  8. import android.content.Context;  
  9. import android.os.Bundle;  
  10. import android.widget.ArrayAdapter;  
  11. import android.widget.SectionIndexer;  
  12.   
  13. import com.woozzu.android.util.StringMatcher;  
  14. import com.woozzu.android.widget.IndexableListView;  
  15.   
  16. public class IndexableListViewActivity extends Activity {  
  17.     private ArrayList<String> mItems;  
  18.     private IndexableListView mListView;  
  19.   
  20.     /** Called when the activity is first created. */  
  21.     @Override  
  22.     public void onCreate(Bundle savedInstanceState) {  
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.main);  
  25.   
  26.         // 初始化一些数据  
  27.         mItems = new ArrayList<String>();  
  28.         mItems.add("Diary of a Wimpy Kid 6: Cabin Fever");  
  29.         mItems.add("Steve Jobs");  
  30.         mItems.add("Inheritance (The Inheritance Cycle)");  
  31.         mItems.add("11/22/63: A Novel");  
  32.         mItems.add("The Hunger Games");  
  33.         mItems.add("The LEGO Ideas Book");  
  34.         mItems.add("Explosive Eighteen: A Stephanie Plum Novel");  
  35.         mItems.add("Catching Fire (The Second Book of the Hunger Games)");  
  36.         mItems.add("Elder Scrolls V: Skyrim: Prima Official Game Guide");  
  37.         mItems.add("Death Comes to Pemberley");  
  38.         mItems.add("Diary of a Wimpy Kid 6: Cabin Fever");  
  39.         mItems.add("Steve Jobs");  
  40.         mItems.add("Inheritance (The Inheritance Cycle)");  
  41.         mItems.add("11/22/63: A Novel");  
  42.         mItems.add("The Hunger Games");  
  43.         mItems.add("The LEGO Ideas Book");  
  44.         mItems.add("Explosive Eighteen: A Stephanie Plum Novel");  
  45.         mItems.add("Catching Fire (The Second Book of the Hunger Games)");  
  46.         mItems.add("Elder Scrolls V: Skyrim: Prima Official Game Guide");  
  47.         mItems.add("做作");  
  48.         mItems.add("wokao");  
  49.         Collections.sort(mItems); // 排序  
  50.   
  51.         ContentAdapter adapter = new ContentAdapter(this,  
  52.                 android.R.layout.simple_list_item_1, mItems);  
  53.   
  54.         mListView = (IndexableListView) findViewById(R.id.listview);  
  55.         mListView.setAdapter(adapter);  
  56.         mListView.setFastScrollEnabled(true); // 设置快速滑动  
  57.     }  
  58.   
  59.     private class ContentAdapter extends ArrayAdapter<String> implements  
  60.             SectionIndexer {  
  61.   
  62.         private String mSections = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ";  
  63.   
  64.         public ContentAdapter(Context context, int textViewResourceId,  
  65.                 List<String> objects) {  
  66.             super(context, textViewResourceId, objects);  
  67.         }  
  68.   
  69.         @Override  
  70.         public int getPositionForSection(int section) {  
  71.             // If there is no item for current section, previous section will be  
  72.             // selected  
  73.             // 如果当前部分没有item,则之前的部分将被选择  
  74.             for (int i = section; i >= 0; i--) {  
  75.                 for (int j = 0; j < getCount(); j++) {  
  76.                     System.out.println(getCount());  
  77.                     if (i == 0) { // #  
  78.                         // For numeric section 数字  
  79.                         for (int k = 0; k <= 9; k++) {// 1...9  
  80.                             // 字符串第一个字符与1~9之间的数字进行匹配  
  81.                             if (StringMatcher.match(  
  82.                                     String.valueOf(getItem(j).charAt(0)),  
  83.                                     String.valueOf(k)))  
  84.                                 return j;  
  85.                         }  
  86.                     } else { // A~Z  
  87.                         if (StringMatcher.match(  
  88.                                 String.valueOf(getItem(j).charAt(0)),  
  89.                                 String.valueOf(mSections.charAt(i))))  
  90.                             return j;  
  91.                     }  
  92.                 }  
  93.             }  
  94.             return 0;  
  95.         }  
  96.   
  97.         @Override  
  98.         public int getSectionForPosition(int position) {  
  99.             return 0;  
  100.         }  
  101.   
  102.         @Override  
  103.         public Object[] getSections() {  
  104.             String[] sections = new String[mSections.length()];  
  105.             for (int i = 0; i < mSections.length(); i++)  
  106.                 sections[i] = String.valueOf(mSections.charAt(i));  
  107.             return sections;  
  108.         }  
  109.     }  
  110. }  


字符串匹配工具类

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * Copyright 2011 woozzu 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *     http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.wwj.indexableListView.util;  
  18.   
  19. public class StringMatcher {  
  20.   
  21.     // 这些变量是韩文,小巫也不知道是什么意思,有谁懂的马上联系我啊  
  22.     private final static char KOREAN_UNICODE_START = '가'// 韩文字符编码开始?    
  23.     private final static char KOREAN_UNICODE_END = '힣';   // 韩文字符编码结束?  
  24.     private final static char KOREAN_UNIT = '까' - '가';    // 不知道是啥?  
  25.     // 韩文的一些字符初始化  
  26.     private final static char[] KOREAN_INITIAL = { 'ㄱ''ㄲ''ㄴ''ㄷ''ㄸ',  
  27.             'ㄹ''ㅁ''ㅂ''ㅃ''ㅅ''ㅆ''ㅇ''ㅈ''ㅉ''ㅊ''ㅋ''ㅌ''ㅍ',  
  28.             'ㅎ' };  
  29.   
  30.       
  31.     /** 
  32.      * 字符匹配 
  33.      * @param value 需要keyword匹配的字符串 
  34.      * @param keyword #ABCDEFGHIJKLMNOPQRSTUVWXYZ中的一个 
  35.      * @return 
  36.      */  
  37.     public static boolean match(String value, String keyword) {  
  38.         if (value == null || keyword == null)  
  39.             return false;  
  40.         if (keyword.length() > value.length())  
  41.             return false;  
  42.   
  43.         int i = 0, j = 0;  
  44.         do {  
  45.             // 如果是韩文字符并且在韩文初始数组里面  
  46.             if (isKorean(value.charAt(i)) && isInitialSound(keyword.charAt(j))) {  
  47.                 if (keyword.charAt(j) == getInitialSound(value.charAt(i))) {  
  48.                     i++;  
  49.                     j++;  
  50.                 } else if (j > 0)  
  51.                     break;  
  52.                 else  
  53.                     i++;  
  54.             } else {  
  55.                 // 逐个字符匹配  
  56.                 if (keyword.charAt(j) == value.charAt(i)) {  
  57.                     i++;  
  58.                     j++;  
  59.                 } else if (j > 0)  
  60.                     break;  
  61.                 else  
  62.                     i++;  
  63.             }  
  64.         } while (i < value.length() && j < keyword.length());  
  65.         // 如果最后j等于keyword的长度说明匹配成功  
  66.         return (j == keyword.length()) ? true : false;  
  67.     }  
  68.   
  69.     // 判断字符是否在韩文字符编码范围内  
  70.     private static boolean isKorean(char c) {  
  71.         if (c >= KOREAN_UNICODE_START && c <= KOREAN_UNICODE_END)  
  72.             return true;  
  73.         return false;  
  74.     }  
  75.   
  76.     // 判断是否在韩文字符里面  
  77.     private static boolean isInitialSound(char c) {  
  78.         for (char i : KOREAN_INITIAL) {  
  79.             if (c == i)  
  80.                 return true;  
  81.         }  
  82.         return false;  
  83.     }  
  84.   
  85.     // 获得韩文初始化字符数组里面的一个字符  
  86.     private static char getInitialSound(char c) {  
  87.         return KOREAN_INITIAL[(c - KOREAN_UNICODE_START) / KOREAN_UNIT];  
  88.     }  
  89. }  



自定义索引列表


[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * Copyright 2011 woozzu 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *     http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.wwj.indexableListView.widget;  
  18.   
  19. import android.content.Context;  
  20. import android.graphics.Canvas;  
  21. import android.util.AttributeSet;  
  22. import android.view.GestureDetector;  
  23. import android.view.MotionEvent;  
  24. import android.widget.ListAdapter;  
  25. import android.widget.ListView;  
  26.   
  27. /** 
  28.  * 自定义索引列表 
  29.  *  
  30.  * @author by 佚名 
  31.  *  
  32.  */  
  33. public class IndexableListView extends ListView {  
  34.   
  35.     private boolean mIsFastScrollEnabled = false;  
  36.     private IndexScroller mScroller = null;  
  37.     private GestureDetector mGestureDetector = null;  
  38.   
  39.     public IndexableListView(Context context) {  
  40.         super(context);  
  41.     }  
  42.   
  43.     public IndexableListView(Context context, AttributeSet attrs) {  
  44.         super(context, attrs);  
  45.     }  
  46.   
  47.     public IndexableListView(Context context, AttributeSet attrs, int defStyle) {  
  48.         super(context, attrs, defStyle);  
  49.     }  
  50.   
  51.     @Override  
  52.     public boolean isFastScrollEnabled() {  
  53.         return mIsFastScrollEnabled;  
  54.     }  
  55.   
  56.     @Override  
  57.     public void setFastScrollEnabled(boolean enabled) {  
  58.         mIsFastScrollEnabled = enabled;  
  59.         if (mIsFastScrollEnabled) {  
  60.             if (mScroller == null)  
  61.                 mScroller = new IndexScroller(getContext(), this);  
  62.         } else {  
  63.             if (mScroller != null) {  
  64.                 mScroller.hide();  
  65.                 mScroller = null;  
  66.             }  
  67.         }  
  68.     }  
  69.   
  70.     @Override  
  71.     public void draw(Canvas canvas) {  
  72.         super.draw(canvas);  
  73.   
  74.         // Overlay index bar  
  75.         if (mScroller != null)  
  76.             mScroller.draw(canvas);  
  77.     }  
  78.   
  79.     @Override  
  80.     public boolean onTouchEvent(MotionEvent ev) {  
  81.         // Intercept ListView's touch event  
  82.         if (mScroller != null && mScroller.onTouchEvent(ev))  
  83.             return true;  
  84.   
  85.         if (mGestureDetector == null) {  
  86.             // 创建一个GestureDetector(手势探测器)  
  87.             mGestureDetector = new GestureDetector(getContext(),  
  88.                     new GestureDetector.SimpleOnGestureListener() {  
  89.   
  90.                         @Override  
  91.                         public boolean onFling(MotionEvent e1, MotionEvent e2,  
  92.                                 float velocityX, float velocityY) {  
  93.                             // If fling happens, index bar shows  
  94.                             // 显示索引条  
  95.                             mScroller.show();  
  96.                             return super.onFling(e1, e2, velocityX, velocityY);  
  97.                         }  
  98.   
  99.                     });  
  100.         }  
  101.         mGestureDetector.onTouchEvent(ev);  
  102.   
  103.         return super.onTouchEvent(ev);  
  104.     }  
  105.   
  106.     @Override  
  107.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  108.         return true;  
  109.     }  
  110.   
  111.     @Override  
  112.     public void setAdapter(ListAdapter adapter) {  
  113.         super.setAdapter(adapter);  
  114.         if (mScroller != null)  
  115.             mScroller.setAdapter(adapter);  
  116.     }  
  117.   
  118.     @Override  
  119.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  120.         super.onSizeChanged(w, h, oldw, oldh);  
  121.         if (mScroller != null)  
  122.             mScroller.onSizeChanged(w, h, oldw, oldh);  
  123.     }  
  124.   
  125. }  


索引条

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * Copyright 2011 woozzu 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *     http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.wwj.indexableListView.widget;  
  18.   
  19. import android.content.Context;  
  20. import android.graphics.Canvas;  
  21. import android.graphics.Color;  
  22. import android.graphics.Paint;  
  23. import android.graphics.RectF;  
  24. import android.os.Handler;  
  25. import android.os.Message;  
  26. import android.os.SystemClock;  
  27. import android.view.MotionEvent;  
  28. import android.widget.Adapter;  
  29. import android.widget.ListView;  
  30. import android.widget.SectionIndexer;  
  31.   
  32. /** 
  33.  * 右侧的索引条 
  34.  *  
  35.  * @author by 佚名 
  36.  *  
  37.  */  
  38. public class IndexScroller {  
  39.   
  40.     private float mIndexbarWidth; // 索引条宽度  
  41.     private float mIndexbarMargin; // 索引条外边距  
  42.     private float mPreviewPadding; //  
  43.     private float mDensity; // 密度  
  44.     private float mScaledDensity; // 缩放密度  
  45.     private float mAlphaRate; // 透明度  
  46.     private int mState = STATE_HIDDEN; // 状态  
  47.     private int mListViewWidth; // ListView宽度  
  48.     private int mListViewHeight; // ListView高度  
  49.     private int mCurrentSection = -1// 当前部分  
  50.     private boolean mIsIndexing = false// 是否正在索引  
  51.     private ListView mListView = null;  
  52.     private SectionIndexer mIndexer = null;  
  53.     private String[] mSections = null;  
  54.     private RectF mIndexbarRect;  
  55.   
  56.     // 4种状态(已隐藏、正在显示、已显示、正在隐藏)  
  57.     private static final int STATE_HIDDEN = 0;  
  58.     private static final int STATE_SHOWING = 1;  
  59.     private static final int STATE_SHOWN = 2;  
  60.     private static final int STATE_HIDING = 3;  
  61.   
  62.     public IndexScroller(Context context, ListView lv) {  
  63.         mDensity = context.getResources().getDisplayMetrics().density;  
  64.         mScaledDensity = context.getResources().getDisplayMetrics().scaledDensity;  
  65.         mListView = lv;  
  66.         setAdapter(mListView.getAdapter());  
  67.   
  68.         mIndexbarWidth = 20 * mDensity; // 索引条宽度  
  69.         mIndexbarMargin = 10 * mDensity;// 索引条间距  
  70.         mPreviewPadding = 5 * mDensity; // 内边距  
  71.     }  
  72.   
  73.     public void draw(Canvas canvas) {  
  74.         if (mState == STATE_HIDDEN)  
  75.             return;  
  76.   
  77.         // mAlphaRate determines the rate of opacity  
  78.         Paint indexbarPaint = new Paint();  
  79.         indexbarPaint.setColor(Color.BLACK);  
  80.         indexbarPaint.setAlpha((int) (64 * mAlphaRate));  
  81.         indexbarPaint.setAntiAlias(true);  
  82.         // 画右侧字母索引的圆矩形  
  83.         canvas.drawRoundRect(mIndexbarRect, 5 * mDensity, 5 * mDensity,  
  84.                 indexbarPaint);  
  85.   
  86.         if (mSections != null && mSections.length > 0) {  
  87.             // Preview is shown when mCurrentSection is set  
  88.             if (mCurrentSection >= 0) {  
  89.                 Paint previewPaint = new Paint(); // 用来绘画所以条背景的画笔  
  90.                 previewPaint.setColor(Color.BLACK);// 设置画笔颜色为黑色  
  91.                 previewPaint.setAlpha(96); // 设置透明度  
  92.                 previewPaint.setAntiAlias(true);// 设置抗锯齿  
  93.                 previewPaint.setShadowLayer(300, Color.argb(64000)); // 设置阴影层  
  94.   
  95.                 Paint previewTextPaint = new Paint(); // 用来绘画索引字母的画笔  
  96.                 previewTextPaint.setColor(Color.WHITE); // 设置画笔为白色  
  97.                 previewTextPaint.setAntiAlias(true); // 设置抗锯齿  
  98.                 previewTextPaint.setTextSize(50 * mScaledDensity); // 设置字体大小  
  99.   
  100.                 // 文本的宽度  
  101.                 float previewTextWidth = previewTextPaint  
  102.                         .measureText(mSections[mCurrentSection]);  
  103.   
  104.                 float previewSize = 2 * mPreviewPadding  
  105.                         + previewTextPaint.descent()  
  106.                         - previewTextPaint.ascent();  
  107.                 RectF previewRect = new RectF(  
  108.                         (mListViewWidth - previewSize) / 2,  
  109.                         (mListViewHeight - previewSize) / 2,  
  110.                         (mListViewWidth - previewSize) / 2 + previewSize,  
  111.                         (mListViewHeight - previewSize) / 2 + previewSize);  
  112.   
  113.                 // 中间索引的那个框  
  114.                 canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity,  
  115.                         previewPaint);  
  116.                 // 绘画索引字母  
  117.                 canvas.drawText(  
  118.                         mSections[mCurrentSection],  
  119.                         previewRect.left + (previewSize - previewTextWidth) / 2  
  120.                                 - 1,  
  121.                         previewRect.top + mPreviewPadding  
  122.                                 - previewTextPaint.ascent() + 1,  
  123.                         previewTextPaint);  
  124.             }  
  125.   
  126.             // 绘画右侧索引条的字母  
  127.             Paint indexPaint = new Paint();  
  128.             indexPaint.setColor(Color.WHITE);  
  129.             indexPaint.setAlpha((int) (255 * mAlphaRate));  
  130.             indexPaint.setAntiAlias(true);  
  131.             indexPaint.setTextSize(12 * mScaledDensity);  
  132.   
  133.             float sectionHeight = (mIndexbarRect.height() - 2 * mIndexbarMargin)  
  134.                     / mSections.length;  
  135.             float paddingTop = (sectionHeight - (indexPaint.descent() - indexPaint  
  136.                     .ascent())) / 2;  
  137.             for (int i = 0; i < mSections.length; i++) {  
  138.                 float paddingLeft = (mIndexbarWidth - indexPaint  
  139.                         .measureText(mSections[i])) / 2;  
  140.                 canvas.drawText(mSections[i], mIndexbarRect.left + paddingLeft,  
  141.                         mIndexbarRect.top + mIndexbarMargin + sectionHeight * i  
  142.                                 + paddingTop - indexPaint.ascent(), indexPaint);  
  143.             }  
  144.         }  
  145.     }  
  146.   
  147.     public boolean onTouchEvent(MotionEvent ev) {  
  148.         switch (ev.getAction()) {  
  149.         case MotionEvent.ACTION_DOWN: // 按下,开始索引  
  150.             // If down event occurs inside index bar region, start indexing  
  151.             if (mState != STATE_HIDDEN && contains(ev.getX(), ev.getY())) {  
  152.                 setState(STATE_SHOWN);  
  153.   
  154.                 // It demonstrates that the motion event started from index bar  
  155.                 mIsIndexing = true;  
  156.                 // Determine which section the point is in, and move the list to  
  157.                 // that section  
  158.                 mCurrentSection = getSectionByPoint(ev.getY());  
  159.                 mListView.setSelection(mIndexer  
  160.                         .getPositionForSection(mCurrentSection));  
  161.                 return true;  
  162.             }  
  163.             break;  
  164.         case MotionEvent.ACTION_MOVE: // 移动  
  165.             if (mIsIndexing) {  
  166.                 // If this event moves inside index bar  
  167.                 if (contains(ev.getX(), ev.getY())) {  
  168.                     // Determine which section the point is in, and move the  
  169.                     // list to that section  
  170.                     mCurrentSection = getSectionByPoint(ev.getY());  
  171.                     mListView.setSelection(mIndexer  
  172.                             .getPositionForSection(mCurrentSection));  
  173.                 }  
  174.                 return true;  
  175.             }  
  176.             break;  
  177.         case MotionEvent.ACTION_UP: // 抬起  
  178.             if (mIsIndexing) {  
  179.                 mIsIndexing = false;  
  180.                 mCurrentSection = -1;  
  181.             }  
  182.             if (mState == STATE_SHOWN)  
  183.                 setState(STATE_HIDING);  
  184.             break;  
  185.         }  
  186.         return false;  
  187.     }  
  188.   
  189.     public void onSizeChanged(int w, int h, int oldw, int oldh) {  
  190.         mListViewWidth = w;  
  191.         mListViewHeight = h;  
  192.         mIndexbarRect = new RectF(w - mIndexbarMargin - mIndexbarWidth,  
  193.                 mIndexbarMargin, w - mIndexbarMargin, h - mIndexbarMargin);  
  194.     }  
  195.   
  196.     // 显示  
  197.     public void show() {  
  198.         if (mState == STATE_HIDDEN)  
  199.             setState(STATE_SHOWING);  
  200.         else if (mState == STATE_HIDING)  
  201.             setState(STATE_HIDING);  
  202.     }  
  203.   
  204.     // 隐藏  
  205.     public void hide() {  
  206.         if (mState == STATE_SHOWN)  
  207.             setState(STATE_HIDING);  
  208.     }  
  209.   
  210.     public void setAdapter(Adapter adapter) {  
  211.         if (adapter instanceof SectionIndexer) {  
  212.             mIndexer = (SectionIndexer) adapter;  
  213.             mSections = (String[]) mIndexer.getSections();  
  214.         }  
  215.     }  
  216.   
  217.     // 设置状态  
  218.     private void setState(int state) {  
  219.         if (state < STATE_HIDDEN || state > STATE_HIDING)  
  220.             return;  
  221.   
  222.         mState = state;  
  223.         switch (mState) {  
  224.         case STATE_HIDDEN:  
  225.             // Cancel any fade effect  
  226.             // 取消渐退的效果  
  227.             mHandler.removeMessages(0);  
  228.             break;  
  229.         case STATE_SHOWING:  
  230.             // Start to fade in  
  231.             // 开始渐进效果  
  232.             mAlphaRate = 0;  
  233.             fade(0);  
  234.             break;  
  235.         case STATE_SHOWN:  
  236.             // Cancel any fade effect  
  237.             // 取消渐退的效果  
  238.             mHandler.removeMessages(0);  
  239.             break;  
  240.         case STATE_HIDING:  
  241.             // Start to fade out after three seconds  
  242.             // 隐藏3秒钟  
  243.             mAlphaRate = 1;  
  244.             fade(3000);  
  245.             break;  
  246.         }  
  247.     }  
  248.   
  249.     private boolean contains(float x, float y) {  
  250.         // Determine if the point is in index bar region, which includes the  
  251.         // right margin of the bar  
  252.         return (x >= mIndexbarRect.left && y >= mIndexbarRect.top && y <= mIndexbarRect.top  
  253.                 + mIndexbarRect.height());  
  254.     }  
  255.   
  256.     private int getSectionByPoint(float y) {  
  257.         if (mSections == null || mSections.length == 0)  
  258.             return 0;  
  259.         if (y < mIndexbarRect.top + mIndexbarMargin)  
  260.             return 0;  
  261.         if (y >= mIndexbarRect.top + mIndexbarRect.height() - mIndexbarMargin)  
  262.             return mSections.length - 1;  
  263.         return (int) ((y - mIndexbarRect.top - mIndexbarMargin) / ((mIndexbarRect  
  264.                 .height() - 2 * mIndexbarMargin) / mSections.length));  
  265.     }  
  266.   
  267.     private void fade(long delay) {  
  268.         mHandler.removeMessages(0);  
  269.         mHandler.sendEmptyMessageAtTime(0, SystemClock.uptimeMillis() + delay);  
  270.     }  
  271.   
  272.     private Handler mHandler = new Handler() {  
  273.   
  274.         @Override  
  275.         public void handleMessage(Message msg) {  
  276.             super.handleMessage(msg);  
  277.   
  278.             switch (mState) {  
  279.             case STATE_SHOWING:  
  280.                 // Fade in effect  
  281.                 // 淡进效果  
  282.                 mAlphaRate += (1 - mAlphaRate) * 0.2;  
  283.                 if (mAlphaRate > 0.9) {  
  284.                     mAlphaRate = 1;  
  285.                     setState(STATE_SHOWN);  
  286.                 }  
  287.   
  288.                 mListView.invalidate();  
  289.                 fade(10);  
  290.                 break;  
  291.             case STATE_SHOWN:  
  292.                 // If no action, hide automatically  
  293.                 setState(STATE_HIDING);  
  294.                 break;  
  295.             case STATE_HIDING:  
  296.                 // Fade out effect  
  297.                 // 淡出效果  
  298.                 mAlphaRate -= mAlphaRate * 0.2;  
  299.                 if (mAlphaRate < 0.1) {  
  300.                     mAlphaRate = 0;  
  301.                     setState(STATE_HIDDEN);  
  302.                 }  
  303.   
  304.                 mListView.invalidate();  
  305.                 fade(10);  
  306.                 break;  
  307.             }  
  308.         }  
  309.   
  310.     };  
  311. }  
0 0
原创粉丝点击