滚动到不带工具栏的折叠视图
Scroll to Collapse View without Toolbar
我正在制作类似于最近 android 的状态栏的布局。
我有两个 Views
容器。 ViewPager
和 RecyclerView
。
默认行为应该是当我滚动 RecyclerView
时,我希望 ViewPager
减小尺寸,反之亦然。
逻辑:
viewPagerMaxHeight = 200;
if scrollTop
is ViewPager.height > viewPagerMaxHeight?
YES: Prevent Scroll and Decrease ViewPager size apropriatry
No: Scroll RecyclerView
if scrollBottom
did we scroll to position 0?
YES: Start increasing ViewPager size
No: Scroll RecyclerView
几点注意事项:
- RecyclerView
包含各种大小的项目。
- 有时会删除和添加项目
- 这是一个简单的 RecyclerView,不是
就像在它们相互折叠的通知中一样。
我可以自己构建大部分逻辑,但我无法为 RecyclerView
创建一个合适的监听器,它将 return 滚动的方向和数量。
防止 RecyclerView
滚动是一个奖励
编辑:
我在github
上做了一个例子
v.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
Log.e("scrollY", ""+scrollY);
Log.e("oldScrollY", ""+oldScrollY);
Log.e("currentHeight", ""+currentHeight);
if(scrollY == 200) {
Log.e("==200", "JU");
} else if (scrollY < 200) {
Log.e("<200", ""+currentHeight);
if(currentHeight < fullHeight) {
Log.e("current<full", Integer.toString(deltaScroll));
deltaScroll = oldScrollY - scrollY;
currentHeight = currentHeight + deltaScroll;
if(currentHeight > fullHeight) {
currentHeight = fullHeight;
}
ku.getLayoutParams().height = currentHeight;
ku.requestLayout();
}
v.scrollTo(0, 200);
} else if (scrollY > oldScrollY) {
Log.e("Scroll DOWN", "" + Integer.toString(scrollY));
deltaScroll = scrollY - oldScrollY;
currentHeight = currentHeight - deltaScroll;
if(currentHeight > minHeight) {
ku.getLayoutParams().height = currentHeight;
ku.requestLayout();
v.scrollTo(0, 200);
} else {
currentHeight = minHeight;
ku.getLayoutParams().height = minHeight;
ku.requestLayout();
}
}
}
});
我正在为 RecycleView
设置填充,并将 NestedScrollView
滚动到第一项,这样填充就看不到了。这让我即使已经在顶部也可以滚动顶部。
一切似乎都正常,但正如您会注意到的那样,当缓慢滚动时滚动是 "jumpy"(如果滚动足够快则不会发生)。
我猜这是因为 NestedScrollView
本身会改变高度,例如向上滚动时,也会向下滚动。
根据您当前的代码:
Everything seems to work, but as you will notice scrolling is "jumpy" when scrolling slowly...
YES ,这是因为当用户缓慢滚动时方法 onScrollChange
可能会被调用多次(由于系统误解 scroll ==> stop ==> scroll ==> stop ==> scroll ==> stop ==>...
),因此方法内部的逻辑将被执行多次 or/and,并且由于存在计算和逻辑(if
和 else
),这可能会导致影响UI 的响应能力。如果用户快速滚动,则不会发生这种情况,它可能会调用一次,解释为单个滚动。
解决方案:
- 尽可能减少代码中一些繁琐的计算和逻辑。
- 使用
Coordinator Layout
as a root layout instead of LinearLayout
and set some Behaviours
that your child Views
should follow inside the CoordinatorLayout
。否则使用 boolean
准备逻辑,这将确保您的方法 onSrollChange
的内容不会被调用多次,而只会在用户最终完成整个慢速滚动时调用一次。
以上是在 ConstraintLayout
和 Guideline
的帮助下完全可行的。因此,当您向上滚动时,以编程方式将指南设置为最小值,而当您向下滚动时,将指南设置为正常。
下面是 xml 示例
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.constraint.Guideline
android:id="@+id/viewPagerTopGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.1" />
<android.support.constraint.Guideline
android:id="@+id/viewPagerBottomGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/viewPagerBottomGuideline"
app:layout_constraintTop_toBottomOf="@+id/viewPagerTopGuideline">
</android.support.v4.view.ViewPager>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/viewPagerBottomGuideline"/>
</android.support.constraint.ConstraintLayout>
您也可以将视图放在 NestedScrollView
中。然后滚动你可以像这样设置指南
@BindView(R.id.viewPagerBottomGuideline)
Guideline guideLine;//have Used ButterKnife
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) guideLine.getLayoutParams();
params.guidePercent = 0.20f; // 45% // range: 0 <-> 1
guideLine.setLayoutParams(params);
我刚刚实现了向上滚动,那么您也必须为向下滚动实现相同的功能。
我建议您使用 CoOrdinate Layout 作为主布局(根布局)。
那么您需要做的就是通过 Java 或编码设置此行为,例如折叠工具栏。我已经实现了同样的事情,this link 真的帮了我很多。请点击 link 试一试。
(https://github.com/teocci/AndroidGuidenotes/wiki/Handling-Scrolls-with-CoordinatorLayout)
我正在制作类似于最近 android 的状态栏的布局。
我有两个 Views
容器。 ViewPager
和 RecyclerView
。
默认行为应该是当我滚动 RecyclerView
时,我希望 ViewPager
减小尺寸,反之亦然。
逻辑:
viewPagerMaxHeight = 200;
if scrollTop
is ViewPager.height > viewPagerMaxHeight?
YES: Prevent Scroll and Decrease ViewPager size apropriatry
No: Scroll RecyclerView
if scrollBottom
did we scroll to position 0?
YES: Start increasing ViewPager size
No: Scroll RecyclerView
几点注意事项:
- RecyclerView
包含各种大小的项目。
- 有时会删除和添加项目
- 这是一个简单的 RecyclerView,不是
就像在它们相互折叠的通知中一样。
我可以自己构建大部分逻辑,但我无法为 RecyclerView
创建一个合适的监听器,它将 return 滚动的方向和数量。
防止 RecyclerView
滚动是一个奖励
编辑:
我在github
上做了一个例子v.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
Log.e("scrollY", ""+scrollY);
Log.e("oldScrollY", ""+oldScrollY);
Log.e("currentHeight", ""+currentHeight);
if(scrollY == 200) {
Log.e("==200", "JU");
} else if (scrollY < 200) {
Log.e("<200", ""+currentHeight);
if(currentHeight < fullHeight) {
Log.e("current<full", Integer.toString(deltaScroll));
deltaScroll = oldScrollY - scrollY;
currentHeight = currentHeight + deltaScroll;
if(currentHeight > fullHeight) {
currentHeight = fullHeight;
}
ku.getLayoutParams().height = currentHeight;
ku.requestLayout();
}
v.scrollTo(0, 200);
} else if (scrollY > oldScrollY) {
Log.e("Scroll DOWN", "" + Integer.toString(scrollY));
deltaScroll = scrollY - oldScrollY;
currentHeight = currentHeight - deltaScroll;
if(currentHeight > minHeight) {
ku.getLayoutParams().height = currentHeight;
ku.requestLayout();
v.scrollTo(0, 200);
} else {
currentHeight = minHeight;
ku.getLayoutParams().height = minHeight;
ku.requestLayout();
}
}
}
});
我正在为 RecycleView
设置填充,并将 NestedScrollView
滚动到第一项,这样填充就看不到了。这让我即使已经在顶部也可以滚动顶部。
一切似乎都正常,但正如您会注意到的那样,当缓慢滚动时滚动是 "jumpy"(如果滚动足够快则不会发生)。
我猜这是因为 NestedScrollView
本身会改变高度,例如向上滚动时,也会向下滚动。
根据您当前的代码:
Everything seems to work, but as you will notice scrolling is "jumpy" when scrolling slowly...
YES ,这是因为当用户缓慢滚动时方法 onScrollChange
可能会被调用多次(由于系统误解 scroll ==> stop ==> scroll ==> stop ==> scroll ==> stop ==>...
),因此方法内部的逻辑将被执行多次 or/and,并且由于存在计算和逻辑(if
和 else
),这可能会导致影响UI 的响应能力。如果用户快速滚动,则不会发生这种情况,它可能会调用一次,解释为单个滚动。
解决方案:
- 尽可能减少代码中一些繁琐的计算和逻辑。
- 使用
Coordinator Layout
as a root layout instead ofLinearLayout
and set someBehaviours
that your childViews
should follow inside theCoordinatorLayout
。否则使用boolean
准备逻辑,这将确保您的方法onSrollChange
的内容不会被调用多次,而只会在用户最终完成整个慢速滚动时调用一次。
以上是在 ConstraintLayout
和 Guideline
的帮助下完全可行的。因此,当您向上滚动时,以编程方式将指南设置为最小值,而当您向下滚动时,将指南设置为正常。
下面是 xml 示例
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.constraint.Guideline
android:id="@+id/viewPagerTopGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.1" />
<android.support.constraint.Guideline
android:id="@+id/viewPagerBottomGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/viewPagerBottomGuideline"
app:layout_constraintTop_toBottomOf="@+id/viewPagerTopGuideline">
</android.support.v4.view.ViewPager>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/viewPagerBottomGuideline"/>
</android.support.constraint.ConstraintLayout>
您也可以将视图放在 NestedScrollView
中。然后滚动你可以像这样设置指南
@BindView(R.id.viewPagerBottomGuideline)
Guideline guideLine;//have Used ButterKnife
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) guideLine.getLayoutParams();
params.guidePercent = 0.20f; // 45% // range: 0 <-> 1
guideLine.setLayoutParams(params);
我刚刚实现了向上滚动,那么您也必须为向下滚动实现相同的功能。
我建议您使用 CoOrdinate Layout 作为主布局(根布局)。 那么您需要做的就是通过 Java 或编码设置此行为,例如折叠工具栏。我已经实现了同样的事情,this link 真的帮了我很多。请点击 link 试一试。
(https://github.com/teocci/AndroidGuidenotes/wiki/Handling-Scrolls-with-CoordinatorLayout)