I have a RecyclerView in a LinearLayout. How can I have LinearLayout "slide" upwards until it hits the App Bar, whereby the RecyclerView should then begin scrolling the items as usual. Likewise, scrolling the list down will begin to "slide" the entire container down when the the first item is reached in the list until the container returns to its starting position.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/nearby_stops"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="#dimen/half_padding"
android:paddingTop="#dimen/half_padding"
android:scrollbars="none" />
</LinearLayout>
I looked at https://github.com/umano/AndroidSlidingUpPanel, however it does not support RecyclerView and the moment.
Put the RecyclerView inside a Fragment, so make an XML like so for the Fragment:
This is your XML for the RecyclerView
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/nearby_stops"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="#dimen/half_padding"
android:paddingTop="#dimen/half_padding"
android:scrollbars="none" />
</LinearLayout>
Then for the Activity hosting the Fragment just add a FrameLayout for the Fragment:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Put other views here -->
<FrameLayout
android:id="#+id/slidingFragmentContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Then inside your Activity when you instantiate the Fragment do the following:
SampleFragment listFragment = new SampleFragment();
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.abc_slide_in_bottom, R.anim.abc_slide_out_bottom,
R.anim.abc_slide_in_bottom, R.anim.abc_slide_out_bottom)
.addToBackStack(null)
.add(R.id.slidingFragmentContent, listFragment)
.commit();
The animations R.anim.abc_slide_in_bottom and R.anim.abc_slide_out_bottom are available in the Android API.
I also noticed you're not setting any orientation for your LinearLayouts. Set an orientation like so android:orientation="..."
You can assign a Button to show the Fragment, like so:
mButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
showFragment();
}
});
--------------------------------------------------------------------
To get the RecyclerView to scroll up as you scroll it just use the following:
Create an XML layout like this for your Activity:
<android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="#dimen/map_view_height"
android:orientation="vertical"
android:fitsSystemWindows="true">>
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsingToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<YourCustomViewContainingTheMap
app:layout_collapseMode="parallax"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
Inflate your Fragment inside the FrameLayout and then as you scroll up it should do a parallax animation on the Map. If you don't want a Parallax effect just set app:layout_CollapseMode="pin"
Here is a sample app I created, you can see as I scroll up on the RecyclerView it slides up:
(Please note the Frame Animations on GIFs is not that great)
To get a shadow behind the sliding list on your map, just set app:layout_collapseMode to parallax and then add another view in front of your MapView inside the CollapsingToolbarLayout which can be your mask, it can be be a simple view, and then you can adjust it's alpha value as you scroll up the list.
It's better to use the native android views at your disposal, I noticed that AndroidSlidingPanelLayout has around 43 issues.
Related
I have a fragment which uses a coordinator layout to show an AppBarLayout and a recycler view like this:
The layout file is thus far:
<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="wrap_content"
app:elevation="4dp"
android:layout_height="wrap_content">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|snap">
<!-->Content removed<-->
</RelativeLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/fragment_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
The problem I'm having is that if I fling the recycler view so that the list scrolls all the way to the top, the AppBarLayout doesn't reveal unless I specifically pull down again. Is there a scroll flag to make the AppBarLayout come down when the recycler view reaches the top, as if it's attached to the first item in the recycler view?
No, transferring inertial is a known issue with nested scrolling in general, both with the platform APIs and those used by CoordinatorLayout.
I have the following layout
<?xml version="1.0" encoding="utf-8"?>
<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/coordinator_bracket_activity"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/activity_fragment"
android:layout_height="match_parent"
android:layout_width="match_parent">
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/app_bar_bracket_activity"
layout="#layout/app_bar" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foregroundTint="#color/colorAccent"
app:tabMode="fixed"
app:tabMaxWidth="0dp"
app:tabGravity="fill"/>
<mypackage.NonSwipeViewPager
android:id="#+id/tabs_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
The nonswipeviewpager was just a custom class where I inherited a viewpager to disable some stuff.
Anyway, I have a button on my app bar that needs to call a fragment that needs to cover the whole screen. I would call it and add a fragment on the frame layout. It worked before I added a viewpager for tab layouts. Now I'm not sure how to deal with the viewpager.
FragmentTransaction ft = mFM.beginTransaction();
mCustomFragment = CustomFragment.newInstance(mObject, mListOfObjects());
ft.replace(R.id.activity_fragment, mCustomFragment , "CustomFragment");
ft.addToBackStack(null);
ft.commit();
This is on my clicklistener of that button on the app bar.
Thoughts?
Views are drawn in the order they are defined in your XML. If you want a View on top of another view it should appear after it or you try to use:
https://developer.android.com/reference/android/view/View.html#bringToFront()
i'm using a Material swipe tab to show with swipe 3 different fragment layout.
This is the xml layout for swipe tab:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<include
android:id="#+id/tool_bar"
layout="#layout/tool_bar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<com.android4devs.slidingtab.SlidingTabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
></android.support.v4.view.ViewPager>
</LinearLayout>
Now the xml layout fragment of swipe have a button fixed into bottom of layout so when i swipe to this fragment the layout of fragment is cut see image:
there some way to fix the layout fragment into ViewPager or a way for scroll it with a scroller view?
Thanks
In your second Fragment, you can use
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.fullScroll(View.FOCUS_DOWN);
}
});
To scroll your ScrollView to the bottom, so your Button will be totally visible.
I want to create a Fragment with a RecyclerView that slides up and shows more items as you slide it up.
Here is an example of what I am talking about.
Initial Creation:
User Swipes Up to slide RecyclerView up, shows more items:
There are a few issues, I would like to not use a CoordinatorLayout, and I would like to set it to where the items in the RecyclerView stack up directly on top of the EditText.
This is the layout code I am using:
<android.support.design.widget.CoordinatorLayout
android:id="#+id/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:visibility="visible">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#android:color/transparent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsingToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<View
android:id="#+id/emptyView"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#android:color/transparent"
app:layout_collapseMode="parallax"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="#+id/editText"
android:paddingLeft="16dp"
android:inputType="textAutoCorrect"
android:layout_centerVertical="true"
android:background="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="56dp"/>
</RelativeLayout>
</RelativeLayout>
And I get something like this:
This is definitely not scalable, and empty view would need to be consistently measured.
I solved this by using a custom TouchListener all of the other solutions were very basic and limited to a specific and boxed use-case.
The way I did this was to implement a new TouchListener based off of this library:
BounceTouchListener
I get the following results:
Use RecyclerView with 2 types of rows:
Empty row/rows colored gray (without divider)
Rows with content as you already have
The RecyclerView will have to match_parent to the entire fragment
So you will get the right effect of a "blank" area on top of the RecyclerView.
You can use setReverseLayout of LinearLayoutManager
Used to reverse item traversal and layout order. This behaves similar
to the layout change for RTL views. When set to true, first item is
laid out at the end of the UI, second item is laid out before it etc.
For horizontal layouts, it depends on the layout direction. When set
to true, If RecyclerView is LTR, than it will layout from RTL, if
RecyclerView} is RTL, it will layout from LTR. If you are looking for
the exact same behavior of setStackFromBottom(boolean), use
setStackFromEnd(boolean)
I'm using a single activity - multiple fragments structure.On the activity i'm using v7 toolbar as action bar . I have sever fragments with viewpagers , some with tabs as well.In one of my fragments i have recyclerview . My goal is when i'm scrolling i wanna collapse the bar and hide the floating action button.My floating button is on inside a CoordinatorLayout so it can be displayed properly.But this is inside the layout of the fragment(which is part of a viewpager) , and the activity_main.xml has root element another CoordinatorLayout. Does the fragment CL intercepts the work of the CL inside the layout of the activity,because when i scroll the recycler nothing happens.
Should i use new toolbar for every fragment or i can use one in the
activity and implement different behavior for into fragments?
Can anyone references any examples of using CoordinatorLayout and
collapsing the bar within nested fragments?
activity_main.xml
<android.support.design.widget.CoordinatorLayout
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"
android:gravity="center"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
</android.support.design.widget.CoordinatorLayout>
The work of the main CoordinatorLayout wasn't intercepted.Adding app:layout_behavior to the frame layout which is fragment container did the job.
Looks like this now:
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity" />