如何模仿棒棒糖的手机应用程序,在滚动内容之前调整上层项目的大小?

背景

在棒棒糖的电话应用程序,当你到达“最近”或“联系人”选项卡,并尝试滚动时,首先发生的事情是调整上部区域,其中包括最近的事件和search框,如此:

在这里输入图像说明

如果RecyclerView上有3个以上的项目,RecyclerView将不会向下滚动,只要上部区域缩小到最小尺寸即可。

向上滚动也一样:只要上部区域没有完全放大,RecyclerView将不会向上滚动。

问题

我找不到实现此function的最佳方法。

更具体地说,我有一个关于上部区域大小的问题,所以它会像棒棒糖一样顺畅。

为了简化,我只需要调整屏幕的一部分,而不是手机的应用程序(“最近的事件”和search框)上显示的2。

我试过了

有很多事情我试图做:

  1. 使RecyclerView变得像整个屏幕一样大,同时有一个假的,大的空头。 当我滚动时,我也把“翻译Y”设置为顶部的真实内容。 这有一个显示滚动条作为上部区域的一部分(我想在正确的位置显示滚动条)的问题。 另外,由于您必须处理其他页面的RecyclerViews滚动值,因此这会变得非常复杂。 这是类似于一些第三方库的解决scheme,比如这个 (但在这里我使用了布局而不是ImageView,但是代码几乎相同)。

  2. RecyclerView低于上方区域,滚动更改上方区域的layoutParams,类似于我在这篇文章中所做

  3. 与2相同,但不是更改LayoutParams,而是更改视图的scaleY。

对于#2和#3,问题是在某些情况下,只要我在某个值上滚动到+ Y的事件,我也会滚动甚至相同值的-Y(反之亦然) ,使得resize效果的处理“跳动”(即使用户滚动得好)。

我猜为什么会出现这种情况,当我移动RecyclerView时,用户所做的下一个事件与原来的位置完全不同,因为我改变了RecyclerView的位置或大小。

我曾尝试使用setOnTouchListener (甚至与GestureDetectorCompat一起)和setOnScrollListener 。 所有引起了同样奇怪的问题。

这个问题

我如何解决这个问题? 为什么会发生,怎么发生呢?


编辑:我试图改变#2,所以,而不是处理RecyclerView的触摸事件,我将处理其容器(一些LinearLayout)的触摸事件。 出于某种原因,容器没有响应触摸事件,所以我用RelativeLayoutreplace了它,并在该布局内部放置了一切视图,这将响应触摸事件(并相应地更改上部区域)。 这工作,但后来我无法进一步将事件传递给需要的子视图。

我认为最好的办法是自定义RecyclerView(扩展它)的触摸处理。 也许添加一个滚动侦听器,当RecyclerView要滚动时,它会询问是否正确,如果没有,它将不会尝试滚动,直到触发事件被触发并重置其状态。

Solutions Collecting From Web of "如何模仿棒棒糖的手机应用程序,在滚动内容之前调整上层项目的大小?"

好,一个解决scheme(我仍然不喜欢,但是工作)是使用“ TouchInterceptionFrameLayout ”类(从我find的库 ),这将允许您决定何时允许滚动和不滚动,当它不应该滚动的时候,你改变了同时具有分页标签和ViewPager的布局的填充(或者你想要的)。

viewPager&tabs的容器覆盖了整个区域,并且有一个可以改变的填充。

这是布局:

<LinearLayout android:id="@+id/header" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="wrap_content"> <!-- put upper content here --> </LinearLayout> <LinearLayout android:id="@+id/pagerAndTabsContainer" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.astuetz.PagerSlidingTabStrip android:id="@+id/viewPagerSlidingTabsStrip" android:layout_width="match_parent" android:background="@color/default_background" android:layout_height="48dip"/> <android.support.v4.view.ViewPager android:background="@color/default_background" android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> </com.github.ksoichiro.android.observablescrollview.TouchInterceptionFrameLayout> 

然后,你需要有一些初始化的代码(当布局阶段完成,你可以得到真正的视图大小):

 // the upper area height, that can be shrunk to a size of 0 height when needed mResizeableViewHeight = mHeaderView.getHeight(); // set initial padding if you wish to show the upper area by default mPagerAndTabsContainer.setPadding(0, mResizeableViewHeight, 0, 0); prepareViewPager(mViewPager); // set the pages and fragments... // init the "TouchInterceptionFrameLayout" to handle touch events mContentView.setScrollInterceptionListener(mInterceptionListener); 

在TouchInterceptionFrameLayout.TouchInterceptionListener的“shouldInterceptTouchEvent”函数中,您决定何时应该阻止触摸,并且在此接口的“onMoveMotionEvent”上,您应该处理阻塞的触摸。

对于每个具有recyclerView的片段,改为使用ObservableRecyclerView ,然后调用这些行:

  // get the fragment that shows the screen I've made (with the layout) Fragment fragment = getTargetFragment(); // let the recyclerView handle filtered touches mRecyclerView.setTouchInterceptionViewGroup(((IGetContainer) fragment).getContainer()); // if you wish to put animations when you do a touch-up event, this may be handy (or use onUpOrCancelMotionEvent of the "TouchInterceptionListener" too/instead ) : if (fragment instanceof ObservableScrollViewCallbacks) mRecyclerView.setScrollViewCallbacks((ObservableScrollViewCallbacks) fragment); 

我不喜欢这个解决scheme,因为它覆盖了整个屏幕上的一个触摸包装,因为它会导致viewPager的透支(并且要求你为它设置一个背景),而且因为它比我有的复杂心里。 不pipe滚动规则多less,它也比棒棒糖的电话应用程序更不stream畅。

我可以让TouchInterceptionListener开始处理触摸事件,只要它们源于RecyclerView,但这使得它更加复杂。

我知道这是晚了。 但是不能使用一个协调器布局和一个CollapsingToolbarLayout在里面。