这个版本号的博客写起来颇费口舌。有些代码自己语言组织能力有限,感觉描写叙述起来非常费劲,前前后后改了五六遍稿子还是不尽人意 ,只是我还是坚持写出来自己当初的思路,假设看得不明确的地方我在文章最后仍然会上传源码,能够直接执行看效果,看过执行的效果后对文中有些别扭的语言预计会能直观的了解。在版本号3.0的尽管实现了随着手指的左右移动listView中的item也随着滚动。可是会出现例如以下的情况:

当左边已经是第一个的时候,会出现例如以下的情况(仍然能够向右移动):

当右边是adapter最后一个item的时候,会出现例如以下的情况(仍然能够向左移动):

正常来说,当左边第一个和右边最后一个应该不能滚动才是,本4.0版本号将解决问题。在解决问题之前先说说相关的知识点:

知识点1):手指在屏幕上移动的时候,会发生 其它相关方法...>onScroll-->onScroll-->onScroll ..-->其它相关方法.这种调用

知识点2):3.0版本号在处理手指滚动的时候用到了onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY)这种方法,这种方法中有个distanceX參数。这个參数我们知道,当手指想做移动的时候distanceX>0;而手指向右移动的时候distanceX<0;这是由于distanceX的值是由第二个參数决定的:distanceX = 上次掉用onScroll方法的e2.getX()-当前onScroll方法的e2.getX()或者简写成
lastEvent2.getX() - currentEvent2.getX() = distanceX;

在版本号3.0的时候我们直接用distanceX这个变量(确切的说这个变量值的相反数来模拟左右移动滚动的距离),可是这次为了解决上面的问题我们将不再直接用distanceX,而是新定义了两个变量:

变量:preTotalDistanceX :相对于当前onScroll方法调用之前。之前全部onScroll调用所产生的距离之和。比方当前是第n次调用了onScroll。那么preTotalDistanceX=前n-1次调用onScroll中distanceX的累加和;

变量:totalDistanceX:当前调用onScroll方法方法调用中全部distanceX的累加和;比方当前是第n次调用了onScroll方法,那么totalDistanceX就是n个onScrll方法调用中參数里distanceX的累加和。

那么滚动的距离distanceX = totalDistanceX - preTotalDistanceX

用代码表示总距离例如以下:

            public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {
totalDistanceX += distanceX;
requestLayout();
return true; };

该版本号onLayout的方法就改动例如以下:

		int distanceX = totalDistanceX - preTotalDistanceX;
removeAnvisiableViews(-distanceX);
addRightChildViews(-distanceX);
addLeftChildViews(-distanceX);
layoutChildViews(-distanceX);
preTotalDistanceX = totalDistanceX;

要解决文章开头提出的问题,关键是让distanceX = 0;即pretotalDistanceX=totalDistanceX;所以解决这个问题的关键就是怎样让这两个变量相等。从知识点2能够知道,如果用户的手指先右后左:此时最左边的item是adapter的第一个item,所以手指向右移动的时候不能让listView向右滚动,可是实际上随着手指的向右移动totalDistanceX变量是<0,并沿着平面直角坐标系远离0点而负递增,所以在这里能够初步推断:当totalDistanceX<=0的时候,让totalDistanceX
= 0;这样preoTotalDistanceX=totalDistanceX=0,这样就会让distanceX=0,从而不会让我们的ListView不会向右移动;如果用户的手指先左后右的移动方式:当手指向左移动的时候totalDistanceX>0且不断增大。是递增的。而当手指右移动的时候totalDistanceX是在原来的基础上不断降低的过程,当较少到0的时候继续向右移动的话totalDistanceX变为负数,继续向右移动的话就类似与手指先右后左的现象了;这个是关键的地方。整个左右移动的过程发生诡异的变化类似于物理中的位移。当totalDistanceX=0的时候我们能够断定不能在向右滚动。

所以在onLayout代码中我做了例如以下推断:

@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) { if (listAdapter == null) {
return;
}
/**确保党左边是第一个的时候不再滚动*/
if(totalDistanceX<=0) {
totalDistanceX = 0;
} int distanceX = totalDistanceX - preTotalDistanceX;
removeAnvisiableViews(-distanceX);
addRightChildViews(-distanceX);
addLeftChildViews(-distanceX);
layoutChildViews(-distanceX);
preTotalDistanceX = totalDistanceX; }

