I am using bottom TabLayout with ViewPager above the tabs, XML listed below:
<RelativeLayout
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar_wrapper"
layout="#layout/toolbar_main" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs_bottom_main"
style="#style/AppTabLayout"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_alignParentBottom="true"
app:tabGravity="fill" />
<View
android:id="#+id/view_black_line"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_above="#id/tabs_bottom_main"
android:background="#android:color/black" />
<NonSwipableViewPager
android:id="#+id/view_pager_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/view_black_line"
android:layout_below="#id/toolbar_wrapper"
android:background="#android:color/white" />
</RelativeLayout>
When the keyboard shows up, the whole View pushed up, I would like to hide the bottom TabLayout only (but keep the ViewPager above) once the keyboard shows up. How to achieve it?
P.S.
I have tried listening the keyboard show up event and set TabLayout visibility with mBottomTabLayout.setVisibility(isOpen ? View.GONE : View.VISIBLE);
But this will hide the whole ViewPager together with the TabLayout.
Add this to your manifest under activity tag in which you want to hide the TabLayout:
android:windowSoftInputMode="adjustPan"
It works after I change RelativeLayout to LinearLayout according to #Rahul Sharma's advice.
Then I used the KeyboardVisibilityEvent library:
KeyboardVisibilityEvent.setEventListener(this,
new KeyboardVisibilityEventListener() {
#Override
public void onVisibilityChanged(boolean isOpen) {
mBottomTabLayout.setVisibility(isOpen ? View.GONE : View.VISIBLE);
}
});
Related
In an Android project, I have an Activity that contains (from top to bottom) a header, a RecyclerView and a RelativeLayout.
Code sample :
<android.support.design.widget.CoordinatorLayout ...>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
...
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
This is the behaviour I want : the RelativeLayout is "folded" by default, i.e. under the RecyclerView. When the user swipes up, the RelativeLayout expands to use the whole screen, and folded again when swipes down.
What is the right way to do it ? As I want the RelativeLayout to be BELOW the RecyclerView when folded, and OVER it when expanded. I tried setting the dependencies between elements dynamically but couldn't manage to do so.
Thanks for any help or advice on how to organize the activity to get such a behaviour.
EDIT
This is the XML structure :
<CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</AppBarLayout>
<RecyclerView
android:id="#+id/top_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/app_bar"
android:layout_above="#+id/relativelayout_footer" />
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_alignParentBottom="true">
<TextView ...>
<RecyclerView
android:id="#+id/included_list"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="gone"/>
</RelativeLayout>
</RelativeLayout>
</CoordinatorLayout>
And the listener :
top_list.setVisibility(playlistOpened ? View.VISIBLE : View.GONE);
app_bar.setVisibility(playlistOpened ? View.VISIBLE : View.GONE);
included_list.setVisibility(playlistOpened ? View.GONE : View.VISIBLE);
Transition cb = new ChangeBounds();
cb.setDuration(1000);
TransitionManager.beginDelayedTransition(slider, cb);
playlistOpened = ! playlistOpened;
As you see, I switch the visibility of the elements in order to reorganise the view. When the included_list is set to VISIBLE, it pushes up the TextView.
The only problem is that the top_list and the app_bar disappear before being covered by the RelativeLayout. I tried adding a Listener to the Transition and do these when the transition ends, but it doesn't work (I guess because they're not set to GONE at the beginning, so the RelativeLayout can't move up). Any idea of how to do so ? Maybe I should open another question for it ?
Okay, a final attempt. I am back to RelativeLayout and added another one around the RecyclerView to fix its scrolling problem. However, transitions get tricky (and the listener complicated) then. In order to prevent the RecyclerView from popping away before the RelativeLayout with the TextView inside fully covers the latter, I had to include a fading transition to the RecyclerView, too. Hope this suits you.
XML:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
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.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/rlwithrecyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/rlwithtextview"
android:layout_alignParentTop="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/rlwithtextview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<TextView
android:layout_width="match_parent"
android:layout_height="400dp"
android:id="#+id/textview"
android:text="Just a test" />
</RelativeLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
onClick():
#Override
public void onClick(View v) {
RelativeLayout rlWithRecyclerView = findViewById(R.id.rlwithrecyclerview);
RelativeLayout.LayoutParams layoutParamsRlWithRecyclerView;
RelativeLayout rlWithTextView = findViewById(R.id.rlwithtextview);
RelativeLayout.LayoutParams layoutParamsRlWithTextView;
if (rlWithTextView.getLayoutParams().height == MATCH_PARENT) {
layoutParamsRlWithTextView = new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
layoutParamsRlWithRecyclerView = new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
layoutParamsRlWithRecyclerView.addRule(RelativeLayout.ALIGN_PARENT_TOP);
layoutParamsRlWithRecyclerView.addRule(RelativeLayout.ABOVE, R.id.rlwithtextview);
} else {
layoutParamsRlWithRecyclerView = new RelativeLayout.LayoutParams(MATCH_PARENT, 0);
layoutParamsRlWithTextView = new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
}
layoutParamsRlWithTextView.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
Transition changeBounds = new AutoTransition();
changeBounds.setDuration(500);
TransitionManager.beginDelayedTransition(rlWithRecyclerView, changeBounds);
TransitionManager.beginDelayedTransition(rlWithTextView, changeBounds);
rlWithRecyclerView.setLayoutParams(layoutParamsRlWithRecyclerView);
rlWithTextView.setLayoutParams(layoutParamsRlWithTextView);
}
Although I got credit for the two other answers, I will eventually delete them, since they don't solve the problem.
The new BottomNavigationView from support library v25.0.0 is supposed to hide when scrolling down, in order to see all the items from a list. However, in my testing scenario, the view hides when scrolling up. Any ideas what can cause this reverse behavior?
The inner_fragment is set up as a Fragment inserted inside the activity_main_framelayout_content Framelayout. XML layouts below:
main_activity.xml:
<android.support.design.widget.CoordinatorLayout
android:id="#+id/activity_main_coordinatorlayout"
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.support.v7.widget.Toolbar
android:id="#+id/activity_main_toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways">
<include layout="#layout/activity_main_spinner_layout"/>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/activity_main_framelayout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:fitsSystemWindows="true"/>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/activity_main_framelayout_navigation_drawer"
android:layout_width="#dimen/drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
android:background="#color/color_black_700"/>
inner_fragment.xml:
<FrameLayout 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">
<FrameLayout
android:id="#+id/inner_fragment_framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.BottomNavigationView
android:id="#+id/inner_fragment_bottom_navigation_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:menu="#menu/inner_fragment"
app:itemBackground="#drawable/bg_bottom_navigation"
app:itemIconTint="#color/ic_bottom_navigation"
app:itemTextColor="#color/ic_bottom_navigation"/>
</FrameLayout>
A simple solution is to just add an offset listener to appbarlayout. Works perfectly for me.
So something like this:
((AppBarLayout)toolbar.getParent()).addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
mNavigationBar.setTranslationY(verticalOffset*-1);
}
});
This release of BottomNavigationView is missing scrolling behavior to work out of the box as specified in the guidelines.
I wrote an article on what's missing and how you can fix it. This includes implementing scrolling behavior of the BottomNavigationView in CoordinatorLayout.
My solution was to replace the FrameLayout with a NestedCoordinatorLayout from here https://stackoverflow.com/a/37660246/2233621 and then add the BottomNavigationBehavior from Nikola's blog post https://medium.com/#nullthemall/bottomnavigationview-missing-pearls-eaa950f9ad4e#.p1i01wwui that way your bottom navigation behaviour can listen for nested scrolling of the fragment inside the NestedCoordinatorLayout
I believe you could use another view that implements NestedScrollParent + NestedScrollChild for the same behaviour.
I have developed an application and my requirement is to show setting button at the top on click.
Below is the code for my Activity_main.xml,
Any shortcut way to auto hide and show the app bar layout?
<android.support.design.widget.AppBarLayout
android:id="#+id/appbarlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email" />
Following is the code at main_activity.java for onclick logic:
final AppBarLayout appbar = (AppBarLayout) findViewById(R.id.appbarlayout);
appbar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
appbar.setVisibility(View.GONE);
}
});
Thanks
in the screen shot you can see the setting button, I want to hide this whole blue color appbar.
Just use View's setVisibility() to hide and show the AppBarLayout.
If you want it to animate then add android:animateLayoutChanges="true" to the AppBarLayout's xml.
You can set the Scrolling Behavior of a child View.
<android.support.v7.widget.RecyclerView
android:id="#+id/rvToDoList"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
Then add the scrollFlags of your Toolbar.
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"/>
And finally, simulate a scroll every N seconds so the Toolbar gets hidden.
//After 5 secs, scroll screen to N item in a list or something.
I have tried these, still not working. better solution is show and hide the CollapsingToolbar and set the AppBarLayout params dynamically.
Do this when ever you show/hide the CollapsingToolbarLayout
mAppBar.setLayoutParams(new CoordinatorLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
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.