Android自己定义组件系列【7】——进阶实践(4)
上一篇《Android自己定义组件系列【6】——进阶实践(3)》中补充了关于Android中事件分发的过程知识。这一篇我们接着来分析任老师的《可下拉的PinnedHeaderExpandableListView的实现》。
一、StickyLayout中的OnGiveUpTouchEventListener接口的作用是什么?
public interface OnGiveUpTouchEventListener {
public boolean giveUpTouchEvent(MotionEvent event);
}
在StickyLayout中还提供了设置监听的方法例如以下:
public void setOnGiveUpTouchEventListener(OnGiveUpTouchEventListener l) {
mGiveUpTouchEventListener = l;
}
这样的方式事实上是一种钩子方法。在OnGiveUpTouchEventListener中定义了一个抽象方法(未详细实现)giveUpTouchEvent.,然后通过MainActivity继承OnGiveUpTouchEventListener接口来实现详细逻辑。
@Override
public boolean giveUpTouchEvent(MotionEvent event) {
if (expandableListView.getFirstVisiblePosition() == 0) {
View view = expandableListView.getChildAt(0);
if (view != null && view.getTop() >= 0) {
return true;
}
}
return false;
}
这种方法中的逻辑:取到ExpandableListView中的第一个可见项。假设是它的子View中的第一个则说明如今首先应该滑动上面的Header部分(让其展开)。
这里返回的true和false有什么不同呢?向下看
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int intercepted = 0;
int x = (int) event.getX();
int y = (int) event.getY(); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mLastXIntercept = x;
mLastYIntercept = y;
mLastX = x;
mLastY = y;
intercepted = 0;
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = x - mLastXIntercept;
int deltaY = y - mLastYIntercept;
if (mStatus == STATUS_EXPANDED && deltaY <= -mTouchSlop) {
intercepted = 1;
} else if (mGiveUpTouchEventListener != null) {
if (mGiveUpTouchEventListener.giveUpTouchEvent(event) && deltaY >= mTouchSlop) {
intercepted = 1;
}
}
break;
}
case MotionEvent.ACTION_UP: {
intercepted = 0;
mLastXIntercept = mLastYIntercept = 0;
break;
}
default:
break;
} Log.d(TAG, "intercepted=" + intercepted);
return intercepted != 0;
}
在StickyLayout类中的事件拦截方法的ACTION_MOVE中有这么几句代码:
if (mStatus == STATUS_EXPANDED && deltaY <= -mTouchSlop) {
intercepted = 1;
} else if (mGiveUpTouchEventListener != null) {
if (mGiveUpTouchEventListener.giveUpTouchEvent(event) && deltaY >= mTouchSlop) {
intercepted = 1;
}
}
如今应该明确了吧,呵呵。STATUS_EXPANDED是一个状态值。意思是如今Header部分是展开的,假设Header部分是收起的则会推断giveUpTouchEvent的返回值。假设giveUpTouchEvent返回true说明列表所有被拉下来了,此时应该将Header部分展开。假设返回false则应该下滑列表而不是展开Header部分。
二、PinnedHeaderExpandableListView对OnScrollLister的实现
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (mHeaderView != null && scrollState == SCROLL_STATE_IDLE) {
int firstVisiblePos = getFirstVisiblePosition();
if (firstVisiblePos == 0) {
mHeaderView.layout(0, 0, mHeaderWidth, mHeaderHeight);
}
}
if (mScrollListener != null) {
mScrollListener.onScrollStateChanged(view, scrollState);
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (totalItemCount > 0) {
refreshHeader();
}
if (mScrollListener != null) {
mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
}
OnScrollListener是ListView的滚动事件。
在onScrollStateChanged(AbsListView view, int scrollState)中,scrollState有三种状态。各自是:
1、SCROLL_STATE_FLING:開始滚动
2、SCROLL_STATE_TOUCH_SCROLL:正在滚动
3、SCROLL_STATE_IDLE:已经停止
onScroll()方法在列表滚动时一直回调。知道滚动停止才停止回调,另外单击时也回调一次。而OnScrollStateChanged的意思是上面三种状态改变时回调。回调顺序例如以下:
- 第1次:scrollState = SCROLL_STATE_TOUCH_SCROLL(1) 正在滚动
- 第2次:scrollState = SCROLL_STATE_FLING(2) 手指做了抛的动作(手指离开屏幕前,用力滑了一下)
- 第3次:scrollState = SCROLL_STATE_IDLE(0) 停止滚动
- 上面的OnScrollStateChanged方法中在滚动停止后再次布局(绘制)了列表的头。在onScroll方法中主要是为了调用前面提到的refreshHeader()方法去回调并刷新列表头。
- 四、怎样处理以下列表头将上面列表头顶上去?
protected void refreshHeader() {
if (mHeaderView == null) {
return;
}
int firstVisiblePos = getFirstVisiblePosition();
int pos = firstVisiblePos + 1;
int firstVisibleGroupPos = getPackedPositionGroup(getExpandableListPosition(firstVisiblePos));
int group = getPackedPositionGroup(getExpandableListPosition(pos)); if (group == firstVisibleGroupPos + 1) {
View view = getChildAt(1);
if (view.getTop() <= mHeaderHeight) {
int delta = mHeaderHeight - view.getTop();
mHeaderView.layout(0, -delta, mHeaderWidth, mHeaderHeight - delta);
}
} else {
mHeaderView.layout(0, 0, mHeaderWidth, mHeaderHeight);
} if (mHeaderUpdateListener != null) {
mHeaderUpdateListener.updatePinnedHeader(firstVisibleGroupPos);
}
}refreshHeader()方法中能够看到,先推断上面的是不是多个列表头假设是则又一次设置以下列表头的位置到“标准位置”,这样就感觉有一种顶上去的感觉了。
- 三、怎样展开收缩列表
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int x = (int) ev.getX();
int y = (int) ev.getY();
Log.d(TAG, "dispatchTouchEvent");
int pos = pointToPosition(x, y);
if (y >= mHeaderView.getTop() && y <= mHeaderView.getBottom()) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mActionDownHappened = true;
} else if (ev.getAction() == MotionEvent.ACTION_UP) {
int groupPosition = getPackedPositionGroup(getExpandableListPosition(pos));
if (groupPosition != INVALID_POSITION && mActionDownHappened) {
if (isGroupExpanded(groupPosition)) {
collapseGroup(groupPosition);
} else {
expandGroup(groupPosition);
}
mActionDownHappened = false;
} }
return true;
} return super.dispatchTouchEvent(ev);
}能够看到PinnedHeaderExpandableListView中的事件分发函数中有例如以下代码:
if (y >= mHeaderView.getTop() && y <= mHeaderView.getBottom())
限制高度(在列表头位置)
if (isGroupExpanded(groupPosition)) {
collapseGroup(groupPosition);
} else {
expandGroup(groupPosition);
}假设点击则展开或闭合。
。。。
Android自己定义组件系列【7】——进阶实践(4)的更多相关文章
- Android自己定义组件系列【6】——进阶实践(3)
上一篇<Android自己定义组件系列[5]--进阶实践(2)>继续对任老师的<可下拉的PinnedHeaderExpandableListView的实现>进行了分析,这一篇计 ...
- Android自己定义组件系列【5】——进阶实践(2)
上一篇<Android自己定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这 ...
- Android自己定义组件系列【4】——自己定义ViewGroup实现双側滑动
在上一篇文章<Android自己定义组件系列[3]--自己定义ViewGroup实现側滑>中实现了仿Facebook和人人网的側滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布 ...
- Android自己定义组件系列【3】——自己定义ViewGroup实现側滑
有关自己定义ViewGroup的文章已经非常多了,我为什么写这篇文章,对于刚開始学习的人或者对自己定义组件比較生疏的朋友尽管能够拿来主义的用了,可是要一步一步的实现和了解当中的过程和原理才干真真脱离别 ...
- Android自己定义组件系列【5】——高级实践(1)
在接下来的几篇文章将任老师的博文<您可以下拉PinnedHeaderExpandableListView实现>骤来具体实现.来学习一下大神的代码并记录一下. 原文出处:http://blo ...
- Android自己定义组件系列【1】——自己定义View及ViewGroup
View类是ViewGroup的父类,ViewGroup具有View的全部特性.ViewGroup主要用来充当View的容器.将当中的View作为自己孩子,并对其进行管理.当然孩子也能够是ViewGr ...
- Android自己定义组件系列【2】——Scroller类
在上一篇中介绍了View类的scrollTo和scrollBy两个方法,对这两个方法不太了解的朋友能够先看<自己定义View及ViewGroup> scrollTo和scrollBy尽管实 ...
- Android自己定义组件系列【9】——Canvas绘制折线图
有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了非常多插件,可是非常多时候我们须要依据详细项目自己定义这些图表,这一篇文章我们一起来看看怎样在Android中使用Can ...
- Android自己定义组件系列【8】——面膜文字动画
我们掩盖文字动画Flash中非经货共同体共同,由于Android应用程序开发人员做你想要做这个动画在应用程序中去?本文中,我们看的是如何自己的定义ImageView来实现让一张文字图片实现文字的遮罩闪 ...
随机推荐
- tomcat建立虚拟主机
WEB浏览器与WEBserver建立连接后,除了将请求URL中的资源路径发送给WEBserver外,还会将URL中的主机名部分作为HTTP请求消息的Host头发送给WEBserver.比如,在浏览器地 ...
- Oracle SQL函数之聚组函数
AVG([distinct|all]x) [功能]统计数据表选中行x列的平均值. [参数]all表示对所有的值求平均值,distinct只对不同的值求平均值,默认为all 如果有参数distinct或 ...
- escape和unescape给字符串编码
var before = "\xxx\xxx" var after = escape(before); var after2 = unescape(after );
- 【初级坑跳跳跳】[NULLException] findViewById() id 引用错误,导致空指针
在学习Intent页面切换,几个页面切换,导致view id 写错,写成另一个xml里的id去了,导致空指针异常 setContentView(R.layout.activity_second); B ...
- 使用react-native做一个简单的应用-02项目搭建与运行
下面我们开始着手去做这一个项目,因为初学不久就开始边学边做,所以有些地方设计不太合理.请大家多多包涵.0.0 下面来介绍截图中的三个文件夹, GuoKuApp:是我开发app的文件夹. GuoKuDB ...
- Sql server中根据object的定义查找object
SELECT OBJECT_NAME(object_id) FROM sys.sql_modulesWHERE definition LIKE '%keyword to search%' 或者 SEL ...
- 【转】VS2010中文注释带红色下划线的解决方法
转载自:http://blog.csdn.net/whatday/article/details/7856323 环境:Visual Studio 2010 问题:代码中出现中文后会带下划线,很多时候 ...
- Eclipse编译Arduino程序不能使用串口函数Serial.begin解决办法
在Arduino官方的编译器当中Serial.begin(9600);初始化语句是可以直接使用的,而到Eclipse当中,同样的语句却不能用了.会出现下面的问题: 显然,这是Eclipse没有找到Se ...
- windows查询端口
依次点击“开始→运行”,键入“cmd”并回车,打开命令提示符窗口.在命令提示符状态下键入“netstat -an”,按下回车键后就可以看到以数字形式显示的TCP和UDP连接的端口号及状态.
- ORA-04092: COMMIT 不能在触发器中
触发器无需commit也不能写commit触发器和触发它的DML是同一个事务DML提交了,触发器的操作也提交了,要不就一起回滚了 当然,如果你一定要在触发器里写COMMIT那就用自治事务相当于一个事务 ...