执行一把发现上面的设想是成立的。到此为止,博客开头的第一个问题得到了解决。

以下将解决第二个问题:当adapter里面最后一个item加入到viewGroup里面而且全然显示的时候,禁止listView继续向左滚动。

先看最有一个item没有显示全然的情况,例如以下图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2h1bnFpdXdlaQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

解决第二个问题的关键仍然是怎样让distanceX= totalDistanceX-pretotalDistanceX=0。也就是怎样让totalDistanceX=preototalDistanceX;依据图示我们非常easy得出例如以下结论:要让最后一个item显示完。在之前滚动距离总和的基础上再让listView滚动X大小的距离能够了,用上面的等式表示为totalDistanceX=X+pretotalDistanceX,所以当totalDistanceX>X+pretotalDistanceX的时候我们让 totalDistanceX
= X+preototalDistanceX;在程序用我是用scrollXMax来表示X+preototalDistanceX的值(此变量名起的有点垃圾);在代码用为:

//scrollXMax = X + pretotalDistanceX
if(totalDistanceX>scrollXMax) {
totalDistanceX = scrollXMax;
} ......
preototalDistanceX = totalDistanceX;

这样当最后一个item滚动了X距离的情况下调用layout绘制到listView之后,手指在移动的情况下if(totalDistanceX>scrollXMax仍然成立)。这样计算的distanceX=0.可是话有说回来了,X+preDistanceX这段代码加入到哪儿呢?结合之前的几篇博客,不难分析出应该在addRightChildViews方法里面加入,代码例如以下:

private void addRightChildViews(int distanceX) {
// 2.让屏幕尽可能的显示Item。注意刚開始的时候是没有
View rightChildView = getChildAt(getChildCount() - 1); // 获取此childView右边框距离parentView左边框的距离
int rightEdge = rightChildView != null ? rightChildView.getRight() : 0;
while (rightEdge + distanceX < getWidth()
&& rightIndex < listAdapter.getCount()) {
View child = listAdapter.getView(rightIndex, null, null);
child = measureChild(child);
addViewInLayout(child, -1, child.getLayoutParams(), true);
rightEdge += child.getMeasuredWidth(); //推断最后一个item
if (rightIndex == listAdapter.getCount() - 1) {
scrollXMax = rightEdge +preTotalDistanceX- getWidth();
} rightIndex++;
}
}

到此位置。上面的的两个问题都得到圆满解决。自己在整这个版本号的时候走了不少弯路,捣鼓了半天,到最后完成还是有种小小的成就感;何为编程。说白了就是在遵循特性编程语言规则的情况下,用该编程语言描写叙述或者表达程序猿思路的过程。

在4.0版本号的实现中。自己在纸上又是写又是画的,思路清晰了然后就非常自然而然的用编程语言把这个思路表达出来。这就是编程吧!啰嗦完成。当然该版本号还没有完好完成,比方说不能点击就是这个,将在下一个版本号解决剩余的问题。时间同意的话直接写完。此处为项目源代码,欢迎批评指正

