效果图:

这样写Layout:

  1. <?
  2.  
  3. xml version="1.0" encoding="utf-8"?
  4.  
  5. >
  6. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  7. xmlns:rcm="http://schemas.android.com/apk/res/com.ringcentral.android"
  8. android:id="@+id/contact_list_view"
  9. android:layout_width="match_parent"
  10. android:layout_height="match_parent"
  11. android:background="@color/bgColorMain"
  12. android:orientation="vertical" >
  13.  
  14. <FrameLayout
  15. android:layout_width="match_parent"
  16. android:layout_height="match_parent" >
  17.  
  18. <ListView
  19. android:id="@android:id/list"
  20. android:layout_width="match_parent"
  21. android:layout_height="match_parent"
  22. android:cacheColorHint="@android:color/transparent"
  23. android:divider="@null"
  24. android:listSelector="@drawable/bg_list_item_selector" />
  25.  
  26. <com.example.view.<strong>SectionIndexerView //这个是右边的导航</strong>
  27. android:id="@+id/section_indexer_view"
  28. android:layout_width="70dip"
  29. android:layout_height="fill_parent"
  30. android:layout_gravity="right"
  31. android:layout_marginBottom="4dip"
  32. android:layout_marginRight="6dip"
  33. android:layout_marginTop="4dip"
  34. android:textSize="12.0sp" />
  35.  
  36. <<strong>TextView //这个是中间的字母提示</strong>
  37. android:id="@+id/section_text"
  38. android:layout_width="wrap_content"
  39. android:layout_height="wrap_content"
  40. android:layout_gravity="center"
  41. android:background="@drawable/section_text_bg"
  42. android:gravity="center"
  43. android:textColor="#FFFFFF"
  44. android:textSize="40sp"
  45. android:visibility="gone" />
  46. </FrameLayout>
  47.  
  48. <RelativeLayout
  49. android:id="@+id/no_contact_indication"
  50. android:layout_width="match_parent"
  51. android:layout_height="match_parent" >
  52.  
  53. <TextView
  54. android:id="@+id/emptyListText"
  55. android:layout_width="wrap_content"
  56. android:layout_height="wrap_content"
  57. android:layout_centerInParent="true"
  58. android:singleLine="true"
  59. android:text="No Contacts"
  60. android:textColor="@color/text_no_items"
  61. android:textSize="20sp" />
  62.  
  63. <ProgressBar
  64. android:id="@+id/loading"
  65. style="@style/RCMProgressBar"
  66. android:layout_width="wrap_content"
  67. android:layout_height="wrap_content"
  68. android:layout_centerInParent="true"
  69. android:visibility="gone" />
  70. </RelativeLayout>
  71.  
  72. </LinearLayout>

