当前位置:首页 » 安卓系统 » androidfling

androidfling

发布时间: 2023-05-25 14:49:57

‘壹’ NestedScrollView+RecyclerView 滑动卡顿简单解决方案

以下xml是当前布亩伏局:
<code>
<android.support.v4.widget.NestedScrollView
xmlns:android=" http://schemas.android.com/apk/res/android "
android:layout_width="match_parent"
android:layout_height="match_parent"

<LinearLayout
android:id="@+id/linerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"


<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</code>

NestedScrollView中包含了LinearLayout,LinearLayout包含了一系列的组件,其中迅袜携包括RecyclerView,RecyclerView和NestedScrollView都有滚动事件,这种情况下进行滑动操作,fling的操作体验很差,几乎就是手指离开的时好中候,滑动停止.

以下xml是改动后的布局:
<android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:nestedScrollingEnabled="false" />
android:nestedScrollingEnabled="false"
官方文档:
Enable or disable nested scrolling for this view.
If this property is set to true the view will be permitted to initiate nested scrolling operations with a compatible parent view in the current hierarchy. If this view does not implement nested scrolling this will have no effect. Disabling nested scrolling while a nested scroll is in progress has the effect of stopping the nested scroll.
这里设置为false,放弃自己的滑动,交给外部的NestedScrollView处理,就没有出现卡顿的现象了,并且有fling的效果

‘贰’ android 关于手势事件onFling

touch事件中先return给手势事件(return gestureDetector.onTouchEvent(event); ),在onFling中判断,如果速度大于一个值就执行,应该就可以的

‘叁’ Android 里的手势监听SimpleOnGestureListener 绑定到LinearLayout 或 RelativeLayout 不触发 onFling()

让OnTouch方法 返回 true;
这样写试试
public boolean onTouch(View v, MotionEvent event) {
detector.onTouchEvent(event);
return true;

}
不行的话 你了解下这些事件里返回值的意义,懂了 就有解决思路了

‘肆’ android fragment怎么监听上下滑动

view 或者 activity 实现 OnGestureListener 接口。
在 onScroll 方则陪举法中实现上下乱纳滑动:
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
Log.d("Fling", "Fling Happened!");
float x1 = e1.getX(), x2 = e2.getX();

if (x1 -x2 >孙碧 120) {
if (mDirection != EAST) {
mNextDirection = WEST;
}
Log.d(this.getClass().getName(), "To LEFT" + "(" + x1
+ "," + x2 + ")");
return (true);
} else if (x1 - x2 < -120) {
if (mDirection != WEST) {
mNextDirection = EAST;
}
Log.d(this.getClass().getName(), "To Right" + "(" + x1
+ "," + x2 + ")");
return (true);
}

return false;
}

‘伍’ Android的手势GestureDetector, onFling之前肯定有onscroll吗

Fling之前必然有scroll,因为Fling就是scroll达到一定速度的后续结果。
你在onScroll时,是无法判定之后会不会有fling,这个判定只能在ACTION_UP之后,通过计算手势的速度来决定。
你可能说,我可以中间根据scroll的速度来判断,可是呢,ta可能很快的滚过,但是马上慢下来,再慢慢抬起。所以在最后抬起之前判断,是做不到完全准确的。

‘陆’ android ontouch事件return true和return false的区别

1,return false说明你还没消费onTouch事件,在执行完你onTouch里面的代码之后,onTouch事件并没有结束。就是会自动地执行Gallery这个view里onTouch代码(这个为默认).所以这就是为什么没增加你的处理的时候就只自动地调用Gallery的onTouch,若你在onTouch里面增加你的代码并且return false就会执行你的处理和默认的处理。

2,return true说明你已经消费完了onTouch事件,在执行完你的onTouch里面的代码之后,这个onTouch事件就结束了。也就是说不会再调用默认的onTouch事件了。在onTouch里面有很多种的处理比如move,down,up....,若你在move里面return false,那么接着的fling,up等后面的事件也不会处理的。

‘柒’ Android自定义View之区块选择器

先来看下效果吧:

我们来分析这个view需要实现哪些效果。

别害怕有这么多的功能,我们一个一个来实现。首先是刻度尺,这个简单。由于完整的刻度尺是比屏幕宽度大的,因此我们先来了解几个概念:

