精华内容
下载资源
问答
  • 仿微信通讯录

    2017-03-30 16:47:07
    仿微信通讯录
  • 高仿微信通讯录

    2018-09-30 10:04:48
    高仿微信通讯录,详细介绍请到https://blog.csdn.net/zyw0101/article/details/82832137
  • 高仿微信通讯录列表

    2017-11-10 16:23:40
    高仿微信通讯录列表。 滑动字母导航
  • 仿微信通讯录排序

    2018-08-28 11:06:39
    eclipse项目,代码类,实用性,仿微信通讯录名称排序,demo简介明了
  • 主要为大家详细介绍了Android仿微信通讯录列表侧边栏效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • Android仿微信通讯录侧边栏
  • 仿微信通讯录, 通讯录朋友按名字首字母索引排序, 可实现添加朋友, 访问本地通讯录,并添加通讯录朋友 其他 可进行联系人姓名搜索,支持中文和拼音搜索 利用NotificationCenter,实现不同的视图控制器之间的参数...
  • 主要介绍了Android仿微信通讯录滑动快速定位功能,非常不错,具有参考借鉴价值,需要的朋友可以参考下
  • 主要介绍了小程序组件之仿微信通讯录的实现代码。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • RecyclerView+index实现仿微信通讯录
  • 本文主要介绍了Android自定义View实现通讯录字母索引(仿微信通讯录)的实现步骤与方法,具有很好的参考价值,下面跟着小编一起来看下吧
  • React Native 仿微信通讯录右侧字母快捷操作区.pdf
  • react native 触摸事件机制详解,及高仿微信通讯录功能。
  • 主要介绍了Android 仿微信通讯录导航分组列表,使用ItemDecoration为RecyclerView打造带悬停头部的分组列表,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 用Recycleview实现仿微信通讯录的右侧索引,pinyin4 .jja包实现汉字转化为拼音进行索引
  • Android仿微信通讯录

    千次阅读 2019-09-24 10:06:08
    Android仿微信通讯录 分3部: 1、listview实现显示头像、名字(太简单,这里就不写了) 通讯录页面xml布局代码: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:...

    Android仿微信通讯录

     

    分3部:

    1、listview实现显示头像、名字(太简单,这里就不写了)

    通讯录页面xml布局代码:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
       >
    
        <FrameLayout
            android:id="@+id/fl"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
    
            <ListView
    
                android:id="@+id/school_friend_member"
    
                android:layout_width="match_parent"
    
                android:layout_height="match_parent"
    
                android:cacheColorHint="@android:color/transparent"
    
                android:dividerHeight="1px"
    
                android:fadingEdge="none"
    
                android:listSelector="@android:color/transparent"
    
                android:scrollbars="none"></ListView>
    
    
            <TextView
    
                android:id="@+id/school_friend_dialog"
    
                android:layout_width="80dp"
    
                android:layout_height="80dp"
    
                android:layout_gravity="center"
    
                android:background="@color/green_light"
    
                android:gravity="center"
    
                android:textColor="#ffffffff"
    
                android:textSize="30dp"
    
                android:visibility="invisible" />
    
    
            <com.diancanwang.dell.diancanwang.chat.bean.SideBar
    
                android:id="@+id/school_friend_sidrbar"
    
                android:layout_width="30dp"
    
                android:layout_height="match_parent"
    
                android:layout_gravity="right|center" />
    
        </FrameLayout>
    
    </LinearLayout>

    2、实现A——Z的好友分类

    首先 导入拼音依赖

    compile files('libs/pinyin4j-2.5.0.jar')  (依赖可以到网上搜索一个,添加到app下面的libs文件夹里,我这里给出的是我添加好后app build.gradle里面的)

    其次

    import net.sourceforge.pinyin4j.PinyinHelper;
    import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
    import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
    import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
    import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
    import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
    
    import java.util.Comparator;
    
    /**
     * 2018/4/22.
     */
    
    public class PinyinComparator implements Comparator<SortModel> {
        public int compare(SortModel o1, SortModel o2) {
            if (o1.getSortLetters().equals("@")
                    || o2.getSortLetters().equals("#")) {
                return -1;
            } else if (o1.getSortLetters().equals("#")
                    || o2.getSortLetters().equals("@")) {
                return 1;
            } else {
                return o1.getSortLetters().compareTo(o2.getSortLetters());
            }
        }
    
        public static String getPingYin(String inputString) {
            HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
            format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
            format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
            format.setVCharType(HanyuPinyinVCharType.WITH_V);
            char[] input = inputString.trim().toCharArray();
            String output = "";
            try {
                for (char curchar : input) {
                    if (java.lang.Character.toString(curchar).matches("[\u4e00-\u9fa5]+")) {
                        String[] temp = PinyinHelper.toHanyuPinyinStringArray(curchar, format);
                        output += temp[0];
                    } else
                        output += java.lang.Character.toString(curchar);
                }
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                e.printStackTrace();
            }
            return output;
        }
    
    }

     

    实体类

    /**
     *  2018/4/22.
     * 实体类
     */
    
    public class SortModel {
        private int img;//头像
        private String name;   //显示的数据
        private String sortLetters;  //显示数据拼音的首字母
    
        public SortModel(int img, String name, String sortLetters) {
            this.img = img;
            this.name = name;
            this.sortLetters = sortLetters;
        }
    
        public SortModel() {
        }
    
        public int getImg() {
            return img;
        }
    
        public void setImg(int img) {
            this.img = img;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSortLetters() {
            return sortLetters;
        }
    
        public void setSortLetters(String sortLetters) {
            this.sortLetters = sortLetters;
        }
    
        @Override
        public String toString() {
            return "SortModel{" +
                    "img=" + img +
                    ", name='" + name + '\'' +
                    ", sortLetters='" + sortLetters + '\'' +
                    '}';
        }
    }

     

    
    import android.widget.ListView;
    import android.widget.TextView;
    
    import com.diancanwang.dell.diancanwang.R;
    import com.diancanwang.dell.diancanwang.base.BaseFragment;
    import com.diancanwang.dell.diancanwang.chat.adapter.SortAdapter;
    import com.diancanwang.dell.diancanwang.chat.bean.PinyinComparator;
    import com.diancanwang.dell.diancanwang.chat.bean.SideBar;
    import com.diancanwang.dell.diancanwang.chat.bean.SortModel;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import butterknife.Bind;
    
    /**
     * 通讯录页面
     */
    public class AddBookFragment extends BaseFragment {
    
        @Bind(R.id.school_friend_member)
        ListView mListView;
        @Bind(R.id.school_friend_dialog)
        TextView mDialog;
        @Bind(R.id.school_friend_sidrbar)
        SideBar mSideBar;
        private List<SortModel> list;
    
        @Override
        protected int getLayoutId() {
            return R.layout.fragment_add_book;
        }
    
        @Override
        protected void initView() {
    
        }
    
        @Override
        protected void initData() {
            list = new ArrayList<>();
    //        for (int i = 0; i < 10; i++) {
            SortModel sortModel = new SortModel();
            SortModel sortModel1 = new SortModel();
            SortModel sortModel2 = new SortModel();
            SortModel sortModel3 = new SortModel();
            SortModel sortModel4 = new SortModel();
            SortModel sortModel5 = new SortModel();
    
    
            sortModel.setImg(R.mipmap.ic_launcher);
            sortModel1.setImg(R.mipmap.ic_launcher);
            sortModel2.setImg(R.mipmap.ic_launcher);
            sortModel3.setImg(R.mipmap.ic_launcher);
            sortModel4.setImg(R.mipmap.ic_launcher);
            sortModel5.setImg(R.mipmap.ic_launcher);
            sortModel2.setName("华为");
            sortModel.setName("阿里巴巴");
            sortModel1.setName("百度");
            sortModel3.setName("xiaoxue");
            sortModel4.setName("……%¥#¥%#");
            sortModel5.setName("百家姓");
    
            String pingYin = PinyinComparator.getPingYin("阿里巴巴");
            String pingYin1 = PinyinComparator.getPingYin("百度");
            String pingYin2 = PinyinComparator.getPingYin("华为");
            String pingYin3 = PinyinComparator.getPingYin("xiaoxue");
            String pingYin4 = PinyinComparator.getPingYin("……%¥#¥%#");
            String pingYin5 = PinyinComparator.getPingYin("百家姓");
    
            sortModel3.setSortLetters(pingYin3);
            sortModel.setSortLetters(pingYin);
            sortModel1.setSortLetters(pingYin1);
            sortModel2.setSortLetters(pingYin2);
            sortModel4.setSortLetters(pingYin4);
            sortModel5.setSortLetters(pingYin5);
    
    
    
            list.add(sortModel2);
            list.add(sortModel1);
            list.add(sortModel3);
            list.add(sortModel);
            list.add(sortModel4);
            list.add(sortModel5);
    
    //        }
        }
    
        @Override
        protected void initAdapter() {
            SortAdapter adapter = new SortAdapter(list, getActivity());
            mListView.setAdapter(adapter);
        }
    
    
    }

     

    适配器

    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.SectionIndexer;
    import android.widget.TextView;
    
    import com.bumptech.glide.Glide;
    import com.diancanwang.dell.diancanwang.R;
    import com.diancanwang.dell.diancanwang.chat.bean.PinyinComparator;
    import com.diancanwang.dell.diancanwang.chat.bean.SortModel;
    
    import java.util.Collections;
    import java.util.List;
    
    /**
     * 2018/4/22.
     */
    
    public class SortAdapter extends BaseAdapter implements SectionIndexer {
        private List<SortModel> list;
        private Context mContext;
    
        public SortAdapter(List<SortModel> list, Context mContext) {
            this.list = list;
            this.mContext = mContext;
        }
    
        public void updateListView(List<SortModel> list) {
            this.list = list;
            notifyDataSetChanged();
        }
    
    
        @Override
        public int getCount() {
            return list.size();
        }
    
        @Override
        public Object getItem(int position) {
            return list.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder = null;
            if (convertView == null) {
                viewHolder = new ViewHolder();
                convertView = LayoutInflater.from(mContext).inflate(R.layout.item, null);
                //头像
                viewHolder.imgHead = (ImageView) convertView.findViewById(R.id.book_head);
                //昵称
                viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.book_name);
                //索引字母
                viewHolder.tvLetter = (TextView) convertView.findViewById(R.id.catalog);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
    
    
             获取首字母的assii值
            int section = getSectionForPosition(position);
            //通过首字母的assii值来判断是否显示字母
            int positionForSelection = getPositionForSection(section);
    
            viewHolder.tvLetter.setOnClickListener(null);
    
            if (position == positionForSelection) {
    
                viewHolder.tvLetter.setVisibility(View.VISIBLE);
                //把拼音转成大写字母,并取首字母    toUpperCase()  转换为大写字母
                String firstLetter = list.get(position).getSortLetters().substring(0, 1).toUpperCase();
                // 正则表达式,判断首字母是否是英文字母
                if (firstLetter.matches("[A-Z]")) {
    //              给通讯录好友排序(按照从A-Z的顺序)
                    Collections.sort(list, new PinyinComparator());
                    //给控件设置值
                    viewHolder.tvLetter.setText(firstLetter);
                } else {
                    viewHolder.tvLetter.setText("#");
                }
    
    
            } else {
                viewHolder.tvLetter.setVisibility(View.GONE);
            }
    
            Glide.with(mContext).load(list.get(position).getImg()).into(viewHolder.imgHead);
            viewHolder.tvTitle.setText(list.get(position).getName());
    
            return convertView;
        }
    
        final static class ViewHolder {
            ImageView imgHead;
            TextView tvLetter;
            TextView tvTitle;
        }
    
        @Override
        public Object[] getSections() {
            return null;
        }
    
        @Override
        public int getPositionForSection(int section) {
            for (int i = 0; i < getCount(); i++) {
                String sortStr = list.get(i).getSortLetters();
                char firstChar = sortStr.toUpperCase().charAt(0);
                if (firstChar == section) {
                    return i;
                }
            }
    
            return -1;
    
        }
    
        @Override
        public int getSectionForPosition(int position) {
    
            return list.get(position).getSortLetters().toUpperCase().charAt(0);
        }
    }

    适配器里的xml布局

    <?xml version="1.0" encoding="utf-8"?>
    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="vertical">
    
    
        <TextView
            android:id="@+id/catalog"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#F9F9F9"
            android:paddingBottom="5dp"
            android:paddingLeft="20dp"
            android:paddingTop="5dp"
            android:text="A"
            android:textColor="#454545" />
    
    <!--
    
        <TextView
    
            android:id="@+id/line"
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:background="@color/green_light" />
    -->
    
    
        <LinearLayout
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:background="@color/white"
            android:orientation="horizontal"
            android:paddingBottom="5dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="5dp">
    
    
            <ImageView
                android:id="@+id/book_head"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:src="@color/green_light" />
    
    
            <TextView
                android:id="@+id/book_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dip"
                android:ellipsize="end"
                android:gravity="center_vertical"
                android:singleLine="true"
                android:text="xxxx"
                android:textColor="#323232"
                android:textSize="16sp" />
    
        </LinearLayout>
    
    
    </LinearLayout>

    3.实现右侧的字母导航

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.drawable.ColorDrawable;
    import android.support.annotation.Nullable;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.TextView;
    
    /**
     *  2018/4/16.
     * 侧边栏 SideBar
     */
    
    public class SideBar extends View {
    
        //触摸事件(用的接口回调)
        private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
    
        //26个字母
        public static String[] b = {"A", "B", "C", "D", "E", "F", "G", "H", "I",
                "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
                "W", "X", "Y", "Z", "#"};
    
    
        private int choose = -1;// 选中
        private TextView mTextDialog;
    
        public void setTextView(TextView mTextDialog) {
            this.mTextDialog = mTextDialog;
        }
    
        public SideBar(Context context) {
            super(context);
        }
    
        public SideBar(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public SideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Paint paint = new Paint();
            int height = getHeight();//获取高度
            int width = getWidth();//获取宽度
            int singleHeight = height / b.length;//获取每一个字母的高度
    
            for (int i = 0; i < b.length; i++) {
                paint.setColor(Color.parseColor("#838383"));//未选中的颜色
                paint.setTextSize(30);
                paint.setAntiAlias(true);//抗锯齿功能
                // 选中的状态
                if (i == choose) {
                    paint.setColor(Color.BLACK);//选中的颜色
                    paint.setFakeBoldText(false); //true为粗体,false为非粗体            }
                }
                // x坐标等于中间-字符串宽度的一半.
                float xPos = width / 2 - paint.measureText(b[i]) / 2;
                float yPos = singleHeight * i + singleHeight;
                canvas.drawText(b[i], xPos, yPos, paint);
                paint.reset();// 重置画笔
    
    
            }
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            final int action = event.getAction();
            final float y = event.getY();// 点击y坐标
            final int oldChoose = choose;
            final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
            final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
    
            switch (action) {
                case MotionEvent.ACTION_UP:
                    setBackgroundDrawable(new ColorDrawable(0x00000000));
                    choose = -1;//
                    invalidate();
                    if (mTextDialog != null) {
                        mTextDialog.setVisibility(View.INVISIBLE);
                    }
    
                    break;
    
                default:
                    setBackgroundColor(Color.TRANSPARENT);
                    if (oldChoose != c) {  //判断选中字母是否发生改变
                        if (c >= 0 && c < b.length) {
                            if (listener != null) {
                                listener.onTouchingLetterChangedListener(b[c]);
                            }
                            if (mTextDialog != null) {
                                mTextDialog.setText(b[c]);
                                mTextDialog.setVisibility(View.VISIBLE);
                            }
    
                            choose = c;
                            invalidate();
                        }
                    }
    
                    break;
            }
    
            return true;
        }
    
        public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
            this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
        }
    
        public interface OnTouchingLetterChangedListener {
            void onTouchingLetterChangedListener(String s);
        }
    }
    

    在设置数据的页面把SideBar和Dialog绑定再一起,然后初始化监听

      protected void initView() {
    //        把SideBar和Dialog绑定
            mSideBar.setTextView(mDialog);
    
    
            mSideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {
                @Override
                public void onTouchingLetterChangedListener(String s) {
    
                    // 该字母首次出现的位置
                    int position = adapter.getPositionForSection(s.charAt(0));
                    if (position != -1) {
                        mListView.setSelection(position);
                    }
    
                }
            });
        }
    展开全文
  • 本篇文章主要介绍了android仿微信通讯录搜索示例(匹配拼音,字母,索引位置),具有一定的参考价值,有兴趣的可以了解一下
  • 高防微信通讯录,加搜索联系人,右侧分组手触摸滑动分区,左侧会有放大提示效果
  • 以前写过一个自定义View,仿微信通讯录列表侧边栏,文章在:Android 仿微信通讯录列表侧边栏 最近又需要使用到它了,就又重新看了一遍代码,修复了几个小bug 而且,既然说的是仿微信,就索性把布局什么的就按照微信...

    以前写过一个自定义View,仿微信通讯录列表侧边栏,文章在:Android 仿微信通讯录列表侧边栏

    最近又需要使用到它了,就又重新看了一遍代码,修复了几个小bug
    而且,既然说的是仿微信,就索性把布局什么的就按照微信的风格来设计
    效果图如下所示


    img_2df47d620e576dd96ee8c186b0b24443.gif
    这里写图片描述

    设计思路可以看我上面给的文章链接,思路挺简单的,大致流程都一样,就修改了一些小地方,这里就不再重复讲了

    这里提供代码下载:Android 仿微信通讯录列表侧边栏

    展开全文
  • 【Android 仿微信通讯录 导航分组列表-上】使用ItemDecoration为RecyclerView打造带悬停头部的分组列表,修改bug版本.zip 【Android 仿微信通讯录 导航分组列表-上】使用ItemDecoration为RecyclerView打造带悬停头部...
  • Android 自定义 View 实现通讯录字母索引(仿微信通讯录) 标签: 自定义View索引悬浮层 2015-02-12 21:30 3083人阅读 评论(1) 收藏 举报  分类: 仿微信(1)  版权声明:本文为博主...

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

    标签: 自定义View索引悬浮层
      3083人阅读  评论(1)  收藏  举报
      分类:

    一、效果:我们看到很多软件的通讯录在右侧都有一个字母索引功能,像微信,小米通讯录,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));
        }
       
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

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

        /**
         * 测量本身的大小,这里只是测量宽度
         * @param widthMeaSpec 传入父View的测量标准
         * @return 测量的宽度
         */
        private int measureWidth(int widthMeaSpec){
            /*定义view的宽度*/
            int width ;
            /*获取当前 View的测量模式*/
            int mode = MeasureSpec.getMode(widthMeaSpec) ;
            /*
            * 获取当前View的测量值,这里得到的只是初步的值,
            * 我们还需根据测量模式来确定我们期望的大小
            * */
            int size = MeasureSpec.getSize(widthMeaSpec) ;
            /*
            * 如果,模式为精确模式
            * 当前View的宽度,就是我们
            * 的size ;
            * */
            if(mode == MeasureSpec.EXACTLY){
                width = size ;
            }else {
                /*否则的话我们就需要结合padding的值来确定*/
                int desire = size + getPaddingLeft() + getPaddingRight() ;
                if(mode == MeasureSpec.AT_MOST){
                    width = Math.min(desire,size) ;
                }else {
                    width = desire ;
                }
            }
            mViewWidth = width ;
            return width ;
        }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

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

    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();
            }
        }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    我来讲一下 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;
        }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

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

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

        /*定义一个回调接口*/
        public interface OnIndexSelectListener{
            /*返回选中的位置,和对应的索引名*/
            void  onItemSelect(int position, String value) ;
        }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    回调接口我们放在哪里调用呢,当我们手指按下的时候,这时候其实我们需要确定我们按下的是哪个索引,滑动的时候也是一样,所以,这个没什么好商量的,直接放在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);
            }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    selectItem(int)方法中就是执行的回调方法。 
    5、实现悬浮框显示已经选中的索引内容 
    这里需要用到 WindowManager 容器,然需要现实的 View 附在这上面的就行,当手指按下的时候,让 View 显示出来,松开不显示就行了

            /*设置浮动选中的索引*/
            /*获取windowManager*/
            mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
            /*overly 视图,通过LayoutInflater 获取*/
            mFloatView = LayoutInflater.from(getContext()).inflate(R.layout.overlay_indexview,null) ;
            /*开始让其不可见*/
            mFloatView.setVisibility(INVISIBLE);
            /*转换 高度 和宽度为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);
                }
            }) ;
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    同样的道理,如果需要改变显示的内容,就需要在调用回调的位置,为 View 中的 TextView 设置当前的索引内容。 
    好了此 View 的代码就这么多, 
    接下来就把引用他的 Xml 和浮动 View 的 Xml 也贴出来,

    引用的布局文件

        <moon.wechat.view.IndexView
            android:layout_width="25dp"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"/>
       
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    浮动 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>
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    浮动 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>
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    最后就是源码下载地址:在这里

    展开全文
  • 仿微信通讯录列表

    2014-08-19 15:44:16
    这是一个简单的Demo,因为字母排序的缘故,想让listview随字母侧边栏拖动,所有只能有一个listview,这里提供实现将两个listview组合起来,上面是群组管理,下面是通讯录联系人排序

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,380
精华内容 952
关键字:

仿微信通讯录