关于SectionIndexerView  的写法:

  1. public class SectionIndexerView extends View{
  2.  
  3. public static final String TAG = SectionIndexerView.class.getSimpleName();
  4. private static final boolean DEBUG = true;
  5. /** 写文字的画笔 */
  6. private Paint mTextPaint;
  7. /** 指定view的宽度 */
  8. private int mViewWidth = 0;
  9. /** 指定view的高度 */
  10. private int mViewHeight = 0;
  11. /** 每一个文字的高度 */
  12. private float mPerTextHeight;
  13. /** 是否是按下状态 */
  14. private boolean mIsPressed = false;
  15. /** 关联的listview */
  16. private ListView mListview = null;
  17. /** 关联的indexer */
  18. private SectionIndexer mIndexer;
  19. /** 关联的textview */
  20. private TextView mView = null;
  21. /** 依照A-Z排序的section */
  22. private String[] mSectionIndexerText = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
  23. "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z","#" };
  24. private static final float TEXTSIZE_RATIO = 0.84f;
  25. /** 默认的字体大小常量 */
  26. private static final int CHAR_WIDTH = 12;
  27. /** 背景的透明度 */
  28. private static final int BG_ALPHA = 153;
  29. /** 背景的圆角弧度 */
  30. private static final float BG_RADIAN = 20f;
  31. /** 默认的字体大小 */
  32. private int mCharwidth = CHAR_WIDTH;
  33. /** Context */
  34. private Context mContext = null;
  35.  
  36. /**
  37. * 构造函数
  38. *
  39. * @param context
  40. * Context
  41. */
  42. public SectionIndexerView(Context context) {
  43. super(context);
  44. init(context);
  45. }
  46.  
  47. /**
  48. * 构造函数
  49. *
  50. * @param context
  51. * Context
  52. * @param attributeSet
  53. * AttributeSet
  54. */
  55. public SectionIndexerView(Context context, AttributeSet attributeSet) {
  56. super(context, attributeSet);
  57. init(context);
  58. }
  59.  
  60. /**
  61. * 初始化基本信息
  62. *
  63. * @param context
  64. * Context
  65. */
  66. private void init(Context context) {
  67. mContext = context;
  68. mCharwidth = (int) (mCharwidth * mContext.getResources().getDisplayMetrics().density);
  69. this.mTextPaint = new Paint();
  70. this.mTextPaint.setAntiAlias(true);
  71. this.mTextPaint.setColor(-1);
  72. }
  73.  
  74. /**
  75. * 初始化SectionIndexer,指定listview,indexer及显示section的textview
  76. *
  77. * @param listview
  78. * 关联的listview
  79. * @param indexer
  80. * 关联的SectionIndexer
  81. * @param view
  82. * 关联的TextView
  83. */
  84. public void init(ListView listview, SectionIndexer indexer, TextView view) {
  85. this.mListview = listview;
  86. this.mIndexer = indexer;
  87. this.mView = view;
  88. }
  89.  
  90. @Override
  91. protected void onDraw(Canvas paramCanvas) {
  92. Paint localPaint = new Paint();
  93. localPaint.setAntiAlias(true);
  94. this.mTextPaint.setColor(Color.parseColor("#75797d"));
  95. if (this.mIsPressed) {
  96. localPaint.setColor(Color.parseColor("#838a98"));
  97. localPaint.setAlpha(BG_ALPHA);
  98. } else {
  99. localPaint.setAlpha(0);
  100. }
  101.  
  102. this.mTextPaint.setTextSize(this.mViewHeight * TEXTSIZE_RATIO / mSectionIndexerText.length);
  103. System.out.println("==textSize="+(this.mViewHeight * TEXTSIZE_RATIO / mSectionIndexerText.length));
  104. System.out.println("====mViewWidth="+mViewWidth+"mCharWidth="+mCharwidth);
  105. //paramCanvas.drawRoundRect是画背景,BG_RADIAN为弯曲的弧度
  106. paramCanvas.drawRoundRect(new RectF(50, 0.0F, this.mViewWidth,
  107. this.mViewHeight), BG_RADIAN, BG_RADIAN,
  108. localPaint);
  109.  
  110. //这个textPointX为
  111. int textPointX = 140;
  112.  
  113. //textPointY为写text的Y的位置
  114. float textPointY = (this.mPerTextHeight - this.mTextPaint.ascent()) / 2.0F;
  115.  
  116. int sectionslength = this.mSectionIndexerText.length;
  117. int currentSection = 0;
  118. int currentHeight = 0;
  119. while (true) {
  120. if (currentSection >= sectionslength) {
  121. break;
  122. }
  123.  
  124. //(mCharwidth - (int) this.mTextPaint.measureText(this.mSectionIndexerText[currentSection])) / 2
  125. //这样写的原因是使每一个字母居中对齐
  126. paramCanvas.drawText(
  127. this.mSectionIndexerText[currentSection],
  128. textPointX
  129. + (mCharwidth - (int) this.mTextPaint
  130. .measureText(this.mSectionIndexerText[currentSection])) / 2,
  131. textPointY + (3.0F + currentHeight * this.mPerTextHeight), this.mTextPaint);// SUPPRESS CHECKSTYLE : magic number
  132. ++currentHeight;
  133. ++currentSection;
  134. }
  135.  
  136. }
  137.  
  138. @Override
  139. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  140. int width = View.MeasureSpec.getSize(widthMeasureSpec);
  141. this.mViewWidth = width;
  142.  
  143. int height = View.MeasureSpec.getSize(heightMeasureSpec);
  144. this.mViewHeight = height;
  145. setMeasuredDimension(this.mViewWidth, this.mViewHeight);
  146. this.mPerTextHeight = (this.mViewHeight / this.mSectionIndexerText.length);
  147. }
  148.  
  149. @Override
  150. public boolean onTouchEvent(MotionEvent motionEvent) {
  151. boolean returnvalue = false;
  152. switch (motionEvent.getAction()) {
  153. case MotionEvent.ACTION_DOWN:
  154. if (DEBUG) {
  155. Log.d(TAG, "action down!");
  156. }
  157. mListview.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
  158. SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0));
  159. returnvalue = processTouchEvent(motionEvent);
  160. break;
  161. case MotionEvent.ACTION_MOVE:
  162. if (DEBUG) {
  163. Log.d(TAG, "action move!");
  164. }
  165. returnvalue = processTouchEvent(motionEvent);
  166. break;
  167. case MotionEvent.ACTION_UP:
  168. case MotionEvent.ACTION_CANCEL:
  169. if (DEBUG) {
  170. Log.d(TAG, "action up!");
  171. }
  172. setPressed(false);
  173. mView.setText("");
  174. mView.setVisibility(View.GONE);
  175. returnvalue = true;
  176.  
  177. break;
  178. default:
  179. break;
  180. }
  181. invalidate();
  182. return returnvalue;
  183. }
  184.  
  185. /**
  186. * 处理onTouch事件
  187. *
  188. * @param motionEvent
  189. * MotionEvent
  190. * @return true 处理了触摸事件。false没有处理
  191. */
  192. private boolean processTouchEvent(MotionEvent motionEvent) {
  193. String selcected = "";
  194.  
  195. int backgroundPointX = this.mViewWidth - getPaddingRight() - mCharwidth * 3// SUPPRESS CHECKSTYLE
  196. - getPaddingLeft();
  197. if (motionEvent.getX() < backgroundPointX) {
  198. mView.setVisibility(View.GONE);
  199. setPressed(false);
  200. return false;
  201. }
  202. setPressed(true);
  203. int curruntSection = (int) (motionEvent.getY() / this.mPerTextHeight);
  204.  
  205. if (curruntSection >= 0 && curruntSection <= mSectionIndexerText.length - 1) {
  206. selcected = mSectionIndexerText[curruntSection];
  207. mView.setVisibility(View.VISIBLE);
  208. } else {
  209. if (curruntSection < 0) {
  210. selcected = mSectionIndexerText[0];
  211. } else if (curruntSection > mSectionIndexerText.length) {
  212. selcected = mSectionIndexerText[mSectionIndexerText.length - 1];
  213. }
  214. mView.setVisibility(View.GONE);
  215. }
  216. boolean foundedPosition = false;
  217. for (int i = 0; i < mIndexer.getSections().length; i++) {
  218. SectionTitle title = (SectionTitle)mIndexer.getSections()[i];
  219. if (selcected.equals(title.title)) {
  220. mListview.setSelection(mIndexer.getPositionForSection(i));
  221. foundedPosition = true;
  222. break;
  223. }
  224. }
  225.  
  226. if (foundedPosition) {
  227. mView.setBackgroundResource(R.drawable.section_text_bg);
  228. mView.setText(selcected);
  229. } else {
  230. mView.setBackgroundResource(R.drawable.section_text_gray_bg);
  231. mView.setText(selcected);
  232. }
  233. return true;
  234. }
  235. @Override
  236. public void setPressed(boolean pressed) {
  237. this.mIsPressed = pressed;
  238. }
  239.  
  240. }

