Recyclerview move to and visibility going off-screen - android

When I set something visible in my recycler view "visibility = VISIBLE" it goes offscreen if its close to bottom or top, I wanted to know if is there any way to make the recyclerview focus in it when VISIBLE is called.
Another problem I have is with move to "(ctx as MainActivity).moveTo(id.toInt() + 7)" << for those who asked moveTo jumps to target item in the recycler view.
I am having a hard time to make it look good and jump to the right spot, I think the toolbar with "app:layout_scrollFlags="scroll|enterAlways"" might be messing with it.
I tried adding numbers to the move-to and I managed to make the keyboard move things up when opened to keep focus on edit text but couldn't solve the other problems.
The toolbar
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:layout_weight="1"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
app:title="Gerenciador de Prioridades"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
On top of that I get some null error first time I try to use moveto so I made an if to avoid it and +7 to make sure it goes down, dont know if it's the best approach.
if (id != 1.toLong()) {
(ctx as MainActivity).moveTo(id.toInt() + 7)
}
I really appreciate any help or suggestions you can provide.
Edit :
When this item is too close to the botom and with visibility GONE it goes offscreen when I click it for visibility = VISIBLE , so im wondering if there is anyway to make it go up or something to keep it inside the scroll view but visible for the user.

Use include to place you view in the app bar layout
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:layout_weight="1"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
app:title="Gerenciador de Prioridades"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways">
</androidx.appcompat.widget.Toolbar>
<include layout="#layout/content_main" />
</com.google.android.material.appbar.AppBarLayout>
Then add your views to the content main layout , this should fix the issue

Related

Prevent a child in ScrollView from being scrolled out of the screen

Somehow I came across Reddit app, and wondered how their Scrolling mechanism works. As you can see from the gif, there is a Menubar (Up/Downvote-comment-share bar) that always locates within the screen and can’t be scrolled out of the screen when scrolled up/down. When scrolling up, it will be located underneath the Toolbar (the grey bar at the top). When scrolling down, it will be located above the EditTextView (the Add-a-comment bar at the bottom).
Relative layout
|-->Toolbar (android:id="#+id/toolbar")
|-->ScrollView (android:layout_below="#id/toolbar")
|-->Child (This child is located underneath the Toolbar when scrolling up)
|-->Child
|-->Child
If I wanted to write this page, what dependencies, widgets or concepts
would I need to use or look into?
Note: You can give me snippets of codes if you prefer :)
you can use the CoordinatorLayout layout to realize that function. the layout like that. for details, you can see this blog in the medium.
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/behavior_demo_coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways|snap"
android:background="?attr/colorPrimary" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/behavior_demo_swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="#+id/behavior_demo_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>
The toolbar (containing the menu) is outside of the ScrollView in the XML.
Or it may not even be a ScrollView at all.
It may just be view recycling- but even so the toolbar is outside of that XML layout used for displaying the content.
For hiding the TopBar and bottomBar (comment box) I recommend you use Animation
Simply call animation like
//on scrollUp
topLayout.animate().translationY(-300).alpha(0.0f).setDuration(300);
// this will make the layout go up and fade to invisible
//on scrollDown
topLayout.animate().translationY(0).alpha(1.0f).setDuration(300);
// this will make the layout come down and fade to be visible
Implement this will both Views using addOnScrollListener() or I suggest you to have a look at this answer for implementing scroll Up/Down using CoordinateLayout
Hope this will help!

Collapse app bar layout when scroll reach 20 percent of the height. I want snap to work as well

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>

How to let only specific fragments scroll inside a ViewPager of CoordinatorLayout?