简单的横向ListView实现(version 4.0)的更多相关文章

  1. 简单的横向ListView实现(version 3.0)

    版本号2仅仅是简单的实现了当手指按下的时候listView的Item向左移动一定的距离,并没有随着手指的左右移动而左右滚动.在这个版本号3.0中将会实现随着手指的移动而滚动的目标:当手指向左移动的时候 ...

  2. gitlab 源码安装=》rpm安装横向迁移(version 9.0)

    准备: 下载版本地址: https://packages.gitlab.com/gitlab/gitlab-ce 迁移环境: 源码安装的gitlab9.0.13 目标迁移至9.0.13 RPM安装的环 ...

  3. Java简单双向链表实现 @version 1.0

    package com.list; /** * 数据结构和算法Java表示 双向链表 * * @version 1.0 * @author 小明 * */ public class MyDoublel ...

  4. Java单链表简单实现* @version 1.0

    package com.list; /** * 数据结构与算法Java表示 * @version 1.0 * @author 小明 * */ public class MyLinkedList { p ...

  5. ExpandableListView简单应用及listview模拟ExpandableListView

    首先我们还是来看一些案例,还是拿搜狐新闻客户端,因为我天天上下班没事爱看这个东东,上班又没时间看新闻,上下班路途之余浏览下新闻打发时间嘛.           看这个效果挺棒吧,其实实现起来也不难,我 ...

  6. 张高兴的 UWP 开发笔记:横向 ListView

    ListView 默认的排列方向是纵向 ( Orientation="Vertical" ) ,但如果我们需要横向显示的 ListView 怎么办? Blend for Visua ...

  7. eclipse 和 android studio 编译时报 Unsupported major.minor version 52.0错解决办法

    version 52.0 是java8的环境.当gradle tools 升级到2.2.1时候,可能编译时候会报该错误. 很多网友说更改java version,但是很多时候无效.下面是我遇到时候的解 ...

  8. (class file version 53.0), Java Runtime versions up to 52.0错误的解决方法

    遇到这个错误是在Apache Tomcat上部署应用程序的时候遇到的,具体的错误描述是: java.lang.UnsupportedClassVersionError: HelloWorld has ...

  9. Unsupported major.minor version 52.0解决办法

    一.错误现象:当改变了jdk版本时,在编译java时,会遇到Unsupported major.minor version错误.jdk版本和stanford parser对应关系 JDK版本和Java ...

随机推荐

  1. 深度学习 —— 使用 gensim 实现 word2vec

    在自然语言处理领域中,将单词(words)或词语(phases)映射到向量空间(vector space)中可以很容易就得到单词之间的相似度,因为向量空间中两个向量的相似度很容易求得,比如余弦相似度. ...

  2. logAnalyzer日志管理系统配置实例

    LogAnalyzer日志管理系统配置实例 上个月我写过一篇<利用EventlogAnalyzer分析Linux日志>一文深受大家喜欢,今天我再次为大家讲解Linux系统下的一款开源的日志 ...

  3. SQL语句查询数据库所有表和所有字段的详细信息(包括表描述和字段描述)

    select (case then ddd.value else '' end ) as "表名(中文)" --如果表名相同就返回空 , (case then d.name els ...

  4. angular4自定义组件非input元素实现ngModel双向数据绑定

    在angular里我们一般都是给input元素添加[(ngModel)]="value"实现数据双向绑定,如果想实现自定义的组件上实现ngModel双向数据绑定应该怎么办呐... ...

  5. COGS——T 7. 通信线路

    http://www.cogs.pro/cogs/problem/problem.php?pid=7 ★★   输入文件:mcst.in   输出文件:mcst.out   简单对比时间限制:1.5 ...

  6. I帧、P帧和B帧的特点

    I帧:帧内编码帧 I帧特点: 1.它是一个全帧压缩编码帧.它将全帧图像信息进行JPEG压缩编码及传输; 2.解码时仅用I帧的数据就可重构完整图像; 3.I帧描写叙述了图像背景和运动主体的详情; 4.I ...

  7. Oracle的表空间和sqlplus

    1.  表空间的概念 曾经接触过的数据库都没有听到过表空间这个词,在前一段时间看到Oracle数据库的时候发现表空间无处不在. 所以表空间在Oracle数据库中应该是一个非经常常使用而且非常重要的概念 ...

  8. 在resin配置參数实现JConsole远程监控JVM

    在Resin配置參数实现JConsole远程监控JVM 在Resin中配置中配置下列參数,就能够是实现了! <jvm-arg>-Dcom.sun.management.jmxremote& ...

  9. [ Javascript ] JavaScript中的定时器(Timer) 是怎样工作的!

    作为入门者来说.了解JavaScript中timer的工作方式是非常重要的.通常它们的表现行为并非那么地直观,而这是由于它们都处在一个单一线程中.让我们先来看一看三个用来创建以及操作timer的函数. ...

  10. Impala SQL

    不多说,直接上干货! 其实,跟hive差不多,大家可以去参考我写的hive学习概念系列. Impala SQL VS HiveQL 下面是Impala对基础数据类型和扩展数据类型的支持 • 此外,Im ...