What is layout_collapseParallaxMultiplier used in CollapsingToolbarLayout ?
I have seen the android developer doc, but I didn't understand.
please explain this parameter & it's effect when it used with layout_collapseMode with example.
Below is a simple example of xml.
<android.support.design.widget.CollapsingToolbarLayout ... >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:src="#drawable/random_pattern"
android:scaleType="fitXY"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.75"/>
</android.support.design.widget.CollapsingToolbarLayout>
In very simple words:
When scrolling we see the following - appbar image starts hiding under the content and beyond the top edge of the screen.
Parameter layout_collapseParallaxMultiplier determines what part of the image (in percent) will be hidden under the bottom content.
So, for example, setting this parameter to value 1.0 means that top boundary of appbar's image is bound to the top edge of the screen and doesn't move when scrolling. And main content is moving up the top of the image.
When the parameter is not set this corresponds to the value 0.5 and image will be overlapped above and below synchronously.
This was explained on Android Design Support Library:
In addition to pinning a view, you can use app:layout_collapseMode="parallax" (and optionally app:layout_collapseParallaxMultiplier="0.7" to set the parallax multiplier) to implement parallax scrolling (say of a sibling ImageView within the CollapsingToolbarLayout). This use case pairs nicely with the app:contentScrim="?attr/colorPrimary" attribute for CollapsingToolbarLayout, adding a full bleed scrim when the view is collapsed.
This is a behavior example when you use app:layout_collapseMode="parallax".
Related
I want to add a behaviour to my CollapsingToolbarLayout such that the "collapsible" content is sticky (image) in this case. Only the bottom sheet needs to be scrollable and it will overlay the images in the ViewPager. Attaching recording video for better understanding.
https://www.youtube.com/shorts/trmpy__f9Is
The expected behaviour is as shown the image below where the header should stick and footer should overlay it when scrolled.
Code is something like this-
<androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.appbar.CollapsingToolbarLayout
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<androidx.viewpager2.widget.ViewPager2/>
<androidx.appcompat.widget.Toolbar />
<ConstraintLayoutForSomeContent/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Also tried playing with app:layout_collapseMode="pin" and app:layout_scrollFlags="noScroll" to CollapsibleToolbarLayout, AppBarLayout with no luck.
The other option was not making ViewPager part of the CollapsibleToolbarLayout which solves the purpose but then the ViewPager is not scrollable anymore as the touch is consumed by the overlaying CollapsibleToolbarLayout.
Is there a way this can be achieved.
Try This
add the below line in your view pager
app:layout_collapseParallaxMultiplier="1.0"
change the value you want between 1 to 0.9
So, I have a special case where the height of my appbarlayout fills the whole screen. I am using scroll|snap layout behavior for collapsingtoolbarlayout. The problem is that by default appbarlayout is collapsed when the user reaches more than 50 percent of the height of appbarlayout. For me, this behavior is not appropriate because with snap behavior this is difficult for the user to expand and collapse the appbarlayout.
I have already tried to expand or collapse it programmatically by putting checks on offset value in offset change listener but that doesn't help because the offset change listener gets called a lot of times and checks are not enough to serve the purpose.
<android.support.design.widget.AppBarLayout
android:id="#+id/activity_campaign_details_app_bar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:elevation="0dp">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/activity_campaign_details_collapsing_toolbar_bar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|snap">
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
Should it be set at the AppBarLayout sibling's parent or at the first Scrollable View inside its sibling?
With Material Design for Android, there are Views that let us work with the behavior of the layout depending on its surroundings, one of them is the CoordinatorLayout, as this CodePath guide mentions:
CoordinatorLayout extends the ability to accomplish many of the
Google's Material Design scrolling effects. Currently, there are
several ways provided in this framework that allow it to work without
needing to write your own custom animation code.
The one I'm interested in now is:
Expanding or contracting the Toolbar or header space to make room for the main content.
So, we would use the AppBarLayout with a Toolbar with app:layout_scrollFlags set and another ViewGroup sibling to the AppBarLayout with app:layout_behavior.
My question is: in what exact ViewGroup (or maybe View) should we put that
app:layout_behavior?
So far, I've tried with (And they have all worked, and they are all siblings to the AppBarLayout):
Scrolling View
First ViewGroup inside a Scrollable View
ScrollView inside a ViewGroup
And this one didn't work:
ViewGroup with no Scrollable View children.
There are multiple examples online, but none of them really state where should you put it, like:
http://www.ingloriousmind.com/blog/quick-look-on-the-coordinatorlayout/
https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout
https://developer.android.com/training/basics/firstapp/building-ui.html
https://www.bignerdranch.com/blog/becoming-material-with-android-design-support-library/
Check this link: https://developer.android.com/reference/android/support/design/widget/AppBarLayout.html
AppBarLayout also requires a separate scrolling sibling in order to
know when to scroll. The binding is done through the
AppBarLayout.ScrollingViewBehavior class, meaning that you
should set your scrolling view's behavior to be an instance of AppBarLayout.ScrollingViewBehavior. A string resource containing the
full class name is available.
They mentioned about that, it should be the View which will be shown under the AppBarLayout like this:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<!-- Your scrolling content -->
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<android.support.v7.widget.Toolbar
...
app:layout_scrollFlags="scroll|enterAlways"/>
<android.support.design.widget.TabLayout
...
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
My question is: in what exact ViewGroup (or maybe View) should we put
that app:layout_behavior?
And in this link: http://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout
Next, we need to define an association between the AppBarLayout and
the View that will be scrolled. Add an app:layout_behavior to a
RecyclerView or any other View capable of nested scrolling such as
NestedScrollView. The support library contains a special string
resource #string/appbar_scrolling_view_behavior that maps to
AppBarLayout.ScrollingViewBehavior, which is used to notify the
AppBarLayout when scroll events occur on this particular view. The
behavior must be established on the view that triggers the event.
Make sure you added the appbar_scrolling_view_behavior field in your String.xml
<!-- The class name to the ScrollingChildBehavior required for AppBarLayout -->
<string name="appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>
And as everyone knows we just can use this like below
<android.support.v7.widget.RecyclerView
android:id="#+id/rvSomeList"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
Its just for info not OP answer.
app:layout_behavior should be set to those views which are direct child of Coordinator layout
AppBarLayout also requires a separate scrolling sibling in order to
know when to scroll.
This description from Android is woefully incomplete and caused me hours of wasted time.
Scrolling sibling is a misnomer and need not be a scrolling view of any type.
For example, below my AppBarLayout, I'm using a ViewPager2 that will render a Fragment that will render a Scrollview, so I needed to set app:layout_behavior="#string/appbar_scrolling_view_behavior" directly on the ViewPager2 in the main layout, NOT the deeply nested Scrollview in the fragment layout.
I also have no use for scrolling the AppBarLayout or any of its children on or off the screen, so I falsely assumed I could get away with not setting the app:layout_behavior anywhere.
Wrong.
This reveals a more insidious issue: AppBarLayout requires the scrolling sibling, yes. But not just to "know when to scroll", but to actually adjust the size of the sibling to fit properly on screen alongside it! Otherwise, the sibling maintains its configured size and will be nudged downward offscreen by the height of the AppBarLayout! You can even see this in Android Studio's layout editor.
Long story short: If you're going to use an AppBarLayout, you need to mark one of your views with app:layout_behavior="#string/appbar_scrolling_view_behavior", whether it's a scroll view or not.
I had to add the following to the gradle file otherwise it gave me a compile error.
implementation 'com.google.android.material:material:1.0.0'
Hope this would help some others too!
For someone who uses CoordinatorLayout with FragmentContainer and AppBarLayout:
It is really good to set the app:layout_behavior also on the container (not just on NestedScrollView or RecyclerView). It deletes unnecessary bottom margin of the FragmentContainer and guarantees that the appbar hides when the keyboard is shown.
Does anyone know how can I achieve the new parallax scrolling effect - you can see the effect when you open an app on the PlayStore and try to scroll down, the content goes over the top image. How can I achieve that?
Google has recently announced Design support library and with this it has support for implementing Collapsing Toolbar.
In addition to pinning a view, you can use
app:layout_collapseMode="parallax" (and optionally
app:layout_collapseParallaxMultiplier="0.7" to set the parallax
multiplier) to implement parallax scrolling (say of a sibling
ImageView within the CollapsingToolbarLayout)
Example:
<android.support.design.widget.AppBarLayout
android:layout_height="192dp"
android:layout_width="match_parent">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
You could try this (FadingActionBar library):
https://github.com/ManuelPeinado/FadingActionBar
Try an example of this library on android: https://play.google.com/store/apps/details?id=com.manuelpeinado.fadingactionbar.demo
EDIT: Rather than third party library use this AppBarLayout and CollapsingToolbarLayout http://android-developers.blogspot.in/2015/05/android-design-support-library.html
try the ObservableScrollView library
https://github.com/ksoichiro/Android-ObservableScrollView
demo application from play store
https://play.google.com/store/apps/details?id=com.github.ksoichiro.android.observablescrollview.samples2
sample demo,
Actually few minutes after posting this question I bumped on two of libraries that do the effect I'm looking for and even more.
Here are links to them:
Parallax Scrolls
Paralloid
There's a library called FadingActionBar that does exactly what you're asking for. You can find the library on GitHub (click) and a Demo-Application in the Play Store (click).
Usage would be something like this:
FadingActionBarHelper helper = new FadingActionBarHelper()
// Set the ActionBar drawable - basically the color
.actionBarBackground(R.drawable.ab_background)
// Set the Header - usually an image
.headerLayout(R.layout.header)
// Set the main layout
.contentLayout(R.layout.activity_scrollview);
setContentView(helper.createView(this));
helper.initActionBar(this);
You may custom the parallax animation by tracking the Recycler View Scrolling
Firstly in the image view layout. Set the parent layout is smaller than image view so that prevent the image outside the bound when set translationY
<android.support.percent.PercentRelativeLayout
android:id="#+id/index_level6_image_section"
android:layout_width="match_parent"
android:layout_height="200dp"
android:clipChildren="false">
<ImageView
android:id="#+id/index_level6_parallaxImage"
android:layout_width="match_parent"
android:layout_height="240dp"
android:layout_centerInParent="true"
android:background="#color/timberwolf"
android:layout_marginTop="-20"
android:layout_marginBottom="-20"
android:scaleType="centerCrop"
app:imageUrl="#{level6CellViewModel.level6ImageUrl}" />
</android.support.percent.PercentRelativeLayout>
After that, track the recycler view scrolling effect and transitionY the image view.
*** I am using rxbinding and kotlin for implementation. You may use traditional listening method and java approach with the same idea.
RxRecyclerView.scrollEvents(recyclerView)
.subscribe { event ->
// get the visible cell items of the recycler view
val firstVisible = layoutManager.findFirstVisibleItemPosition()
val visibleCount = Math.abs(firstVisible - layoutManager.findLastVisibleItemPosition())
/** loop the visible cell items from the recycler view */
for (i in firstVisible..firstVisible + visibleCount) {
event.view().layoutManager?.findViewByPosition(i)?.let { cellItem ->
/** only for index cell level 6 parallax image */
cellItem.findViewById(R.id.index_level6_parallaxImage)?.let { imageView ->
/** setting the parallax effect */
val translationY = (cellItem.top - cellItem.height) / level6ParallaxRate
imageView.translationY = -translationY
}
}
}
}
let's say I have a view that is made up of 2 layers -> top layer and bottom layer. I place them both in a frame layout.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- bottom layer -->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/some_image_you_shouldnt_shrink"/>
<!-- top layer -->
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/somewhat_transparent"/>
</FrameLayout>
now, presumably, when i tap on the editText, the keyboard will pop up, and shrink the size of the edit text. However, it seems that the bottom layer is ALSO getting resized. How do i prevent this bottom layer from getting resized?
Note: the framelayout is in a fragment, and the activity that holds this fragment must declare android:windowSoftInputMode="adjustResize".
EDIT*********
Just to clarify, i want the editText layer to adjust as high as the keyboard needs to. however, i don't want the image behind it to adjust at all
i only have 1 activity that handles these similar types of fragments.
You can't prevent a single view from resizing if you set android:windowSoftInputMode="adjustResize". But if you just want to set a non-resizing background, there is a work-around. Instead of setting the background image in the ImageView through XML, add this in your onCreate() method
getWindow().setBackgroundDrawableResource(R.drawable.some_image_you_shouldnt_shrink);
try this in the manifest
android:windowSoftInputMode="stateVisible|adjustPan"