Background
I have a viewPager, with 3 fragments and tabs for them. Each fragment has an intro phase (of its own) that doesn't have any scrollable content.
After leaving the intro phase, there is a recyclerView that the user can scroll in.
The problem
I need to use the new design library, so that when scrolling (only via recyclerView), it will hide the actionBar and let the tabs still be shown.
When the user goes to a fragment that doesn't have a scrollable content yet, the actionBar should re-appear, similar to what "Google Play Newsstand" has. In fact, I would even be happy to have what they have: as soon as you start swiping left/right, re-show the action bar.
Thing is, if I follow the guidelines and samples, I have 2 issues:
The non-scrollable phase for fragments gets truncated at the bottom, as if it can get scrolled.
I can't find how to re-show the actionBar, and make it stuck there till I switch to a scrollable content (either by switching to another fragment, or when the content of the current fragment changes to a scrollable content).
What I've tried
Here's a short snippet of the current layout XML file of the activity:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/activity_main__coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/activity_main__appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:layoutDirection="ltr"
android:theme="?attr/actionBarTheme"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute"/>
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:tabGravity="fill"
app:tabIndicatorColor="#FFffffff"
app:tabIndicatorHeight="3dp"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
<include layout="#layout/fabs"/>
</android.support.design.widget.CoordinatorLayout>
<include
layout="#layout/sliding_menu"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"/>
</android.support.v4.widget.DrawerLayout>
The fragments have a layout of a ViewAnimator that just switches between phases, while one of them is the non-scrollable content, and the other is the RecyclerView.
I've tried to add a NestedScrollView/ScrollView the non-scrollable content , and force it to fill itself, using android:fillViewport="true" , but it didn't work. For ScrollView it didn't even allow to scroll.
EDIT: Another thing I've tried is to use addOnPageChangeListener on the viewPager, so that in onPageSelected I could set the flags for the toolbar :
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
params.setScrollFlags(!needScrolling? 0 : LayoutParams.SCROLL_FLAG_SNAP | LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | LayoutParams.SCROLL_FLAG_SCROLL);
It works, but it has a issues too:
while scrolling horizontally, I can see the content of the non-scrollable fragment being truncated, and when going to the new fragment (stop touching the screen, to let it snap to the fragment), only then it shrinks its size to fit the correct space.
The toolbar doesn't get re-shown.
If the toolbar is hidden due to scrolling on another fragment, and I'm now on the non-scrollable fragment, it actually gets less space to fill than it's supposed to, so it has empty space at the bottom.
EDIT: one solution is to add an empty view of the same height of actionbar (layout_height="?actionBarSize") at the bottom of the non-scrollable fragments's content. However, when the action bar is hidden, I can see the view, so there is empty space. I still need to know how to re-show the actionbar on this case.
The question
How do I set a different behavior for the toolbar, so that it will re-show and stuck on certain states, yet be scrollable only when there is a RecyclerView shown on the current fragment?

How to keep the toolbar fixed at the top when AppBar collapses/expands?

Overview
I am trying to implement one of the Scrolling Techniques, Flexible space with overlapping content, described in Material Design.
Flexible space with overlapping content
Content can overlap the app bar.
Behavior:
The app bar’s starting position should be located behind the content.
Upon upward scroll, the app bar should scroll faster than the content,
until the content no longer overlaps it. Once anchored in place, the
app bar lifts up to allow content to scroll underneath.
https://www.google.co.in/design/spec/patterns/scrolling-techniques.html#scrolling-techniques-scrolling
Problem
However, the problem is,
the title in my AppBar scrolls down when expanded and hides below the overlapping content.
Here, my toolbar is hidden below the overlapping CardView.
When the appbar is collapsed, the toolbar and hence the Title slides up from below.
Code
Here's my Code:
activity-main.xml
<android.support.design.widget.CoordinatorLayout
...
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<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:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="top"
android:background="?attr/colorPrimary"
app:layout_collapseMode="pin"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
...
I have also added these in my MainActivity's onCreate function
setSupportActionBar(toolbar);
collapsingToolbarLayout.setTitle("App Name");
I want the toolbar(with the tile and the other contents, which I will add later) to stay at the top irrespective of the appbar being expanded or collapsed.
I have read the documentations, gone through many posts and tutorials, watched a lot of videos but failed to find a working solution or any related solutions at all.
If anyone has some idea on how to fix this, please suggest. Thanks for helping.
I was looking for a solution myself when I found the answer in the comments on a similar issue report.
Basically you call setTitleEnabled() on your CollapsingToolbarLayout like this:
CollapsingToolbarLayout.setTitleEnabled(false);
You can do this in xml as well, by adding this to your CollapsingToolbarLayout:
app:titleEnabled="false"
By setting it to false, you'll get the desired behaviour. The title stays fixed to the top of the screen.
The Toolbar itself was actually already at the top, but this makes the title stay there as well, instead of translating between the bottom of the CollapsingToolbarLayout and the Toolbar.
I have acheived this by adding below code inside Toolbar tag.
app:layout_collapseMode="pin"
In my case I needed to add app:titleEnabled="false" to the CollapsingToolbarLayout AND app:layout_collapseMode="pin" to the android.support.v7.widget.Toolbar
Now the toolbar stays pinned to the top of the screen, irrespective of whether the user scrolls up or down.
To keep title at top, simple put this attribute to your CollapsingToolbarLayout:
app:expandedTitleGravity="top"