这样来初始化:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. setContentView(R.layout.contacts_list_content);
  5. mEmtytext = (TextView) findViewById(R.id.emptyListText);
  6. mLoadingBar = (ProgressBar) findViewById(R.id.loading);
  7.  
  8. mQueryHandler = new MyHandler(this);
  9. mAdapter = new ContactsAdapter(this);
  10.  
  11. mSectionIndexer = (SectionIndexerView)findViewById(R.id.section_indexer_view);
  12. TextView textView = (TextView)findViewById(R.id.section_text);
  13.  
  14. getListView().setOnScrollListener(mAdapter);
  15. setListAdapter(mAdapter);
  16. <strong>mSectionIndexer.init(getListView(), mAdapter, textView);</strong>
  17. startQuery();
  18. }

代码:http://download.csdn.net/detail/baidu_nod/7810525

假设给Contact的List加一个用字母排序的导航的更多相关文章

  1. WordPress制作一个首字母排序的标签页面

    很早就想制作这样一个页面了,废话不多说, 先看看效果:传送门 在网上找了很多的代码,试了很久,修改了一些代码,最终就达到了现在的效果. 实现方法:(里面增加了缓存功能,打开页面更快,对数据进行了缓存, ...

  2. C++在字符串前加一个L作用:

    在字符串前加一个L作用:    如 L"我的字符串" 表示将ANSI字符串转换成unicode的字符串,就是每个字符占用两个字节.    strlen("asd" ...

  3. oracle 中的trunc()函数及加一个月,一天,一小时,一分钟,一秒钟方法

    返回处理后的数据,不同于round()(对数值进行四舍五入处理),该函数不对指定小数前或后的数值部分进行舍入处理. 语法:trunc(number[,decimals]) 其中,number为待做处理 ...

  4. iOS圆形图片裁剪,以及原型图片外面加一个圆环

    废话不多说,直接上代码 #import "ViewController.h" @interface ViewController () @property (nonatomic,s ...

  5. 如何给div加一个边框border样式

    如何给div加一个边框样式? 对div盒子加一个边框样式很简单只需要使用border板块样式即可. 一.虚线与实线边框 边框虚线样式:dashed 边框实现样式:solid border:1px da ...

  6. sh里没有多行注释,只能每一行加一个#号

    sh里没有多行注释,只能每一行加一个#号.只能像这样: #-------------------------------------------- # 这是一个自动打ipa的脚本,基于webfrogs ...

  7. express4.0之后不会解析req.files,必须加一个插件multer

    express 4 + 用multer express4.0之后不会解析req.files,必须加一个插件multer http://www.w3school.com.cn/tags/att_form ...

  8. iOS 给UITextView加一个placeholder

    苹果并没有为UITextView提供placeholder功能.我们可以通过两种办法实现. 方法一: 思路:设置默认显示的文字,颜色设置为灰色.代理方法监听textView点击. 缺点:如果点击到文字 ...

  9. [UE4]快速移动,给单位向量加一个力

    一.(Vector_End- Vector_Start ).Normalize,获取从起始位置指向目标位置的单位向量. 二.给单位向量乘以一个浮点数,即给向量加一个力,是往向量方向移动 每一帧往目标点 ...

随机推荐

  1. 回归 WordPress

    一直很喜欢用WordPress,使用方便,模板容易定制,国内建站可选择的虚拟主机多.自从WordPress升级后,官方网站打不开,从 GitHub 安装 WordPress 后无法浏览在线的主题.一切 ...

  2. ubuntu远程windows服务器

    ubuntu端: sudo apt-get install rdesktop windows端: 需要允许此windows远程访问.我的windows是windows server2012,基本操作: ...

  3. javascript学习笔记(2)

    <html> <head><title>Throwing die</title><script>    var canv_width  = ...

  4. 《转》精巧好用的DelayQueue

    该文章转自:http://www.cnblogs.com/jobs/archive/2007/04/27/730255.html 我们谈一下实际的场景吧.我们在开发中,有如下场景 a) 关闭空闲连接. ...

  5. U盘常见故障及检修

    一般U盘故障分为软故障和硬故障,其中以软故障最为常见.  软故障主要是指U盘有坏块,从而导致U盘能被计算机识别,但没有盘符出现,或者有盘符出现,但当打开U盘时却提示要进行格式化,而格式化又不能成功.前 ...

  6. qt windows分发工具使用(windoployqt)

      在qt的安装目录下:QTDIR/bin/windeployqt 例如我的默认安装在: C:\Qt\Qt5.3.1\5.3\msvc2013 windoployqt在: C:\Qt\Qt5.3.1\ ...

  7. iOS6和iOS7代码的适配(2)——status bar

    用Xcode5运行一下应用,第一个看到的就是status bar的变化.在iOS6中,status bar是系统在处理,应用中不需要考虑这部分,iOS7之后是应用在处理,每个ViewControlle ...

  8. 对应第一篇文章api的编写

    router.get('/api/tags/search/:list/:key/:page', function(req, res) { if(_.isEmpty(req.params.key)) { ...

  9. CentOS 安装Node.js

    先安装gcc-c++编译环境和openssl yum install gcc-c++ openssl-devel 然后 下载包并解压 cd /usr/local/src wget http://nod ...

  10. VS2015使用scanf报错解决方案

    版权声明:本文为博主原创文章,未经博主允许不得转载. 方法一:在程序最前面加#define _CRT_SECURE_NO_DEPRECATE: 方法二:在程序最前面加#define _CRT_SECU ...