这里手机屏幕的宽度是width,刻度尺的宽度的时maxWidth,我们其实只需要绘制手机屏幕可见的部分就可以了,这里的offset表示手机屏幕的左边与刻度尺左边的偏移量。

了解了这个概念,我们就来开始写吧,定义一个View,处理下构造都指向3个参数的那个,然后统一做初始化:

我们在onMeasure中处理了wrap_content的高度。然后在onSizeChanged中获取尺寸参数:

接着就开始绘制吧:

这里的titles代表了刻度的标识,每一个元素代表一个刻度(这里我字节写死了,实际上可以通过方法set,也不一定是时间,能代表刻度的都可以)。通过rate设置长短刻度的比例,这里我设置了1:1。运行一下看看,目前仅仅能看到从0开始,看不到完整的刻度尺,我们需要实现touch事件产生移动才有效果。

我们重写onTouchEvent来实现滑动效果:

我们计算出每次move事件的X方向的变化量dx,然后通过这个dx改变offset,并且处理一下边界的情况。然后调用postInvalidate刷新界面。
运行一下看看!现在我们可以滑动刻度尺了。但是好像还有点问题,平时我们使用ScrollView的时候用力划一下,可以看到手指离开了屏幕,但是内容还可以继续滚动。而目前我们自定义的这个view只能通过手指滑动,如果手指离开屏幕就不能滑动了。这样的体验显然不够好,我们来实现这个惯性滑动的效果吧!

要实现惯性滑动,我们需要用到两个类:VelocityTracker,OverScroller。
VelocityTracker简介
view滑动助手类OverScroller

velocityTracker.computeCurrentVelocity方法的第二个参数表示最大惯性速度,这里我设置8000,避免刻度尺过快的滑动。通过调用scroller.fling方法将计算出的速度交给scroller,然后在computeScroll方法中获取当前值,并与上一次的值做差算出变化量dx,同样用这个dx变化offset刷新界面实现滑动效果。

刻度尺完成了,接下来是不可选的灰色区域。我采用两个int值表示在刻度尺的区域,刻度尺的每个刻度表示一个最小单位,前一个int表示在刻度尺的起始位置,后一个int表示占据的刻度数量。

我用一个list存放设置的不可选区域,然后在另一个list中存放转换成RectF的位置信息。这里的RectF是在相对于整体刻度尺而言的,因此绘制到屏幕的时候需要减去offset,并且需要考虑只有部分在屏幕可见的情况。避免在onDraw方法中创建过多临时变量,我声明一个成员变量tempRect,用来保存绘制时的临时参数。

完成了不可选区域,可选区域也是同样的。由于只能有一个可选区域,我们只需要定义一个RectF。额外需要考虑与不可选区域相交时会变色,我定了一个overlapping表示是否相交,通过RectF的intersects方法判断。

通过前面的分析,我们知道这个view中的事件有很多种:点击,移动刻度尺,移动选中区域,扩展选中区域。我们定义这四种类型便于后续的事件处理:

然后改造一下onTouchEvent:

performClick会在你重写onTouchEvent时as提示你需要重写的方法,因为你可能没有考虑到如果给这个view设置OnClickListener的情况。如果你没有在onTouchEvent中调用performClick,那么setOnClickListener方法就失效了。

你可能注意到这一次比较复杂,并且还有一个linking字段,表示是否正在联动,我解释一下这个联动的概念:通过gif其实你可能注意到,当我移动或者扩展选中区域的时候,如果移动到了屏幕的边界,后面的刻度尺就会跟着移动,实际上这个时候选中区域在屏幕中的位置没有改变,只是刻度尺移动了。一开始我也是通过dx来改变offset,但是存在一个问题,移动到屏幕边缘之后,手指可以移动的区域已经很小了,不会产生足够的dx(手指不移动的话,不会有新的touch事件产生)。最好的体验是我把手机移动到屏幕边缘,刻度尺就会自己按照一定的速率移动直到最大offset或者最小offset。于是我使用了Handler,当满足条件后发送消息,表示开始进行联动,会按照固定速度产生一个dx改变offset。当然,在离开屏幕边缘的时候还需要及时取消handler的任务。

至此,功能基本已经实现了,运行一下看看效果吧~

后面需要做什么那?现在这个view只能自己玩,我需要它与其他view有交互,比如选中什么区域,状态的改变生么的。

声明两个接口,并在适当时候回调它们的方法,这样外部就能感知view的状态变化。

