1. 程式人生 > >Android 自定義通訊錄(仿Ios反彈效果+模糊搜尋+檢視手機通訊錄+拉伸導航條)

Android 自定義通訊錄(仿Ios反彈效果+模糊搜尋+檢視手機通訊錄+拉伸導航條)

       現在很多手機APP都用到通訊錄功能,在通訊錄的基礎上新增好友,查詢好友,獲取哪些好友和自己在玩同一款APP,這就需要去獲取手機通訊好友資訊,並把這些資訊展示出來!這些就需要列表展示通訊錄好友。但發現Android手機的通訊錄效果比Ios效果差很多,自己決定仿照Ios效果開發個自定義的通訊錄功能來。
       結合之前自己做過的通訊錄功能以及自定義listview反彈效果和自定義搜尋框。仿照一個比較全功能的通訊錄來,現在把自己成品貼出來,分享下,另外這個專案會在github不斷更新和完善!
-

貼出效果圖:
反彈效果導航模糊搜尋
自定義控制元件涉及有:

  1. 自定義ListView
  2. 自定義EditText
  3. 自定義觸壓顯示字母View

JListView

反彈效果無非就是在ListView的頭部加上個佈局和腳部加上個佈局,之後再重寫onTounchEvent方法,判斷tounch事件,做個邏輯處理。
onTounchEvent程式碼如下:

case MotionEvent.ACTION_DOWN://觸控按下
    mLastY = ev.getRawY();//觸控點相對於螢幕的Y座標,記錄在mLastY
    break;
case MotionEvent.ACTION_MOVE://觸控移動
    final float deltaY = ev.getRawY() - mLastY;//
用正負值判斷移動方向 mLastY = ev.getRawY(); if (getFirstVisiblePosition() == 0 && deltaY > 0) {//向下拉取,更新頭部高度 updateHeaderHeight(deltaY / OFFSET_RADIO); } else if (getLastVisiblePosition() == mTotalItemCount - 1 && deltaY < 0) {//向上拉去,更新尾部高度 updateFooterHeight(-deltaY / OFFSET_RADIO
); } break; case MotionEvent.ACTION_UP://觸控擡起 if (getFirstVisiblePosition() == 0) { resetHeaderHeight();//重置 } else if (getLastVisiblePosition() == mTotalItemCount - 1) { resetFooterHeight();//重置 }

這裡面是更新頭部、腳部高度程式碼原理就是獲取頭部、腳部佈局高度,在上下拉的力度進行重新設定佈局高度。
這裡面我就貼出頭部程式碼:

    private void setVisibleHeaderHeight(int height) {//設定頭部顯示的高度
        if (height < 0)
            height = 0;
        LayoutParams lp = (LayoutParams) headerLayout.getLayoutParams();
        lp.height = height;
        headerLayout.setLayoutParams(lp);
    }

自定義ListView還涉及一個字母導航條,原理就是把導航條的檢視新增到ListView來,重寫onMeasure獲取子控制元件的寬高並記錄,重寫onLayout畫出導航條的位置。

JClearEditText

自定義搜尋框,附加刪除按鈕,跟其他自定義控制元件一樣新建建構函式,不過在這裡需要提的一點是在建構函式中需要設定AttributeSet為edittextsytle。

    public JClearEditText(Context context, AttributeSet attrs) {
        // 這裡構造方法也很重要,不加自定義EditText的很多屬性就失效了
        this(context, attrs, android.R.attr.editTextStyle);
    }

之後,設定關閉按鈕和搜尋小圖示,這個圖片都是通過讀取getResources()資源獲取Drawable物件,通過setCompoundDrawables和setBounds結合設定圖片(Edittext繼承TextView包含這兩種方法)。其他監聽事件和隱藏圖片這些就不在這裡說了,有興趣可以檢視原始碼。

JIndexBarView

導航條原理就是把字母逐個畫出來,通過重寫onDraw:

    @Override
    protected void onDraw(Canvas canvas) {
        if (mListSections != null && mListSections.size() > 1) {
            float sectionHeight = (getMeasuredHeight()*mListSections.size()/26)/ mListSections.size();
            float paddingTop = (sectionHeight - (mIndexPaint.descent() - mIndexPaint.ascent())) / 2;

            for (int i = 0; i < mListSections.size(); i++) {
                float paddingLeft = (getMeasuredWidth() - mIndexPaint.measureText(getSectionText(mListSections.get(i)))) / 2;
                canvas.drawText(getSectionText(mListSections.get(i)),
                        paddingLeft,
                        mJIndexBarMargin + (sectionHeight * i) + paddingTop + mIndexPaint.descent(),
                        mIndexPaint);
            }
        }
        super.onDraw(canvas);
    }

之後在加個是JAdapter介面卡,並且讀取手機通訊錄資訊,把資訊結合下,就可以實現了!

目前專案已做成aar,方便開發者呼叫

用法

  • Android Studio

    compile 'com.soubw:jcontactlib:0.1.2'

呼叫示例

新增繼承實體物件JContacts(可直接使用JContacts實體物件,根據自己是否需要擴充套件實體屬性)

例項為新增自己拓展實體屬性

public class MainBean extends JContacts implements Serializable {

    private String wxj;

    public String getWxj() {
        return wxj;
    }

    public void setWxj(String wxj) {
        this.wxj = wxj;
    }

    public MainBean(){
        super();
    }
}

新增繼承JAdapter

public class MainAdapter extends JAdapter {


    public MainAdapter(Context context, List<MainBean> jContactsList, JListView lvList, int indexBarViewId, int previewViewId, int itemLayoutId, int sectionLayoutId, View loadingView) {
        super(context, jContactsList, lvList, indexBarViewId, previewViewId, itemLayoutId, sectionLayoutId, loadingView);
    }

    @Override
    public void convert(JViewHolder holder, JContacts bean, int type) {
        MainBean b = (MainBean) bean;
        switch (type) {
            case TYPE_ITEM:
                holder.setText(R.id.row_title,bean.getjName()+b.getWxj());
                break;
            case TYPE_SECTION:
                holder.setText(R.id.row_title,bean.getjFirstWord());
                break;
        }
    }
}

呼叫

            mAdaptor = new MainAdapter(this,
                jContactsList,//聯絡人列表
                (JListView) findViewById(R.id.lvList),//JListView物件
                R.layout.jcontact_index_bar_view,//導航條檢視
                R.layout.jcontact_preview_view,//預覽字母背景圖
                R.layout.jcontact_row_view,//列表內容view
                R.layout.jcontact_section_row_view,//列表字母view
                mLoadingView//載入LoadingView
        );

0.1.0版本以後

新增可自己選擇搜尋框的背景框和圖示,以及提示文字

        <com.soubw.jcontactlib.JListView
            android:id="@+id/lvList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:dividerHeight="0.1dp"
            android:divider="@android:color/black"
            jcontact:jClearEditTextBg="@drawable/jclearedittext_bg"
            jcontact:jClearEditTextCloseBg="@drawable/jclearedittext_close_bg"
            jcontact:jClearEditTextIconBg="@drawable/jclearedittext_icon_bg"
            jcontact:jClearEditTextNotice="請輸入關鍵字"
            android:scrollbars="none"/>

詳細可以參考Demo

具體詳細資訊可以檢視下原始碼:https://github.com/WX-JIN/JContact
如發現問題、或者其他建議,可以在我的GitHub上提issues,或者部落格留言,博主會第一時間來處理。謝謝!