仿微信通訊錄字母排序列表

先看下效果圖


Gif_20180425_103334.gif

在這里我們先分析下效果,左邊是一個按照字母排序的并有子列表卧蜓,右邊是直接一個字母的排列帐要,屏幕中間有一個顯示你點擊了右邊的那個字母的顯示。
在這里我們先去處理右邊的字母列表弥奸。我們先去自定義一個view榨惠,把26個字母和“#”放到一個數(shù)組里面,再用畫筆在ondraw()里面畫出來其爵。

   @Override
    protected void onDraw(Canvas canvas) {
        // 畫26個字母

        int itemHeight = (getHeight() - getPaddingTop() - getPaddingBottom()) / mLetters.length;

        for (int i = 0; i < mLetters.length; i++) {
            // 知道每個字母的中心位置  1  字母的高度一半   2 字母高度一般+前面字符的高度
            int letterCenterY = i * itemHeight + itemHeight / 2 + getPaddingTop();
            // 基線冒冬,基于中心位置, 知道中心位置還不會基線,看一下之前的視頻
            Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
            int dy = (int) ((fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom);
            int baseLine = letterCenterY + dy;
            // x 繪制在最中間 = 寬度/2 - 文字/2
            int textWidth = (int) mPaint.measureText(mLetters[i]);
            int x = getWidth() / 2 - textWidth / 2;
            if (!isUp){
                // 當前字母 高亮  用兩個畫筆(最好) 改變顏色
                if (mLetters[i].equals(mCurrentTouchLetter)) {
                    mPaint.setColor(Color.RED);
                    canvas.drawText(mLetters[i], x, baseLine, mPaint);
                } else {
                    mPaint.setColor(Color.BLUE);
                    canvas.drawText(mLetters[i], x, baseLine, mPaint);
                }
            }else {
                mPaint.setColor(Color.BLUE);
                canvas.drawText(mLetters[i], x, baseLine, mPaint);
            }

        }
    }

當我們在這個字母列表上面滑動的時候摩渺,被點擊到的字母會變色简烤,這就需要有兩個顏色的畫筆去分別畫不同的字母。
我們可以在onTouchEvent方法里面拿到按下和滑動的事件摇幻,在MotionEvent.ACTION_DOWN和MotionEvent.ACTION_MOVE的時候處理字母的變色横侦。我們首先得那個我們點擊的是哪個字母挥萌,我們可以拿到當前點擊位置的y方向的距離去除以每個字母的高度,然后取整就知道那個字母被點擊了枉侧,這時候調(diào)用invalidate方法去重新繪制字母列表引瀑,這樣就可以實現(xiàn)當那個字母被點擊或者是滑動時被覆蓋的字母變色的效果。然后在這里我們寫一個回調(diào)榨馁,去讓頁面中間的那個textview知道如何去顯示那個字母被點擊了憨栽。

  @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                // 計算出當前觸摸字母  獲取當前的位置
                float currentMoveY = event.getY();
                // 位置 = currentMoveY / 字母高度 , 通過位置獲取字母  優(yōu)化翼虫?
                int itemHeight = (getHeight() - getPaddingTop() - getPaddingBottom()) / mLetters.length;
                currentPosition = (int) (currentMoveY / itemHeight);

                if (currentPosition < 0)
                    currentPosition = 0;

                if (currentPosition > mLetters.length - 1)
                    currentPosition = mLetters.length - 1;

                // 要判斷 屑柔?

                mCurrentTouchLetter = mLetters[currentPosition];

                if (mListener != null) {
                    mListener.touch(mCurrentTouchLetter, true, currentPosition);
                }
                isUp = false;
                // 重新繪制
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                if (mListener != null) {
                    mListener.touch(mCurrentTouchLetter, false, currentPosition);
                }
                isUp = true;
                // 重新繪制
                invalidate();
                break;
        }
        return true;
    }


    private LetterTouchListener mListener;

    public void setOnLetterTouchListener(LetterTouchListener listener) {
        this.mListener = listener;
    }

    // 接口回掉其他View會不會使用?
    public interface LetterTouchListener {
        void touch(CharSequence letter, boolean isTouch,int currentPosition);
    }