后面的话就是根据业务添加一些api了,例如添加不可选区域,改变刻度范围什么,一切都看需求了。

想学习更多Android知识,或者获取相关资料请加入Android开发交流群:1018342383。 有面试资源系统整理分享,Java语言进阶和Kotlin语言与Android相关技术内核,APP开发框架知识, 360°Android App全方位性能优化。Android前沿技术,高级UI、Gradle、RxJava、小程序、Hybrid、 移动架构师专题项目实战环节、React Native、等技术教程!架构师课程、NDK模块开发、 Flutter等全方面的 Android高级实践技术讲解。还有在线答疑

‘捌’ 如何在android中实现swipe的手势功能及页面拖动动画

SimpleOnGestureListener. 你只需要实现自己所关心的手势就可以了.
Swipe在android里面是叫Fling ^_^
首先创建自己的一个手势detector类:

private static final int SWIPE_MIN_DISTANCE = 120; private static final int SWIPE_MAX_OFF_PATH = 250; private static final int SWIPE_THRESHOLD_VELOCITY = 200;然后在onFling方法中, 判断是不是一个合理的swipe动作: if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { viewFlipper.setInAnimation(slideLeftIn); viewFlipper.setOutAnimation(slideLeftOut); viewFlipper.showNext(); } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { viewFlipper.setInAnimation(slideRightIn); viewFlipper.setOutAnimation(slideRightOut); viewFlipper.showPrevious(); }里的viewFlipper是含有多个view的一个container, 可以很方便的调用prev/next view, 加上animation动画, 可以达到一些不错的效果:
viewFlipper = (ViewFlipper)findViewById(R.id.flipper); slideLeftIn = AnimationUtils.loadAnimation(this, R.anim.slide_left_in); slideLeftOut = AnimationUtils.loadAnimation(this, R.anim.slide_left_out); slideRightIn = AnimationUtils.loadAnimation(this, R.anim.slide_right_in); slideRightOut = AnimationUtils.loadAnimation(this, R.anim.slide_right_out); 自定义的animation可以查看具体的XML, 比如从左边进来的一个动画:

‘玖’ 如何优雅地在Android上实现iOS的图片预览

原文博客链接

用过 iOS 的都知道,拟物理的回弹效果在上面非常普遍,因为这是 iOS 系统支持的一套 UI 框架,但是 Android 就没有了,就拿图片查看器来讲,iOS 的效果就是感觉一张图片被绑定在了弹簧装置上,滑动很自然,Android 没有自带的图片查看器,需要自己实现

市面上主流的图片查看器都没有回弹的效果,一部分原因是没有这个需求,还有一部分是实现麻烦,这里讲述一个个人认为最好的方案

一个图片查看器,要求可以滑动 Fling,触碰到边界的时候回弹,有越界孝唤回弹的效果,支持双指缩放,双击缩放

咋一看需求,应该好写,滚动的时候用 Scroller 来解巧态凯决,回弹效果直接用 ValueAnimator ,设置插值器为减速插值器来解决。看似简单,但是因为是仿物理效果,中间牵扯到从滚动到回弹的时候( Scroller 动画切换到 ValueAnimator 动画)的闭老速度衔接问题,要看上去从滚动到开始回弹至结束没有突兀,中间的特判边界处理是很麻烦的,还要牵扯到缩放,所以不考虑这种方案

既然是要模拟现实中的物理效果,为何不在每一帧根据当前的状态得到对用的加速度,然后去计算下一帧的状态位置,这样只要模拟现实中的物理加速度不就可以实现了吗,那些边界特判之类的就可以去见阎王了

方案确定完毕,接下来就是选定加速度的方程,要模拟弹簧的效果,拉力很简单,用胡克定律嘛! F = k * dx ,摩擦力呢? Ff = μ*FN ? 这里推荐一个更加好的方案,借鉴自 Rebound 库,这是 Facebook 的一个弹簧动画库,设定一个目的数值,它会根据当前的拉力,摩擦力,速度然后变化到目标值,加速度方程为

其中 tension 为弹性系数, friction 为摩擦力系数,为什么让摩擦力和速度成正比呢?如果摩擦力和速度成正比,那么就不存在静摩擦力,也就是不存在物体静止情况下拉力小于摩擦力的情况(因为速度为0的时候,阻力为0,除非拉力为0),物体肯定会向目标地点靠近,遏制了物体摩擦力过大而无法达到目的地情况

