仿微信通讯录滑动定位ListView功能(二)

简介: 仿微信通讯录滑动定位ListView功能(二)

3.ListView设计


从上面的截图来看,这个ListView在每个最先出现的字母上多了一个字母编号,这是怎么实现的呢?


答案就是当是第一次出现某个字母的时候显示首字母,当不是第一个显示的时候隐藏首字母。


也就是ListView里面有两个TextView,一个用来显示首字母,一个用来显示名字,当不是首次出现的字母时,隐藏第一个TextView。这样这个 效果就实现了。


下面我们就来实现我们的ListView。


Ⅰ首先实现联系人信息类MessageItem


它有两个属性,一个字母,一个名字,代码如下:


public class MessageItem {
    public String firstChar;
    public String name;
}


Ⅱ实现ListView的适配器


还要用我们常用的BaseAdapter,代码如下:


private List<MessageItem> nameList = new ArrayList<>();
private class NameAdapter extends BaseAdapter {
    private LayoutInflater inflater;
    NameAdapter() {
        super();
        this.inflater = getLayoutInflater();
    }
    @Override
    public int getCount() {
        return nameList.size();
    }
    @Override
    public Object getItem(int position) {
        return nameList.get(position);
    }
    @Override
    public long getItemId(int position) {
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        View view = convertView;
        if (view == null) {
            view = this.inflater.inflate(R.layout.list_item, null);
            holder = new ViewHolder(view);
            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }
        MessageItem item = nameList.get(position);
        holder.name.setText(item.name);
        if (item.firstChar != null) {//如果有首字母
            holder.title.setText(item.firstChar);//设置其首字母
            holder.title.setVisibility(View.VISIBLE);//显示TextView
        } else {
            holder.title.setVisibility(View.GONE);//隐藏TextView
        }
        return view;
    }
}
public class ViewHolder {
    public TextView title;
    public TextView name;
    public ViewHolder(View view) {
        this.title = (TextView) view.findViewById(R.id.title);
        this.name = (TextView) view.findViewById(R.id.name);
    }
}

需要讲解View.GONE与View.INVISIBLE,两样是隐藏,前一个隐藏后不占位置,后一个隐藏后会占位置。但都不会显示。


其他都是最基本的Android知识,这里不作过多的描述,如果看不懂,请认真学习Android基础在来。


Ⅲ排序联系人,确立首字母


我偷了一个小懒,不排序联系人,直接给了排序好的联系人如下:


private String[] name = {"aimengyuan", "aili", "bibo", "bbmb", "caonima", "changjiang", "debug", "eoog", "fengxinyao", "git", "hefan", "inne", "ppoppo", "renmingbi", "xinxin", "you", "zzzzzzz"};


这里之所以不用汉字,是因为汉字排序的工具类,我没有下载,你可以去下载后使用,这里具体讲解功能实现,排序汉字不是本章重点。原谅我偷懒一下。


现在我们假设我们有了排序好的联系人。那么怎么设置首字母在该显示的地方显示,不该显示的地方不显示呢?


代码如下:

private int[] charFlag = new int[26];//设置标志符,当设置了某个字母的首字母后,标志为1
public void initView() {
    for (int i = 0; i < name.length; i++) {
        MessageItem item = new MessageItem();//创建一个联系人
        item.name = name[i];//获取它的名字,如果是汉字,获取他对应的拼音
        int ascii = (int) name[i].charAt(0);//获取名字首字母,ASCII编码
        for (int j = 0; j < 26; j++) {//遍历标志符
            int flag = (int) (ascii - 97);
            if (flag == j) {//如果是小写字母
                if (charFlag[j] != 1) {//如果该小写字母不等于1
                    item.firstChar = String.valueOf(((char) (j + 65)));//设置其首字母
                    charFlag[j] = 1;//将标志符设置为1,表示该字母有首字母在出现这个字母,不设置其首字母。
                }
            }
        }
        this.nameList.add(item);//添加联系人
    }
    this.adapter = new NameAdapter();
    this.mListView.setAdapter(this.adapter);//设置适配器
}


小写字母a~z,ASCII编码为:97到122


大写字母A~Z,ASCII编码为:65到90


这里减去97就是让其在26之内,好作判断之用。


字符强转会变为ASCII编码,int强转也会成为字符。


ⅣMianActivity初始化


代码如下:

private RightView rightView;
private EditText editText;
private TextView dialogString;
private ListView mListView;
private NameAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    this.rightView = (RightView) findViewById(R.id.rightView);
    this.editText = (EditText) findViewById(R.id.searchEdit);
    this.dialogString = (TextView) findViewById(R.id.dialogString);
    this.mListView = (ListView) findViewById(R.id.myList);
    this.rightView.setMdialog(this.dialogString);
    this.rightView.setOnTextViewChange(this);
    initView();
}


Ⅴ实现自定义控件回调接口


代码如下:

@Override
public void onTextChange(String s) {
    for (int i = 0; i < nameList.size(); i++) {
        MessageItem item = nameList.get(i);//获取item信息
        if (item.firstChar != null && item.firstChar.equals(s)) {//判断首字母不为空,并且首字母与弹出TextView字符串相等
            final int finalI = i;
            mListView.post(new Runnable() {
                @Override
                public void run() {
                    mListView.requestFocusFromTouch();//获取焦点
                    mListView.setSelection(finalI);//跳转到该首字母的item
                }
            });
            adapter.notifyDataSetChanged();//更新ListView
        }
    }
}


为什么ListView不直接调用run中的方法,而是使用post,原因有2:


原因一:界面初始化完成之后listview失去了焦点


原因二:因为listview的item高度不一致,setSelection无法准确定位。


这样更新UI,不会阻塞。


最终的运行效果如下所示:


3.png


4.最后的漏洞


如图所示:

5.png


当输入法出现后,会挤压自定义控件,这个问题很是苦恼,经过百度多篇文章后,提到如下方法在AndroidManifest.xml的该Activity控件下设置如下属性:

android:windowSoftInputMode="stateAlwaysHidden|adjustPan"


就可以完美解决上面的漏洞。


该属性的参数详情如下:


【A】stateUnspecified:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置


【B】stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示


【C】stateHidden:用户选择activity时,软键盘总是被隐藏


【D】stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘也总是被隐藏的


【E】stateVisible:软键盘通常是可见的


【F】stateAlwaysVisible:用户选择activity时,软键盘总是显示的状态


【G】adjustUnspecified:默认设置,通常由系统自行决定是隐藏还是显示


【H】adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间


【I】adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分

相关文章
|
3月前
|
存储 自然语言处理 小程序
微信小程序多语言切换神器:简繁体切换功能完全指南
随着全球化的发展,支持多种语言的应用程序愈发重要。本文介绍了如何在微信小程序中实现简体与繁体字体之间的切换功能,以满足不同地区用户的需求。通过创建utils文件夹并编写相应的转换函数,开发者可以方便地实现语言切换,从而提升用户体验。文章中还附带了示例代码和效果图,帮助读者更好地理解和应用这一功能。
135 0
微信小程序多语言切换神器:简繁体切换功能完全指南
|
4月前
|
算法 JavaScript 前端开发
切西瓜法实现微信抢红包功能
该文章介绍了使用“切西瓜法”和“栅栏法”两种算法来模拟微信抢红包的随机分配机制,并通过具体的JavaScript代码实现了红包金额的公平随机分配过程。
切西瓜法实现微信抢红包功能
|
4月前
|
人工智能 前端开发 JavaScript
MacTalk 测评通义灵码,实现“微信表情”小功能
墨问西东创始人池建强分享了团队使用通义灵码的经验。
|
4月前
|
小程序 API 开发工具
使用python 实现微信签到提醒功能
【9月更文挑战第4天】使用python 实现微信签到提醒功能
97 2
|
5月前
|
Web App开发 缓存 小程序
【Azure API 管理】从微信小程序访问APIM出现200空响应的问题中发现CORS的属性[terminate-unmatched-request]功能
【Azure API 管理】从微信小程序访问APIM出现200空响应的问题中发现CORS的属性[terminate-unmatched-request]功能
|
5月前
|
小程序 前端开发 开发者
|
5月前
|
小程序 前端开发 API
Ant Design Mini 问题之在微信小程序中,由于不支持slot特性,Ant Design Mini的什么组件功能受到了限制,如何解决
Ant Design Mini 问题之在微信小程序中,由于不支持slot特性,Ant Design Mini的什么组件功能受到了限制,如何解决
135 1
|
3月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
832 7
|
3月前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
855 1
|
3月前
|
小程序 前端开发 测试技术
微信小程序的开发完整流程是什么?
微信小程序的开发完整流程是什么?
209 7