How does the Android L contacts app collapse its toolbar?

I've been trying to reproduce the way that the Contacts app on version 5.0 collapses the toolbar when the listview is scrolled.
Gallery of screenshots demonstrating the desired interaction
Note the collapse of the toolbar in stages, where it displays search+last contact, fades last contact, collapses last contact, collapses search, leaving only the tabs.
So far, I have a toolbar sitting above a recyclerview in a LinearLayout, and the toolbar is used as an actionbar, not standalone.
I can't figure out how to intercept the touch event on the recyclerview and make it shrink the toolbar, and then return the scroll event to the recyclerview. I tried putting the entire thing in a scrollview, but then the recyclerview couldn't calculate it's height properly and displayed no content. I tried overriding onscroll on the recyclerview, and found that it will only notify me when a scroll event started, and provide me with the first visible card id.
The way that looks right, but I can't get working for the life of me, is this:
getSupportActionBar().setHideOnContentScrollEnabled(true);
Which returns:
Caused by: java.lang.UnsupportedOperationException: Hide on content scroll is not supported in this action bar configuration.
Using a traditional actionbar, putting a toolbar below it, and setting hideoncontentscrollenabled also didn't work, scrolling never triggered the hide method on the actionbar.
-- edit --
I was able to get hideOnContentScrollEnabled working on a listview with a traditional actionbar, but the behavior is not the same as the contacts app. This is clearly not the method they used-- it simply triggers .hide() on the actionbar when a fling event occurs on a listview, which is notably different from the contacts app, which drags the toolbar along with the scroll event.
-- /edit --
So I abandoned that route, and put fill_parent on the cardview height, and animated a collapse on the toolbar. But how do I trigger it so that it follows the touch event and then returns the touch event to the recyclerview?
activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/actionBarSize"
android:background="#color/colorPrimary"
/>
<fragment android:name="me.myapplication.FragmentTab"
android:id="#+id/tab_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
fragment_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="8dp"
android:background="#eeeeee"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
styles.xml
...
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
...
MainActivity.java
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
// Disable the logo in the actionbar, as per material guidelines
toolbar.getMenu().clear();
toolbar.setTitle("My toolbar");
setSupportActionBar(toolbar);
I haven't investigated the source code yet but this guy seems to have made life easy yet enlightening.
https://github.com/ksoichiro/Android-ObservableScrollView
EDIT
Google has just released Android Design Library. Please take a look as it contains all the effects of collapsing toolbars and much more.
Well, I have no idea how they do it, but... why don't you take a peek to the source code? Luckily for us, the Contacts app is still open-source on Android L (others weren't as lucky as Contacts, like Mail, which does not work anymore on L; or Keyboard, which they stopped updating anymore since the launch of their propietary Google Keyboard).
Anyway, here's the source code I think you should look at:
https://github.com/android/platform_packages_apps_contacts/blob/master/src%2Fcom%2Fandroid%2Fcontacts%2Factivities%2FActionBarAdapter.java
Note the method update(boolean skipAnimation) in Line 311, which calls animateTabHeightChange(int start, int end) (Line 437).
My guess is all the magic happens there ;-)
As of June 2015, your desired effect can be accomplished via the so called CollapsingToolbarLayout of the new design support library.
Based on the sample code here, I am figuring that:
the search cardview is child of the toolbar
the missed call cardview belongs to the collapsingtoolbar with the collapseMode attribute set to pin
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="112dp"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="?attr/actionBarSize"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed|enterAlways">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="false"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways">
<!-- Search layout -->
<android.support.v7.widget.CardView
</android.support.v7.widget.CardView>
</android.support.v7.widget.Toolbar>
<!-- Last call card view-->
<android.support.v7.widget.CardView
app:layout_collapseMode="pin">
</android.support.v7.widget.CardView>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#color/primary_color"
app:layout_scrollFlags="scroll"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
No third party library is required now! Android is officially providing library. You can collapse the toolbar and do many other tweaks.
Check this android-developer's blog
And don't forget to add this dependency in your build.gradle file.
compile 'com.android.support:design:22.2.0'
I found this library that seems to do what you're looking for: https://github.com/kmshack/Android-ParallaxHeaderViewPager and this https://github.com/flavienlaurent/NotBoringActionBar
You can play the video to see the behavior: https://www.youtube.com/watch?v=sCP-b0a1x5Y
It might not be the 'new' standard way of doing it with ToolBar, but it might give you an idea by inspecting the code. It seems to attach a OnScrollListener to the scrolling content and then trigger changes on the size of the bar.
For me https://mzgreen.github.io/2015/06/23/How-to-hideshow-Toolbar-when-list-is-scrolling%28part3%29/ has helped. A source code is found here: https://github.com/mzgreen/HideOnScrollExample/tree/master/app/src/main.
A RecycleView in your layout should look like:
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
Note that after starting an application 2 toolbars appear (actionbar and toolbar). So in your activity.java you should write so:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide ActionBar.
supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
getSupportActionBar().hide();
setContentView(R.layout.your_activity_layout);
...
The toolbar is customized as shown here: https://stackoverflow.com/a/26548766/2914140. I mean, it appears without title and any other elements, so you can add them in a layout.
Android's Contact app doesn't have an easy plug-and-play solution that you can grab for use in your own app.
It does a full implementation, essentially doing it the same way you would do it if you were implementing it from scratch. For context, before looking at the code, keep in mind how the views are laid out:
https://github.com/android/platform_packages_apps_contacts/blob/lollipop-release/res/layout/quickcontact_activity.xml
The MultiShrinkScroller is a FrameLayout which intermediates the scrolling behavior, but the main stuff is in a LinearLayout, so reducing the height of the higher views will "scroll" the lower views upwards.
The key file for the implementation is this one:
https://github.com/android/platform_packages_apps_contacts/blob/lollipop-release/src/com/android/contacts/widget/MultiShrinkScroller.java
public void scrollTo(int x, int y) {
final int delta = y - getScroll();
boolean wasFullscreen = getScrollNeededToBeFullScreen() <= 0;
if (delta > 0) {
scrollUp(delta);
} else {
scrollDown(delta);
}
updatePhotoTintAndDropShadow();
updateHeaderTextSizeAndMargin();
//... other stuff
}
private void scrollUp(int delta) {
// Collapse higher views first
if (getTransparentViewHeight() != 0) {
final int originalValue = getTransparentViewHeight();
setTransparentViewHeight(getTransparentViewHeight() - delta);
setTransparentViewHeight(Math.max(0, getTransparentViewHeight()));
delta -= originalValue - getTransparentViewHeight();
}
// Shrink toolbar as needed
final ViewGroup.LayoutParams toolbarLayoutParams
= mToolbar.getLayoutParams();
if (toolbarLayoutParams.height > getFullyCompressedHeaderHeight()) {
final int originalValue = toolbarLayoutParams.height;
toolbarLayoutParams.height -= delta;
toolbarLayoutParams.height = Math.max(toolbarLayoutParams.height,
getFullyCompressedHeaderHeight());
mToolbar.setLayoutParams(toolbarLayoutParams);
delta -= originalValue - toolbarLayoutParams.height;
}
// Finally, scroll content if nothing left to shrink
mScrollView.scrollBy(0, delta);
}
updatePhotoTintAndDropShadow(); and updateHeaderTextSizeAndMargin(); handle the change in tint and text as it gets collapsed so that it turns into the look and feel of a regular ActionBar/ToolBar.
You could grab the MultiShrinkScroller file itself and adapt it for your own use, but there are probably easier implementations nowadays (including those from Android's design library).

Categories

Resources