亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android自定義View實(shí)現(xiàn)通訊錄字母索引(仿微信通訊錄)

 更新時(shí)間:2016年12月28日 10:38:16   作者:鐘光燕  
本文主要介紹了Android自定義View實(shí)現(xiàn)通訊錄字母索引(仿微信通訊錄)的實(shí)現(xiàn)步驟與方法,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧

一、效果:我們看到很多軟件的通訊錄在右側(cè)都有一個(gè)字母索引功能,像微信,小米通訊錄,QQ,還有美團(tuán)選擇地區(qū)等等。這里我截了一張美團(tuán)選擇城市的圖片來(lái)看看;

我們今天就來(lái)實(shí)現(xiàn)圖片中右側(cè)模塊的索引功能,包括觸摸顯示以選中的索引字母。這里我的UI界面主要是參照微信的界面來(lái)實(shí)現(xiàn),所以各位也可以對(duì)照微信來(lái)看看效果,什么都不說(shuō)了,只有效果圖最具有說(shuō)服力!

二、分析:

我們看到這樣的效果我們心理都回去琢磨,他是如何實(shí)現(xiàn)的;

首先,它肯定是通過(guò)自定義 View 來(lái)實(shí)現(xiàn)的,因?yàn)?Android 沒(méi)有提供類似這樣的控件、那么接下來(lái)就是如何自定義我們的 View ,我們知道自定義 View 最最主要的兩個(gè)方法就是 onDraw(Canvas canvas)和

onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法,當(dāng)然,如果是自定義 ViewGroup 的話就必須實(shí)現(xiàn)

onLayout(boolean changed, int left, int top, int right, int bottom) 方法,這里我們顯然用自定義 View 就能夠?qū)崿F(xiàn)此功能,通過(guò)效果圖可以看帶,當(dāng)觸摸這塊區(qū)域的時(shí)候,會(huì)彈出一個(gè)懸浮類似 Toast 的框來(lái)顯示已經(jīng)選中的索引內(nèi)容,所以這里還需要重寫View 的onTouchEvent(MotionEvent event)事件,最后就是懸浮框的實(shí)現(xiàn)。那么接下來(lái)就開(kāi)始我們編碼。

三、編碼實(shí)現(xiàn):

我們就按照 View 的執(zhí)行順序來(lái)實(shí)現(xiàn)

1、實(shí)現(xiàn)onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法,這個(gè)方法的功能是測(cè)量出我們的寬和高,具體實(shí)現(xiàn)看代碼

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

這里定義了兩個(gè)方法measureWidth( int) 和 measureHeight(int) ,通過(guò)方法名可以很清楚的知道,其功能分別是測(cè)量寬和高,進(jìn)去看看是如何測(cè)量的。

 /**
  * 測(cè)量本身的大小,這里只是測(cè)量寬度
  * @param widthMeaSpec 傳入父View的測(cè)量標(biāo)準(zhǔn)
  * @return 測(cè)量的寬度
  */
 private int measureWidth(int widthMeaSpec){
  /*定義view的寬度*/
  int width ;
  /*獲取當(dāng)前 View的測(cè)量模式*/
  int mode = MeasureSpec.getMode(widthMeaSpec) ;
  /*
  * 獲取當(dāng)前View的測(cè)量值,這里得到的只是初步的值,
  * 我們還需根據(jù)測(cè)量模式來(lái)確定我們期望的大小
  * */
  int size = MeasureSpec.getSize(widthMeaSpec) ;
  /*
  * 如果,模式為精確模式
  * 當(dāng)前View的寬度,就是我們
  * 的size ;
  * */
  if(mode == MeasureSpec.EXACTLY){
   width = size ;
  }else {
   /*否則的話我們就需要結(jié)合padding的值來(lái)確定*/
   int desire = size + getPaddingLeft() + getPaddingRight() ;
   if(mode == MeasureSpec.AT_MOST){
    width = Math.min(desire,size) ;
   }else {
    width = desire ;
   }
  }
  mViewWidth = width ;
  return width ;
 }

以上是測(cè)量寬度的代碼,其測(cè)量高度的代碼,跟測(cè)量寬度的代碼大致雷同,就不貼出來(lái)了,我會(huì)在最后附上源碼。

2、實(shí)現(xiàn)onDraw(Canvas c)方法,這個(gè)方法相信大家都非常熟悉,就是把這些索引的內(nèi)容繪制到 View 上顯示出來(lái),包括選中的時(shí)候背景顏色的變化;

 @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();
  }
 }

我來(lái)講一下 onDraw 方法中大致做了什么事,第一,繪制背景顏色,注意不是一上來(lái)就繪制,而是等到有手指觸摸的時(shí)候就繪制背景顏色,第二,就是繪制索引的內(nèi)容,這里需要根據(jù)當(dāng)前 View 的寬和高來(lái)決定繪制內(nèi)容的大小,和位置。

3、onTouchEvent(MotionEvent event)方法的實(shí)現(xiàn)

 @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();
  /*過(guò)濾點(diǎn)其他觸摸事件*/
  return true;
 }

代碼也相對(duì)比較簡(jiǎn)單,首先獲取當(dāng)前觸摸的點(diǎn),根據(jù)點(diǎn)的坐標(biāo)來(lái)獲取索引的位置,從而拿到索引的位置。