为了方便接入各种 View ,设计一个 ZoomableGestureHelper 类

设计目的,我只需要知道视图的大小边界 (bounds) 和内部可滚动回弹的边界 (innerBounds),就可以通过计算得到一个新的转换矩阵

对于物理状态,需要一个类 SpringPhysicsState 来做存储,里面包含了速度、拉力系数、摩擦力系数,不保存位置,因为位置是通过 getBounds 动态计算得到的

速度分解成水平方向和垂直方向,因为处理方法一样,下面只讲述垂直方向的计算

状态1 :其中一边有越界

分析一下上图中的位置,蓝色部分为内部图片,它被拖动越界了,此时的合力应该为 tension * dx - friction * v , v 为图片在 y 轴方向上的速度,( dx 和 v 都是矢量,我暂且设置向右和向下为正),之后就直接调用 invalidate(); ,就可以播放动画了。

状态2:两边都没越界

此时因为两边都没有越界,所以应该不存在拉力,可以认为此时 dx 为0,摩擦力需要注意下,因为可以支持滑动( Fling ),所以此时的摩擦力要比之前越界回弹时候的摩擦力小,至于具体数值,文末会给出

状态3:两边都超出

此时两边都超出边界,蓝色区域应该和红色区域中心绑定,所以此时的 dx 为 dxBottom - dxTop (注意符号,因为 dx 为矢量,所以不能是 dxTop - dxBottom )

缩放的方法和移动一致,设定 tension 和 friction ,边界设定为外面红色的框框,蓝色区域无法某一边充满红色区域的时候,有拉力,否则没拉力,摩擦力一直存在,至于双击放大和放小,只需要在双击的时候给缩放状态设置一个初速度,然后 invalidate(); ,搞定!是不是很简单啊

时间这一个参数在计算中是非常重要的,这关系到当前微分状态的数值变化,假如用欧拉方法模拟速度和位置的变化, x' = x + v * dt , v' = v + a * dt ,公式可以看出时间决定了动画的快慢,为了接近现实物理时间,这里采用的时间单位为秒(计算机中常用的是毫秒)

确定了单位,还需要控制一下时间间隔的数值范围,我们不能让两次 computeScroll 的时间间隔过于短或者过于长,这里采用的策略为固定每次计算时候的时间间隔,如果两次 computeScroll 的时间间隔小于此时间间隔,那么保存累计时间间隔,等待下一次 computeScroll ,直到大于等于固定的时间间隔,再用 while 循环一步一步的计算

结束判定是唯一的一个坑,因为计算机只是在 dt 时间内模拟速度和位移的变化,不是通过微积分计算的,存在误差,比如欧拉方法 x' = x + v * dt 和 v' = v + a * dt 计算得到的 x' 和 v' 都是近似数值,把 dt 这段时间内的变化看成了匀变速运动

所以结束判定还需要设置一个阈值,当速度和偏移量小于此数值的时候,可以认定为达到了目的地

对于 ViewPager 的适配有些问题,如果在 Down 的时候 requestDisallow true 移动过程中到了左右边界又 requestDisallow false ,此时 ViewPager 会有一个突变( 突变可耻但有用 ),而且多指头的时候可能会崩溃,这是 ViewPager 的 Bug,具体细节请看源码

‘拾’ android中listview如何支持上下滑动,左右滑动且左右滑动时可以指定固定列数

左右滑动可以用gallery,不知道LZ想要什么样的效果呢,不过提醒一下,不要用scrollview嵌套listview,效果不好哦~~

热点内容
为实现分页存储管理需要哪些硬件支持 发布:2025-02-12 11:46:34 浏览:539
编程下载线 发布:2025-02-12 11:41:48 浏览:210
json存储数据 发布:2025-02-12 11:41:39 浏览:219
天龙八部脚本免费 发布:2025-02-12 11:30:12 浏览:501
卡罗拉的配置一般买哪个好一点 发布:2025-02-12 11:20:03 浏览:743
没有服务器的IP怎么连上 发布:2025-02-12 11:19:55 浏览:80
编程sqs 发布:2025-02-12 11:09:55 浏览:239
electron脱离编译环境 发布:2025-02-12 11:08:21 浏览:69
安卓一体机喇叭插口在哪里 发布:2025-02-12 11:07:37 浏览:867
广东江门首选dns服务器地址 发布:2025-02-12 10:56:55 浏览:955