I'm making a layout similar to recent android's status bar.
I have two Views
inside container. ViewPager
and RecyclerView
.
The default behavior should be that when I scroll RecyclerView
, I want ViewPager
to decrease in size and vice versa.
Logic:
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
Few notes:
- RecyclerView
contains items of various size.
- Sometimes items are removed and added
- It is a simple RecyclerView, not
like in notifications where they collapse on each other.
I can construct most of the logic myself but I could not make a proper listener for RecyclerView
which will return direction and amount that was scrolled.
preventing RecyclerView
from scrolling is a bonus
EDIT:
I have made an example on 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();
}
}
}
});
I'm setting padding for RecycleView
and scrolling NestedScrollView
to the first item so the padding is not visible. this allows me to scroll TOP even when already at the TOP.
Everything seems to work, but as you will notice scrolling is "jumpy" when scrolling slowly (won't happen if scrolled fast enough).
My guess is that is happening because NestedScrollView
itself changes height and while scrolling up for example, scroll down happens as well.
The above is totally doable with the help of ConstraintLayout
and Guideline
. So when you scroll up set the guideline programmatically to minimum and when you scroll down set the guildline back to normal.
Below is a xml sample for the same
<?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>
You can place the views inside a NestedScrollView
as well. Then onscroll you can set the guideline like this
@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);
I have just implemented on scroll up, then you would have to implement the same for scroll down as well.