我們ManActivity的布局文件是這樣的

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"
    android:layout_height="match_parent"
  >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_letter"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


    <TextView
        android:id="@+id/letter_tv"
        android:layout_width="wrap_content"
        android:layout_centerInParent="true"
        android:text="A"
        android:visibility="gone"
        android:textSize="16sp"
        android:textColor="#FF0000"
        android:layout_height="wrap_content" />

    <com.example.letterlist.LetterSideBar
        android:id="@+id/letter_side_bar"
        android:layout_width="wrap_content"
        android:layout_alignParentRight="true"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:layout_height="match_parent" />
    </RelativeLayout>
</FrameLayout>

在ManActivity里面我們給RecyclerView添加數(shù)據(jù)珍剑,先給RecyclerView添加字母列表掸宛,在RecyclerView的布局文件在添加一個子RecyclerView。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView

        android:id="@+id/tv_text"
        android:textSize="15sp"
        android:background="#9999"
        android:textColor="#fff"
        android:layout_width="match_parent"
        android:layout_height="50dp" />
    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_child"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

給子RecyclerView添加數(shù)據(jù)之后招拙,在會掉里面唧瘾,當右邊的列表那個被惦記了,就將父RecyclerView的那個對應(yīng)位置的條目滾動到頂部别凤,這樣效果就實現(xiàn)了

   @Override
    public void touch(CharSequence letter,boolean isTouch,int current) {
        if(isTouch) {
            mLetterTv.setVisibility(View.VISIBLE);
            mLetterTv.setText(letter);
            rvLetter.scrollToPosition(current);
            //讓RecyclerView滾動到頂部
            if (current != -1) {
                rvLetter.scrollToPosition(current);
                LinearLayoutManager mLayoutManager =
                        (LinearLayoutManager) rvLetter.getLayoutManager();
                mLayoutManager.scrollToPositionWithOffset(current, 0);
            }

        }else{
            mLetterTv.setVisibility(View.GONE);

        }
    }

項目已經(jīng)放到github上面:https://github.com/chenzhikaizg/LetterListView

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饰序,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子规哪,更是在濱河造成了極大的恐慌菌羽,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件由缆,死亡現(xiàn)場離奇詭異,居然都是意外死亡猾蒂,警方通過查閱死者的電腦和手機均唉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肚菠,“玉大人舔箭,你說我怎么就攤上這事∥梅辏” “怎么了层扶?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長烙荷。 經(jīng)常有香客問我镜会,道長,這世上最難降的妖魔是什么终抽? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任戳表,我火速辦了婚禮桶至,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匾旭。我一直安慰自己镣屹,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布价涝。 她就那樣靜靜地躺著女蜈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪色瘩。 梳的紋絲不亂的頭發(fā)上伪窖,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音泞遗,去河邊找鬼惰许。 笑死,一個胖子當著我的面吹牛史辙,可吹牛的內(nèi)容都是我干的汹买。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼聊倔,長吁一口氣:“原來是場噩夢啊……” “哼晦毙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耙蔑,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤见妒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后甸陌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體须揣,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年钱豁,在試婚紗的時候發(fā)現(xiàn)自己被綠了耻卡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡牲尺,死狀恐怖卵酪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谤碳,我是刑警寧澤溃卡,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蜒简,受9級特大地震影響瘸羡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜搓茬,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一最铁、第九天 我趴在偏房一處隱蔽的房頂上張望讯赏。 院中可真熱鬧,春花似錦冷尉、人聲如沸漱挎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽磕谅。三九已至,卻和暖如春雾棺,著一層夾襖步出監(jiān)牢的瞬間膊夹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工捌浩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留放刨,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓尸饺,卻偏偏與公主長得像进统,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子浪听,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容