文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android自定义View实现通讯录字母索引(仿微信通讯录)

2022-06-06 05:07

关注

一、效果:我们看到很多软件的通讯录在右侧都有一个字母索引功能,像微信,小米通讯录,QQ,还有美团选择地区等等。这里我截了一张美团选择城市的图片来看看;

我们今天就来实现图片中右侧模块的索引功能,包括触摸显示以选中的索引字母。这里我的UI界面主要是参照微信的界面来实现,所以各位也可以对照微信来看看效果,什么都不说了,只有效果图最具有说服力!

二、分析:

我们看到这样的效果我们心理都回去琢磨,他是如何实现的;

首先,它肯定是通过自定义 View 来实现的,因为 Android 没有提供类似这样的控件、那么接下来就是如何自定义我们的 View ,我们知道自定义 View 最最主要的两个方法就是 onDraw(Canvas canvas)和

onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法,当然,如果是自定义 ViewGroup 的话就必须实现

onLayout(boolean changed, int left, int top, int right, int bottom) 方法,这里我们显然用自定义 View 就能够实现此功能,通过效果图可以看带,当触摸这块区域的时候,会弹出一个悬浮类似 Toast 的框来显示已经选中的索引内容,所以这里还需要重写View 的onTouchEvent(MotionEvent event)事件,最后就是悬浮框的实现。那么接下来就开始我们编码。

三、编码实现:

我们就按照 View 的执行顺序来实现

1、实现onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法,这个方法的功能是测量出我们的宽和高,具体实现看代码


 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));
 }

这里定义了两个方法measureWidth( int) 和 measureHeight(int) ,通过方法名可以很清楚的知道,其功能分别是测量宽和高,进去看看是如何测量的。


 
 private int measureWidth(int widthMeaSpec){
  
  int width ;
  
  int mode = MeasureSpec.getMode(widthMeaSpec) ;
  
  int size = MeasureSpec.getSize(widthMeaSpec) ;
  
  if(mode == MeasureSpec.EXACTLY){
   width = size ;
  }else {
   
   int desire = size + getPaddingLeft() + getPaddingRight() ;
   if(mode == MeasureSpec.AT_MOST){
    width = Math.min(desire,size) ;
   }else {
    width = desire ;
   }
  }
  mViewWidth = width ;
  return width ;
 }

以上是测量宽度的代码,其测量高度的代码,跟测量宽度的代码大致雷同,就不贴出来了,我会在最后附上源码。

2、实现onDraw(Canvas c)方法,这个方法相信大家都非常熟悉,就是把这些索引的内容绘制到 View 上显示出来,包括选中的时候背景颜色的变化;


 @Override
 protected void onDraw(Canvas canvas) {
  if(mTouched){
   canvas.drawColor(0x30000000);
  }
  for (int i = 0 ; i < mIndex.length ; i ++){
   mPaint.setColor(0xff000000);
   mPaint.setTextSize(mTextSize * 3.0f / 4.0f);
   mPaint.setTypeface(Typeface.DEFAULT) ;
   mPaint.getTextBounds(mIndex[i],0,mIndex[i].length(),mTextBound);
   float formX = mViewWidth/2.0f - mTextBound.width()/2.0f ;
   float formY = mTextSize*i + mTextSize/2.0f + mTextBound.height()/2.0f ;
   canvas.drawText(mIndex[i],formX,formY,mPaint);
   mPaint.reset();
  }
 }

我来讲一下 onDraw 方法中大致做了什么事,第一,绘制背景颜色,注意不是一上来就绘制,而是等到有手指触摸的时候就绘制背景颜色,第二,就是绘制索引的内容,这里需要根据当前 View 的宽和高来决定绘制内容的大小,和位置。

3、onTouchEvent(MotionEvent event)方法的实现


 @Override
 public boolean onTouchEvent(MotionEvent event) {
  float y = event.getY() ;
  int index = (int) (y / mTextSize);
  if(index >= 0 && index < mIndex.length){
   Log.v("zgy","======index======="+index) ;
   selectItem(index);
  }
  if(event.getAction() == MotionEvent.ACTION_MOVE){
   mTouched = true ;
  }else if (event.getAction() == MotionEvent.ACTION_MOVE){
  }else {
   mFloatView.setVisibility(INVISIBLE);
   mTouched = false ;
  }
  invalidate();
  
  return true;
 }

代码也相对比较简单,首先获取当前触摸的点,根据点的坐标来获取索引的位置,从而拿到索引的位置。

4、到这里其实就已经实现了我们想要的效果,但是这样我们还是无法运用它,这里就需要定义一个回调接口


 
 public interface OnIndexSelectListener{
  
  void onItemSelect(int position, String value) ;
 }

回调接口我们放在哪里调用呢,当我们手指按下的时候,这时候其实我们需要确定我们按下的是哪个索引,滑动的时候也是一样,所以,这个没什么好商量的,直接放在onTouchEvent(MotionEvent event)中就可以,


  float y = event.getY() ;
  int index = (int) (y / mTextSize);
  if(index >= 0 && index < mIndex.length){
   Log.v("zgy","======index======="+index) ;
   selectItem(index);
  }

selectItem(int)方法中就是执行的回调方法。

5、实现悬浮框显示已经选中的索引内容

这里需要用到 WindowManager 容器,然需要现实的 View 附在这上面的就行,当手指按下的时候,让 View 显示出来,松开不显示就行了


  
  
  mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
  
  mFloatView = LayoutInflater.from(getContext()).inflate(R.layout.overlay_indexview,null) ;
  
  mFloatView.setVisibility(INVISIBLE);
  
  mOverlyWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,70,getResources().getDisplayMetrics()) ;
  mOverlyHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,70,getResources().getDisplayMetrics()) ;
  post(new Runnable() {
   @Override
   public void run() {
    WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(mOverlyWidth,mOverlyHeight,
      WindowManager.LayoutParams.TYPE_APPLICATION,
      WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
      PixelFormat.TRANSLUCENT) ;
    mWindowManager.addView(mFloatView,layoutParams);
   }
  }) ;

同样的道理,如果需要改变显示的内容,就需要在调用回调的位置,为 View 中的 TextView 设置当前的索引内容。

好了此 View 的代码就这么多,

接下来就把引用他的 Xml 和浮动 View 的 Xml 也贴出来,

引用的布局文件


 <moon.wechat.view.IndexView
  android:layout_width="25dp"
  android:layout_height="match_parent"
  android:layout_alignParentRight="true"/>

浮动 View 的布局文件


<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/overly_text"
 android:layout_width="70dp"
 android:layout_height="70dp"
 android:text="A"
 android:gravity="center"
 android:background="@drawable/bg_overly_text"
 android:textSize="40sp"
 android:textColor="#ffffffff"
 android:layout_gravity="center">
</TextView>

浮动 View 的背景


<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 <item>
  <shape>
   <solid android:color="#88000000"/>
   <corners android:radius="5dp"/>
  </shape>
 </item>
</layer-list>
您可能感兴趣的文章:android仿微信通讯录搜索示例(匹配拼音,字母,索引位置)Android 实现带字母索引的侧边栏功能Android通用索引栏实现代码Android手机联系人带字母索引的快速查找Android手机联系人快速索引(手机通讯录)android将搜索引擎设置为中国雅虎无法搜索问题解决方法android 左右滑动+索引图标实现方法与代码Android ItemDecoration 实现分组索引列表的示例代码


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