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

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

既然是仿,那么我们来看看源微信通讯录是个什么样子什么功能以及我们实现后的效果,如下图所示:


下面我们就来一步一步剖析这个功能实现及其思路。


1.分析界面的构成


界面由上左右中四部分构成,控件分别为:


Ⅰ上为EditText输入文本框。


Ⅱ左为ListView。


Ⅲ右为自定义控件。


Ⅳ中为一个隐藏的TextView,当点击右侧自定义控件的字母时,将隐藏的TextView显示出来。


左右中三控件使用什么布局才能达到如此效果?使用LinearLayout显然不可能完成,TextView无法设置在某个控件之上,设置为RelativeLayout需要设置许多参数才能达到上面的效果,那么FrameLayout呢?


FrameLayout是最简单的布局了。所有放在布局里的控件,都按照层次堆叠在屏幕的左上角。后加进来的控件覆盖前面的控件。在FrameLayout布局里,定义任何空间的位置相关的属性都毫无意义。控件自动的堆放在左上角,根本不听你的控制。


当设置为FrameLayout层叠的控件问题解决了,当设置android:layout_gravity="right"时,自定义控件自动就水平居右了,当设置android:gravity="center"中间的TextView就居中了,不像RelativeLayout还要设置什么控件在什么控件的左过或者右边等复杂的属性。


当了解这些后,我们的布局文件也可形成了,代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:orientation="vertical">
    <EditText
        android:id="@+id/searchEdit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/search_frame" />
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ListView
            android:id="@+id/myList"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/dialogString"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_gravity="center"
            android:textSize="50sp"
            android:visibility="invisible"
            android:background="#54FF9F"
            android:textColor="#8B1A1A"
            android:gravity="center"/>
        <com.example.liyuanjing.addressbook.RightView
            android:id="@+id/rightView"
            android:layout_width="20dp"
            android:layout_height="match_parent"
            android:layout_gravity="right" />
    </FrameLayout>
</LinearLayout>


这里的两个属性要说明一下:


㈠.android:focusableInTouchMode:顾名思义,让activity能获取用户焦点


㈡.android:focusable:获取用户焦点


使用这两个属性,是为了防止启动APP后立即弹出输入法。这里的解决思路就是让其他不能弹出输入法的焦点获取焦点,这样就不会启动时弹出输入法了。


2.实现自定义控件RightView


①思路


界面思路:从上面截图可以看出来,这是一个竖立的控件,字母也是竖立的写的,那么我们可以设置它的宽度很小,高度为除上面EditText外的高度,字母根据高度除26等于每个字母的长度。


响应点击事件思路:根据字母所占的位置高度,来确定控件点击了哪个字母。得到字母后,通过设置回调函数更新ListView的显示。并且设置TextView的值及显示和隐藏。


②具体的实现


Ⅰ首先我们定义RightView类继承自View


public class RightView extends View {
    public RightView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}


因为在上面的布局文件中设置了属性,所以需要带有AttributeSet参数的构造方法。


Ⅱ定义TextView


当自定义控件接收到触摸事件的时候,需要设置中间TextView的值,并且还要设置其隐藏还是显示。故代码如下:


private TextView mdialog;
public void setMdialog(TextView mdialog) {
    this.mdialog = mdialog;
}

Ⅲ绘制控件


重写onDraw()方法来绘制控件,代码如下:

private String[] chars = {"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 Paint paint;
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    this.paint = new Paint();//创建一个画笔
    int x = getWidth();//获取控件的宽度
    int y = getHeight();//获取控件的高度
    int singleHeight = y / chars.length;//获取每个字母的高度
    for (int i = 0; i < chars.length; i++) {
        this.paint.setColor(Color.BLACK);//设置画笔的颜色为黑色
        this.paint.setTextSize(20.0f);//设置字体的大小为20f
        canvas.drawText(chars[i], 10, singleHeight * (i + 1), paint);//画字符到控件上
    }
}


在上面的布局文件中我们设置了设置为match_parent,宽度为20dp。那么这里的getWidth()和getHeight()获取的就是设置自定义控件在屏幕上占有的宽度和高度。


Canvas是画布,你可以理解为一张纸,Paint是画笔,可以理解为在纸上作画的那支笔,有了这两个,才能画画。才能在屏幕上画控件。


drawText为画文本:


第一个参数为要画的文本。


第二个参数为文本在控件的X坐标。


第三个参数为文本在控件的Y坐标。


第四个参数为画笔。


如下图,假设文本占整个矩形框,坐标为文本左上角的坐标:


image.png


现在运行程序,得到如下图所示:


2.png


当然没有红色,这为后面加上去的。


Ⅳ创建接口


当中间TextView内容改变的时候,为了能通知ListView作出相应的变化,需要创建一个回调接口,以便通知ListView。让ListView作出响应。

private OnTextViewChange changelistener;
public interface OnTextViewChange {
    void onTextChange(String s);
}
public void setOnTextViewChange(OnTextViewChange change) {
    this.changelistener = change;
}

Ⅴ监听触摸事件


@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    float x = (int) event.getX();//获取触摸到控件上的X坐标值
   float y = (int) event.getY();//获致触摸到控件上的Y坐标值
    switch (event.getAction()) {//判断触摸事件的类型
        case MotionEvent.ACTION_DOWN: {//当类型为按下
            setBackgroundColor(Color.RED);//设置控件的背景
            if (this.mdialog.getVisibility() == View.INVISIBLE) {//当TextView为隐藏
                int vi = (int) ((y / (float) getHeight()) * (float) chars.length);//获取具体按下哪个字母
                this.mdialog.setText(chars[vi]);//设置弹出文本
                this.mdialog.setVisibility(View.VISIBLE);//显示控件
                this.changelistener.onTextChange(this.mdialog.getText().toString());//通知ListView
            }
            break;
        }
        case MotionEvent.ACTION_UP://当类型为抬起
            setBackgroundColor(Color.WHITE);//设置背景
            if (this.mdialog.getVisibility() == View.VISIBLE) {//判断TextView是否为显示
                this.mdialog.setText("");//设置文本为空
                this.mdialog.setVisibility(View.INVISIBLE);//当手指离开控件,隐藏TextView
            }
            break;
        case MotionEvent.ACTION_MOVE: {//当类型为移动
            int vi = (int) ((y / (float) getHeight()) * (float) chars.length);获取具体按下哪个字母
            this.mdialog.setText(chars[vi]);设置弹出文本
            this.changelistener.onTextChange(this.mdialog.getText().toString());//通知ListView
            break;
        }
        default:
            break;
    }
    return true;
}


可以看到,代码按下和移动事件有重复的代码,这里你可以提取出来,为了方便理解,我将此写到了一起。


获取具体按到哪个字母的公式为((y/(float)getHeight)*(float)chars.length)。这里先计算高度占有的比例,然后*26就是具体的字母。当然用了许多强转类型,防止为int后丢失精度。


每次变化坐标都设置一次文本通知ListView。

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