Android 自定义通讯录(仿Ios反弹效果+模糊搜索+查看手机通讯录+拉伸导航条)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WX_JIN/article/details/50848033

       现在很多手机APP都用到通讯录功能,在通讯录的基础上添加好友,查找好友,获取哪些好友和自己在玩同一款APP,这就需要去获取手机通讯好友信息,并把这些信息展示出来!这些就需要列表展示通讯录好友。但发现Android手机的通讯录效果比Ios效果差很多,自己决定仿照Ios效果开发个自定义的通讯录功能来。
       结合之前自己做过的通讯录功能以及自定义listview反弹效果和自定义搜索框。仿照一个比较全功能的通讯录来,现在把自己成品贴出来,分享下,另外这个项目会在github不断更新和完善!
-
github地址https://github.com/WX-JIN/JContact

贴出效果图:
反弹效果导航模糊搜索
自定义控件涉及有:

  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

    引入依赖,依赖包最新版本请查看项目在github说明

    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,或者博客留言,博主会第一时间来处理。谢谢!


私家博客:http://soubw.com/
CSDN:http://blog.csdn.net/wx_jin

参考文章地址:https://github.com/bhavyahmehta/ListviewFilter

展开阅读全文

没有更多推荐了,返回首页