通过之前的了解我们已经能够简单的自定义我们想要的控件,但是不能实现与控件的交互,今天就简单的说说自定义控件关于用户交互与点击事件监听。
如图,今天主要实现状态更新的监听,以及点击上图中的图片和文字将对应的状态显示到点击的进度两个功能。
类似于Button的点击事件,通过setOnClickListener()方法设置监听,将监听类传入控件。而在Button类中,有一个内部接口OnClickListener以及一个OnClickListener对象参数通过setOnClickListener方法设置,具体可以去看Button的源码,下面模仿Button设置监听事件,步骤如下:
1.View中,创建一个状态改变的监听类OnEndNodeChangedListener;
2.View中,将监听类声明为成员变量;
3.View中,使用setOnEndNodeChangedListener()方法为成员变量赋值;
4.调用处,通过setOnEndNodeChangedListener()方法为View添加监听。
自定义View中:
<span style="font-size:14px;"> /* 监听器 */
private OnEndNodeChangedListener listener;
/**
* 设置当前节点编号改变监听事件
*/
public void setOnEndNodeChangedListener(OnEndNodeChangedListener listener) {
this.listener = listener;
}
/**
* 监听事件
*/
public interface OnEndNodeChangedListener {
void onEndNodeChanged(int node, int totalNode);
}</span>
调用处,Activity中:
<span style="font-size:14px;"> statusBar1.setOnEndNodeChangedListener(new StatusBar.OnEndNodeChangedListener() {
@Override
public void onEndNodeChanged(int node, int totalNode) {
Toast.makeText(MainActivity.this, "点击了状态" + node, Toast.LENGTH_SHORT).show();
}
});</span>
效果展示:更改状态后弹出土司。
如图所示能够实现对于状态状态改变的监听。
但是,如果我想点击状态三就能跳到状态三该如何实现呢?
对于点击事件必须重写onTouchEvent()方法,获得一个MotionEvent动作事件进行判断处理,代码如下:
<span style="font-size:14px;"> @Override
public boolean onTouchEvent(MotionEvent event) {
// 根据点击动作进行判断
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_DOWN:
// 获取点击的位置坐标
float x = event.getX();
float y = event.getY();
// 判断是否点击在状态图标
for (int i = 0; i < nodeNumber; i++) {
if (x > (0 + i * padding + mImgWidth * i + (mTextBounds.right - mTextBounds.left) / 2)
&& x < (mImgWidth + i * padding + mImgWidth * i+ (mTextBounds.right - mTextBounds.left) / 2)
&& y > 0 && y < (mImgHeight + 20 + mTextHeight)) {
setEndNode(i + 1); // 重设当前点
Log.i("info", "onTouchEvent: ======x:"+ x);
invalidate(); // 重绘图形
}
}
break;
case MotionEvent.ACTION_UP:
break;
}
// 必须调用
return super.onTouchEvent(event);
}</span>
主要思想就是通过获得点击按下的位置,进行判定。如果该点处于状态图片以及文字区域的整个矩形框内,将当前状态点设置为选中状态;如果该点处于空白位置或者是中间的连接线位置,就不对本次的点击事件进行处理。
这里值得注意的是 invalidate()方法,调用之后会重新调用onDraw()方法,对整个控件进行重新绘制。
同时一定要在之后调用父类的这个方法,处理事件分发传递。
自定义控件的整个过程到此完结,很多不足希望大家斧正。
最后跟上这个Demo的GitHub地址:GitHub简单自定义View Demo地址