您的位置:首页 > 移动开发 > Android开发

Android从零开始之一步一步教你实现联系人功能(一)

2016-07-10 14:52 633 查看
在最近的项目中有这样的一个需求,就是要实现类似联系人的列表,包含模糊查询、按照A到Z拼音首字母分组排序、和收藏功能。参考了一下网上的例子,我觉得还是自己亲自操刀来实现所有的功能。今天带领大家先实现联系人右边的侧边栏【A~Z】。先上一张图:



可以看到,右边是一个A到Z的侧边菜单导航栏,当我们点击右边侧边菜单导航栏时,中间显示当前点击item。相信这个UI对大家都很熟悉。很多APP都有这样的界面。最典型的就是通讯录。

新建一个类,名字叫做SiderBarMenu并且继承View,按照自定义view的步骤。先实现它的三个构造方法。如下:

public SideBarMenu(Context context)
{
this(context, null);
}

public SideBarMenu(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}

public SideBarMenu(Context context, AttributeSet attrs, int style)
{
super(context, attrs, style);
init();
}


private void init()
{
mSideBarMenuPaint = new Paint();
//设置画笔颜色
mSideBarMenuPaint.setColor(Color.RED);
//设置字体大小
mSideBarMenuPaint.setTextSize(30);
//设置字体
mSideBarMenuPaint.setTypeface(Typeface.DEFAULT_BOLD);
}


在含有三个构造方法定义一个初始化方法,用于初始化一些我们后面需要用到的变量等。这儿我们初始化Paint(画笔)的实例,以及设置画笔的颜色、字体大小、字体。在这之前我们先定义下我们需要用到的变量:

//画笔
private Paint mSideBarMenuPaint;
//定义一个用户点击item标识
private int click = -1;
//侧边导航栏的文字
private String[] SIDEBAR = {"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"};
//显示tips的控件
private TextView mTvTips;


完成这些之后,我们就要开始画我们的侧边栏菜单了,首先重写View的onDraw()方法,如下:

@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
//获取控件的宽、高度,即你在布局文件当中设置的:layout_width、layout_height两个的值;
int width = getWidth();
int height = getHeight();
//每个Item高度
int SideBarItemHeight = height / SIDEBAR.length;

for (int i = 0; i < SIDEBAR.length; i++)
{
//计算我们要画文字的X坐标,计算公式:控件宽度/2-文字宽度/2  目的:文字水平方向居中
float xPos = width / 2 - mSideBarMenuPaint.measureText(SIDEBAR[i]) / 2;
//计算我们要画文字的Y坐标,计算公式:控件高度*当前项数+控件高度/2  目的:文字垂直方向居中
float yPos = SideBarItemHeight * i + SideBarItemHeight / 2;
//画出侧边导航栏
canvas.drawText(SIDEBAR[i], xPos, yPos, mSideBarMenuPaint);
//重置画笔,如果重置画笔,则必须重新设置画笔属性
//mSideBarMenuPaint.reset();
}
}


首先,我们要获取到我们在布局文件当中的宽、高。然后算出每一个item的高度。之后在算出每一个item的X、Y坐标。之后调用canvas.drawText()方法绘制我们的侧边栏,这儿我注释了一个reset()方法,如果调用它我们就需要每次在循环里面重新设置paint的属性,因为前面我在init()方法中设置过,所以我把这个方法注释掉了。而且考虑到后面也没有拿这个画笔做其他操作。这时候我们运行程序应该可以到侧边栏已经绘制成功了。

接下来就是处理触摸事件了。我们需要重写dispatchTouchEvent()方法。来手动处理触摸事件。

/**
* 手动处理触摸事件
*
* @param event
* @return
*/
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
//获取触摸事件:ACTION_DOWN、ACTION_MOVE、ACTION_UP
int action = event.getAction();
//获取触摸的Y坐标
float yPos = event.getY();
//判断点击的是那一个item。计算公式:触摸的Y坐标/控件高度*侧边导航栏item总数。
int pos = (int) (yPos / getHeight() * SIDEBAR.length);
//记录之前用户点击的item
int oldClick = click;

//处理触摸事件,up事件单独处理,其他(ACTION_DOWN、ACTION_MOVE)在default中去处理。
switch (action)
{
case MotionEvent.ACTION_UP:
//复位
click = -1;
if (mTvTips != null)
{
mTvTips.setVisibility(View.GONE);
}
invalidate();
break;
default:
if (oldClick != pos)
{
if (pos > 0 && pos < SIDEBAR.length)
{
if (mTvTips != null)
{
mTvTips.setText(SIDEBAR[pos]);
mTvTips.setVisibility(View.VISIBLE);
}
click = pos;
//通知View树重绘,主线程用:invalidate(),非主线程用:postInvalidate();
invalidate();
}
}
break;
}

return true;
}


这儿代码稍稍长一点,我从上到下给解释下,首先我们要通过event.getAction()方法拿到用户的触摸事件,之后在通过event.getY()方法获取用户触摸的Y坐标。拿到Y坐标之后,我们就可以判断用户当前触摸的哪一个item。计算公式:触摸的Y坐标/控件高度*侧边导航栏item总数。不知道大家能理解到这个公式不,理解不到自己用本子算吧。或者找个六年纪一下的同学帮你算。哈哈!然后定义一个变量oldClick来保存用户之前点击的位置。

完成上面的操作之后,我们就开始判断用户的触摸事件了,这儿我们将ACTION_UP事件单独处理,因为ACTION_DOWN、ACTION_MOVE的处理逻辑一样,所以我放到了default里面,

ACTION_UP:

我们需要处理当用户抬手之后隐藏TextView并且将click恢复默认值,不然当你重复点击同一个item是没有效果的。

ACTION_DOWN&ACTION_MOVE:

首先判断之前点击的item位置和现在的位置是否一样,如果不一样,再判断当前位置是否越界,之后设置要显示的内容并且将TextView设置为可见,之后将当前位置重新赋值,并且通知View树重绘。

最后我们再向外抛一个设置TextView的方法。

public void setTextView(TextView tips)
{
this.mTvTips = tips;
}


现在在我们布局文件中使用:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="right">

<com.poisonh.contacts.widgets.SideBarMenu
android:id="@+id/sbm_siderbarmenu"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"/>

<TextView
android:id="@+id/tv_tips"
android:layout_width="50dp"
android:layout_height="50dp"
android:visibility="gone"
android:layout_centerInParent="true"
android:background="@drawable/shape_tips_bg"
android:gravity="center"
android:text="H"
android:textColor="#fff"/>

</RelativeLayout>


最后在MainActivity中使用:

public class MainActivity extends AppCompatActivity
{
private SideBarMenu mSiderBarMenu;
private TextView mTvTips;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//setClickListener();
}

private void initView()
{
mSiderBarMenu = (SideBarMenu) findViewById(R.id.sbm_siderbarmenu);
mTvTips = (TextView) findViewById(R.id.tv_tips);
mSiderBarMenu.setTextView(mTvTips);
}
}


运行程序,你就可以看到文章开头的效果了。源码地址:https://github.com/PoisonH/Contacts
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息