Android自定义TableView (三) 扩展 - 事件

本篇给TableView添加几个事件处理,简单来说分为两种:整行(item)响应事件和单元格响应事件(两者互斥),考虑不响应任何事件的话就是三种,如下:

  1. 不响应事件(默认)
  2. item响应事件:点击、长按
  3. 单元格响应事件:点击、点击+选中

其他情况(比如item可以响应事件同时某一列单元格也可以响应事件)有需要的话可以根据本篇的思路自行扩展。

明确需求(上面列出的3点)之后,再理一下整体的实现思路,第1点什么都不用做,第2点很简单,注册ListView的item点击和长按事件即可,第3点也很简单,就是item里面的每个view注册点击事件(都是原生view自带的事件)。

1.首先根据3点需求定义3种模式

public static final int MODE_NONE_EVENT = 0; //不处理任何事件
public static final int MODE_ITEM_EVENT = 1; //item处理事件
public static final int MODE_ALL_UNIT_EVENT = 2; //所有单元格处理事件
public static final int MODE_EITHER_UNIT_EVENT = 3; //某列单元格处理事件
// 上面的 MODE_ALL_UNIT_EVENT 和 MODE_EITHER_UNIT_EVENT 算一种

2.定义一个变量表示当前事件模式

private int mEventMode;

3.在适当的地方判断当前模式,注册相应的事件

// item处理事件
if (mEventMode == MODE_ITEM_EVENT) { 
    mContentListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // item点击事件
        }
    });
    mContentListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            //item长按事件
            return true;
        }
    });
}

//单元格处理事件,在getView里面
if (mEventMode == MODE_ALL_UNIT_EVENT || mEventMode == MODE_EITHER_UNIT_EVENT) {
    Point coordinate = new Point(i, position); //column=x, row=y
    childView.setTag(coordinate); //记录单元格坐标
    childView.setOnTouchListener(touchListener); //这里使用OnTouch实现点击,不用OnClick
}
3.1 解释一下上面单元格处理事件的一些东西

(1)使用OnTouch而不使用OnClick是因为方便设置单元格点击时按下状态的颜色变化
(2)注册事件是在Adapter的getView方法里面,所以不要使用局部匿名类的方式注册,避免频繁创建对象,上面代码参数touchListener是在getView方法之外定义的成员匿名类,代码如下

private View.OnTouchListener touchListener = new OnTouchListener() {

    private boolean isContainsUnit = false;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (mIsUnitSelectable) {
                Point coordinate = (Point) v.getTag(); //获取单元格坐标
                isContainsUnit = mUnitSelectedMap.containsKey(coordinate);
                int color = isContainsUnit ? mUnitBackColor : mUnitSelectedColor;
                v.setBackgroundColor(color);
            } else {
                v.setBackgroundColor(mUnitDownColor);
            }
        } else if (event.getAction() == MotionEvent.ACTION_UP) {       // UP的时候处理点击事件
            Point coordinate = (Point) v.getTag();
            if (mUnitClickListener != null) {
                mUnitClickListener.onUnitClick(coordinate.y, coordinate.x, getRowData(coordinate.y)[coordinate.x]);
            }
            if (mIsUnitSelectable) {
                if (isContainsUnit) {
                    mUnitSelectedMap.remove(coordinate);
                } else {
                    mUnitSelectedMap.put(coordinate, getRowData(coordinate.y)[coordinate.x]);
                }
            } else {
                v.setBackgroundColor(mUnitBackColor);
            }
        } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
            if (mIsUnitSelectable) {
                int color = isContainsUnit ? mUnitSelectedColor : mUnitBackColor;
                v.setBackgroundColor(color);
            } else {
                v.setBackgroundColor(mUnitBackColor);
            }
        }
        return true;
    }
};

touchListener里面实现了点击和选中的逻辑。

(3)因为不使用局部匿名类的方式注册,所以touchListener里面不能直接取得单元格view的行列坐标,这里利用了view的Tag实现坐标的记录与获取

4.实现自己的回调

上面3注册回调事件之后已经可以响应相应的事件了,但是原生的回调并不能完美满足需求。看图

注册回调示例

上图说明了为什么要定义一个自己的回调,同时也展示了TableView最终对外提供注册单元格点击事件的方法的使用。

4.1 如何实现自己的回调(掌握回调的就不用看了,实现上图的效果就行)
// 1.首先定义一个回调接口
public interface OnUnitClickListener {
    void onUnitClick(int row, int column, String unitText);
}

// 2.然后定义一个接口对象
private OnUnitClickListener mUnitClickListener;

// 3.在适当的地方调用接口里面的函数,并把相应的参数传进去(适当的地方在 3.1 的代码里)
mUnitClickListener.onUnitClick(row, column, unitText);

// 4.对外提供一个注册回调的方法
public void setOnUnitClickListener(OnUnitClickListener listener) {
    mUnitClickListener = listener;
}

// 5.像4的代码截图里面那样使用

5.补充

在注册回调的时候需要设置相应的事件模式,以下选其一

tv.setEventMode(TableView.MODE_NONE_EVENT);//不处理任何事件(默认)

tv.setEventMode(TableView.MODE_ITEM_EVENT);//item处理点击和长按事件

tv.setEventMode(TableView.MODE_ALL_UNIT_EVENT);//所有单元格处理事件

tv.setEventMode(TableView.MODE_EITHER_UNIT_EVENT);//某些列的单元格处理事件
tv.setColumnEventIndex(1,7,9,18);//设置哪些列的单元格处理事件

其它相关

tv.setUnitSelectable(true);//单元格处理事件的时候是否可以选中
tv.setUnitDownColor(R.color.blue_color);//单元格处理事件的时候,按下态的颜色
tv.setUnitSelectedColor(R.color.cyan_color);//单元格被选中的颜色

Map<Point,String> selectedData = tv.getSelectedUnits();//获取所有选中的单元格数据
tv.clearSelectedUnits();//清除所有选中的单元格
tv.setUnitSelected(1,2);//在单元格可以被选中的时候,通过代码设置第1行第2列的单元格被选中

6.更多更详细的见源码

地址:https://github.com/developerzjy/AndroidTableView

运行效果图

上一篇: Android自定义TableView (二) 扩展 - 样式

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,451评论 25 707
  • 废话不多说,直接上干货 ---------------------------------------------...
    小小赵纸农阅读 3,333评论 0 15
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 期待是通往地狱之门。 ——对自己的付出东西不要期待有所回馈 希望越大,失望越大。发生在家里的一件事,弟弟因视力比常...
    修炼记2017阅读 314评论 0 0
  • 午间,做了一个长长的梦。梦中所有的细节清晰,而醒来却只模糊记得个梗概。有异常陡峭的山峰,一些从未见过奇怪动物从山顶...
    蓝羽鱼阅读 277评论 3 1