4、到這里其實(shí)就已經(jīng)實(shí)現(xiàn)了我們想要的效果,但是這樣我們還是無(wú)法運(yùn)用它,這里就需要定義一個(gè)回調(diào)接口

 /*定義一個(gè)回調(diào)接口*/
 public interface OnIndexSelectListener{
  /*返回選中的位置,和對(duì)應(yīng)的索引名*/
  void onItemSelect(int position, String value) ;
 }

回調(diào)接口我們放在哪里調(diào)用呢,當(dāng)我們手指按下的時(shí)候,這時(shí)候其實(shí)我們需要確定我們按下的是哪個(gè)索引,滑動(dòng)的時(shí)候也是一樣,所以,這個(gè)沒(méi)什么好商量的,直接放在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)方法中就是執(zhí)行的回調(diào)方法。

5、實(shí)現(xiàn)懸浮框顯示已經(jīng)選中的索引內(nèi)容

這里需要用到 WindowManager 容器,然需要現(xiàn)實(shí)的 View 附在這上面的就行,當(dāng)手指按下的時(shí)候,讓 View 顯示出來(lái),松開(kāi)不顯示就行了

  /*設(shè)置浮動(dòng)選中的索引*/
  /*獲取windowManager*/
  mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
  /*overly 視圖,通過(guò)LayoutInflater 獲取*/
  mFloatView = LayoutInflater.from(getContext()).inflate(R.layout.overlay_indexview,null) ;
  /*開(kāi)始讓其不可見(jiàn)*/
  mFloatView.setVisibility(INVISIBLE);
  /*轉(zhuǎn)換 高度 和寬度為Sp*/
  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);
   }
  }) ;

同樣的道理,如果需要改變顯示的內(nèi)容,就需要在調(diào)用回調(diào)的位置,為 View 中的 TextView 設(shè)置當(dāng)前的索引內(nèi)容。

好了此 View 的代碼就這么多,

接下來(lái)就把引用他的 Xml 和浮動(dòng) View 的 Xml 也貼出來(lái),

引用的布局文件

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

浮動(dòng) 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>

浮動(dòng) 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>

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!

相關(guān)文章

  • Android指紋識(shí)別API初試

    Android指紋識(shí)別API初試

    這篇文章主要為大家詳細(xì)介紹了Android指紋識(shí)別API,感興趣的小伙伴們可以參考一下
    2016-07-07
  • Android中自定義一個(gè)View的方法詳解

    Android中自定義一個(gè)View的方法詳解

    這篇文章主要介紹了Android中自定義一個(gè)View的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android中自定義View的具體步驟與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2016-07-07
  • Android通過(guò)原生APi獲取所在位置的經(jīng)緯度

    Android通過(guò)原生APi獲取所在位置的經(jīng)緯度

    本篇文章主要介紹了Android通過(guò)原生APi獲取所在位置的經(jīng)緯度,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • Android錄音功能的實(shí)現(xiàn)以及踩坑實(shí)戰(zhàn)記錄

    Android錄音功能的實(shí)現(xiàn)以及踩坑實(shí)戰(zhàn)記錄

    在Android 開(kāi)發(fā)過(guò)程中,有些功能是通用的,或者是多個(gè)業(yè)務(wù)方都需要使用的,下面這篇文章主要給大家介紹了關(guān)于Android錄音功能的實(shí)現(xiàn)以及踩坑的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • Android硬件解碼組件MediaCodec使用教程

    Android硬件解碼組件MediaCodec使用教程

    在Android開(kāi)發(fā)中提供了實(shí)現(xiàn)音視頻編解碼工具M(jìn)ediaCodec,針對(duì)對(duì)應(yīng)音視頻解碼類型通過(guò)該類創(chuàng)建對(duì)應(yīng)解碼器就能實(shí)現(xiàn)對(duì)數(shù)據(jù)進(jìn)行解碼操作。本文通過(guò)示例詳細(xì)講解了MediaCodec的使用,需要的可以參考一下
    2022-11-11
  • Kotlin掛起函數(shù)原理示例剖析

    Kotlin掛起函數(shù)原理示例剖析

    這篇文章主要為大家介紹了Kotlin掛起函數(shù)的原理示例剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Android Jetpack- Paging的使用詳解

    Android Jetpack- Paging的使用詳解

    這篇文章主要介紹了Android Jetpack- Paging的使用詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Android Studio快捷鍵生成TAG、Log.x日志輸出介紹

    Android Studio快捷鍵生成TAG、Log.x日志輸出介紹

    這篇文章主要介紹了Android Studio快捷鍵生成TAG、Log.x日志輸出介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-04-04
  • Android開(kāi)發(fā)實(shí)例之登錄界面的實(shí)現(xiàn)

    Android開(kāi)發(fā)實(shí)例之登錄界面的實(shí)現(xiàn)

    本文主要介紹Android 登錄界面實(shí)現(xiàn),這里主要講解類似Twitter的登錄界面的實(shí)現(xiàn),有興趣的小伙伴可以參考下
    2016-08-08
  • Android Studio打包APK文件具體實(shí)現(xiàn)步驟解析

    Android Studio打包APK文件具體實(shí)現(xiàn)步驟解析

    這篇文章主要介紹了Android Studio打包APK文件具體實(shí)現(xiàn)步驟解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11

最新評(píng)論