How to combine the Toolbar and a TabLayout in landscape orientation? - android

How can one combine the Toolbar and Tablayout when in landscape mode as shown in the youtube app? I can't seem to find a definitive answer for this.
My current layout:
<LinearLayout 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:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<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"
app:popupTheme="#style/ThemeOverlay.AppCompat.Dark"/>
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:tabMode="fixed"
app:tabGravity="fill"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:background="#color/transparent"/>
</LinearLayout>

As mentioned above, Toolbar is a ViewGroup so a TabLayout can be made a child of this.
<LinearLayout 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:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<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"
app:popupTheme="#style/ThemeOverlay.AppCompat.Dark"
android:title="Viewer">
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:layout_gravity="center_horizontal"
app:tabMode="fixed"
app:tabGravity="center"/>
</android.support.v7.widget.Toolbar>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:background="#color/transparent"/>
</LinearLayout>

You can add a layout with components to your ActionBar (the classic one, not the
android.support.v7.widget.Toolbar)
First create a menu resource menu\top_menu.xml to be your actionbar menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/topBarTabLayout"
android:title=""
app:actionLayout="#layout/top_bar_tab_layout"
app:showAsAction="always" />
<!-- Other menu items here -->
</menu>
Then, create a layout called layout/top_bar_tab_layout.xml containing just one TabLayout component (you can add other components too!):
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.TabLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tab_layout_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="0dp"
android:paddingTop="0dp" />
To access this TabLayout component, create a reference inside your activity onCreateOptionsMenu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.top_menu, menu);
topBarTabLayoutMenuItem = menu.findItem(R.id.topBarTabLayout);
topBarTabLayout = (TabLayout) topBarTabLayoutMenuItem.getActionView();
//ADD #1 TAB WITH A ICON RESOURCE
topBarTabLayout.addTab(topBarTabLayout.newTab().setIcon(R.drawable.file));
//ADD #2 TAB WITH A ICON RESOURCE
topBarTabLayout.addTab(topBarTabLayout.newTab().setIcon(R.drawable.folder));
//This may be necessary to force tablayout to fill all space.
topBarTabLayout.setTabGravity(topBarTabLayout.GRAVITY_FILL);
//Add listener to do stuff!
topBarTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
//do whatever you want here, like selecting a viewpager item or open an intent
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
//do whatever you want here
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
//do whatever you want here
}
});
return true;
}
}
This should be enough to add a tabLayout to your actionBar. It will work with other components like spinner or textViews.
Also, if you are planning on setting this tablayout visible only when orientation is landscape, you have to do something like that:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE) {
topBarTabLayoutMenuItem.setVisible(true);
} else {
topBarTabLayoutMenuItem.setVisible(false);
}
}

Related

NestedScrollView with Toolbar

So I set in styles.xml for AppTheme NoActionBar, because I want Toolbar only in a few Activites and also I create post_details_menu with two items. But toolbar not showing at all.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
Then in Manifest.xml, I have the theme: AppTheme
<application
android:theme="#style/AppTheme"
...>
</application>
Then i created my_toolbar:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"/>
</LinearLayout>
And in im PostDetailsActivity i want use my Toolbar:
public class PostDetailActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post_detail);
Toolbar toolbar = findViewById(R.id.my_toolbar);
setSupportActionBar(toolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.post_details_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.post_Edit:
showMessage("post_edit clicked");
return true;
case R.id.post_Delete:
showMessage("post_delete clicked");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
And finally this is my layout for ActivityPostDetails:
<androidx.core.widget.NestedScrollView
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=".PostDetailActivity"
android:background="#fff">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView ... />
<TextView ... />
<androidx.recyclerview.widget.RecyclerView .../>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
It's too simple. set your app bar layout in the XML file where you want to show the toolbar.
check below XML code:-
<androidx.core.widget.NestedScrollView
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=".PostDetailActivity"
android:background="#fff">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"
android:theme="#style/AppTheme.ActionBar"
app:navigationIcon="#drawable/ic_back"
app:subtitleTextAppearance="#style/CustomSubTitleTextAppearance"
app:titleTextColor="#color/black" />
</com.google.android.material.appbar.AppBarLayout>
<ImageView ... />
<TextView ... />
<androidx.recyclerview.widget.RecyclerView .../>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
In your java code, you have to bind toolbar programmatically in PostDetailsActivity.java.
toolbar = findViewById(R.id.toolbar)
toolbar!!.setNavigationIcon(R.drawable.ic_back)
if (toolbar != null) {
setSupportActionBar(toolbar)
}
Xml structure something like this should solve the problem
<LinearLayout>
<Toolbar/>
<NestedScrollView>
//one parent view inside nestedscrollview
<AnylayoutType>
// other required views
</AnylayoutType>
</NestedScrollView>
<LinearLayout/>
With this approach your Toolbar won't move and menu option will always be available and nested sroll view will work as required.
And if you are sure your view hierarchy is not nested its better to use LinearLayout inside nested scrollview

Different menu toolbar in fragment with BottonNavigationView

I have a layout with bottonNavigationView and fragments. How can I have different toolbar menus for each fragment? I've already tried several things.
In a fragment, I hace used.
((AppCompatActivity) getActivity()).getSupportActionBar()
This is the layout of a fragment
<FrameLayout 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="com.cspm.ventas6.cspm.v_fragments.f_clientes"
android:focusable="false">
<LinearLayout
android:id="#+id/con_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:descendantFocusability="blocksDescendants"
android:focusable="false">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar">
<!-- Toolbar is the actual app bar with text and the action items -->
<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>
<ListView
android:id="#+id/client_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#null" />
</LinearLayout>
</FrameLayout>
In your fragment, add following two methods.
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// tells the fragment that fragment will use toolbar's options menu
setHasOptionsMenu(true);
}
/**
* this method is called when fragment prepares options menu,
* simply, inflate your menu and call super
*/
#Override
public void onPrepareOptionsMenu(Menu menu) {
getActivity().getMenuInflater().inflate(R.menu.menu_res_id, menu);
super.onPrepareOptionsMenu(menu);
}
Change menu_res_id with your menu resource.
And, if you only want to remove an item from current menu, then replace line
getActivity().getMenuInflater().inflate(R.menu.menu_res_id, menu);
with
menu.findItem(R.id.action_search).setVisible(false);

Fragment in FrameLayout in CoordinatorLayout flickers when FrameLayout has LayoutBehavior

In our app we use a CoordinatorLayout with two Toolbars (top and bottom) that slide out of view when scrolling. Between the Toolbars we have a FrameLayout, thats used to hold a Fragment. Currently we use mainly one Fragment which contains a NestedWebView (https://github.com/takahirom/webview-in-coordinatorlayout). We add the Fragment at runtime by calling fragmentManager.replace().
The Problem is that the FrameLayout seems to often just disappear. Sometimes its gone right from the application start, sometimes it disappears when I click buttons on the top toolbar. When its gone, I can make it show up by rotating the phone or by swiping on the top toolbar. I colored the CoordinatorLayout for debugging purposes and I can clearly see, that sometimes the WebView fills the space as intended, but often the WebView is invisible.
I figured, that the problem does not occur, when I remove
app:layout_behavior="#string/appbar_scrolling_view_behavior"
from the FrameLayout. But of course then scrolling does not work as intended.
Maybe its worth to note, that our Fragment has
setRetainInstance(true)
set.
Can someone tell me, how I can fix this? Here are the files:
CoordinatorLayout xml
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<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"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/content_container"
android:layout_width="fill_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:theme="#style/AppTheme.AppBarOverlay"
app:layout_behavior=".ui.BottomBarBehavior">
<android.support.v7.widget.ActionMenuView
android:id="#+id/toolbar2"
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
WebViewFragment xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.dfa.diaspora_android.ui.ContextMenuWebView
android:id="#+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"/>
<ProgressBar
android:id="#+id/progressBar"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
style="#style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:indeterminate="false"
android:layout_height="wrap_content"
android:layout_marginTop="-7dp" />
</RelativeLayout>
Some code from our MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main__activity);
ButterKnife.bind(this);
setSupportActionBar(toolbarTop);
MenuInflater menuInflater = getMenuInflater();
Menu bottomMenu = toolbarBottom.getMenu();
menuInflater.inflate(R.menu.main__menu_bottom, bottomMenu);
toolbarBottom.setOnMenuItemClickListener(new ActionMenuView.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
return MainActivity.this.onOptionsItemSelected(item);
}
});
setupUI(savedInstanceState);
}
private void setupUI(Bundle savedInstanceState) {
...
showFragment(StreamFragment.FRAGMENT_NAME);
...
handleIntent(getIntent());
}
private void showFragment(String tag) {
FragmentManager fm = getSupportFragmentManager();
CustomFragment fragment = (CustomFragment) fm.findFragmentByTag(tag);
if (fragment == null) {
switch (tag) {
case StreamFragment.FRAGMENT_NAME:
Log.d(App.TAG, "Create new StreamFragment");
fragment = new StreamFragment();
break;
default:
Log.e(App.TAG, "Missing fragment "+tag+" in showFragment switch case...");
return;
}
}
currentFragment = fragment;
if (!fragment.isVisible()) {
Log.d(App.TAG, "Fragment not visible. Replace it");
fm.beginTransaction().replace(R.id.content_container, fragment, tag).commit();
//Add fragment's bottom menu entries
currentFragment.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater());
} else {
Log.d(App.TAG, "Fragment was visible");
}
}
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
// Reinitialize the UI
setupUI(null);
}
I could fix this issue by changing
compile 'com.android.support:design:24.2.0'
to
compile 'com.android.support:design:24.1.0'
in my app.gradle file.

How do I make my Fragment layout fit under the tabs created in main Activity?

I have a problem which seems to have a different solution everytime it is asked, and causing me great distress. I have tried to use the solutions in other SO questions, but none worked.
I have an Activity from which initializes a ViewPager, a toolbar and a TabLayout. There are two tabs, both of which are implemented using fragments. The problem is
that my fragment is layed out with a spinner, a recycler view, a button and a textfield. Of these widgets, only the recyclerView shows up with the first two items missing,
forcing me to believe the Spinner is hidden just behind my AppLayoutBar, and the textField and buttons are below the screen. My question is, how do I get the layout
of my fragment to appear in the visible part of the screen below the tabs? Below are the Layout files for both fragment and main activity
Fragment:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/header"
>
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/spinner"
android:entries="#array/status"
>
</Spinner>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/list"
android:paddingTop="20dp"
android:layout_below="#+id/spinner"
android:layout_above="#+id/editText"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.75"
android:inputType="textMultiLine"
android:id="#+id/editText"
android:hint="#string/goal_edit_text_hint"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:maxLines="5"
android:minLines="1"
android:scrollHorizontally="false"
android:layout_alignParentStart="true"
android:layout_toLeftOf="#+id/addButton"
android:layout_toStartOf="#+id/addButton" />
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="#string/add_button_text"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:textAppearance="?android:textAppearanceLarge"
android:layout_alignParentEnd="true"
android:drawableLeft="#drawable/math"
android:id="#+id/addButton" />
</RelativeLayout>
Main Activity
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="612dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_gravity="center" />
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/header"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:popupTheme="#style/ThemeOverlay.AppCompat.Light">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"
/>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
For a Detail Tutorial Have a look At
Dear I can understand your problem and I have a solution for you that will work perfectly. I'm giving complete piece of code that will solve your issue.
Step - 1: Paste this XML in your Main Activity 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.broadpeakit.hmehmood.company.HomeActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.CustonActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:titleTextColor="#color/white"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_home" />
</android.support.design.widget.CoordinatorLayout>
Step 2 - Crate another layout with named content_home. and paste this code there.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.broadpeakit.hmehmood.company.HomeActivity"
tools:showIn="#layout/app_bar_home">
<FrameLayout
android:id="#+id/fl_testing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"></FrameLayout>
</RelativeLayout>
Step 3 - Now Create another layout with name viewPager_fragment that will contain your view pager with tabs and we'll inflate this layout later.
<RelativeLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar"
android:background="#color/blue"
app:tabTextColor="#color/white"
app:tabSelectedTextColor="#color/gray"
app:tabIndicatorColor="#color/red"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="#id/tabs"/>
</RelativeLayout>
Step 4 - Now create a class with name viewPagerFragment and extends it with Fragment. we'll inflate this Fragment later in your Main Activity.
public class viewPagerFragment extends Fragment {
private TabLayout tabLayout;
private ViewPager viewPager;
TabsTestFragment1 tabsTestFragment1;
TabsTestFragment2 tabsTestFragment2;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
// Inflate the layout for this fragment
setHasOptionsMenu(true);
return inflater.inflate(R.layout.viewPager_fragment, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((HomeActivity)getActivity()).updateDrawerIcon();
tabsTestFragment1 = new TabsTestFragment1();
tabsTestFragment2 = new TabsTestFragment1();
viewPager = (ViewPager) view.findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout)view.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
public void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(tabsTestFragment1, "Tab 1");
adapter.addFragment(tabsTestFragment2, "Tab 2");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
Step 5 - Now place this code in onCreate of your Main Activity.
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).replace(R.id.fl_testing, new viewPagerFragment()).commit();
Now you are good to RUN your code. Get back to me if you have any issue later. Also mark this issue as solved if you are able to solve your issue using this code. Happy Coding :)
Change your Main Activity with this one
<?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/tabanim_maincontent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<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|snap"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>

Fixed view in ViewPager's content layout, under CoordinatorLayout

My app has an Activity with TabLayout, and 3 Fragments. In Activity's layout, I have CoordinatorLayout with ViewPager. I need to animate toolbar as well.
Now In Fragments layout, I need to put a fixed TextView at the bottom.
Given below is the XML of activity and fragment.
I am facing the problem that this fixed TextView in Fragment's
layout is going under the bottom navigation bar and is scrolling also,
that I don't want.
How can achieve this ?
activity.xml
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/clMain"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
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"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="#color/colorWhite"
android:orientation="vertical">
<android.support.v4.widget.NestedScrollView
android:id="#+id/rlParent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:layout_weight="1"
android:fitsSystemWindows="true"
android:orientation="vertical">
</android.support.v4.widget.NestedScrollView>
<TextView
android:id="#+id/tvConfirmOrder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorDarkGreen"
android:gravity="center"
android:padding="10dp"
android:text="#string/confirm_order"
android:textColor="#color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"></TextView>
</LinearLayout>
As you want this bottom fixed TextView for each fragment, it can be solved by transferring your TextView to activity.xml and adding a custom behavior to it.
So, firstly, create a class that represents custom behavior:
public class FixedBottomViewBehavior extends CoordinatorLayout.Behavior<View> {
public FixedBottomViewBehavior() {
}
public FixedBottomViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
//making our bottom view depends on ViewPager (or whatever that have appbar_scrolling_view_behavior behavior)
return dependency instanceof ViewPager;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
if (ViewCompat.isLaidOut(parent)) {
//attach our bottom view to the bottom of CoordinatorLayout
child.setY(parent.getBottom() - child.getHeight());
//set bottom padding to the dependency view to prevent bottom view from covering it
dependency.setPadding(dependency.getPaddingLeft(), dependency.getPaddingTop(),
dependency.getPaddingRight(), child.getHeight());
}
return false;
}
}
There is no magic here, we're just making our bottom view dependent on some view with appbar_scrolling_view_behavior (in our case it's ViewPager) and then attaching it to the bottom of CoordinatorLayout and setting some padding to dependency.
Secondly, change your activity.xml, by adding your TextView there:
<?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/clMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
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"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<TextView
android:id="#+id/tvConfirmOrder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/colorDarkGreen"
android:gravity="center"
android:padding="10dp"
android:text="#string/confirm_order"
android:textColor="#color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"
app:layout_behavior="your.package.name.FixedBottomViewBehavior" />
</android.support.design.widget.CoordinatorLayout>
Make sure you've removed your TextView from fragment.xml. Don't forget also to change your.package.name.FixedBottomViewBehavior to your package name exactly.
Voila! That should work like a charm with proper toolbar animation and fixed view at the bottom.
In addition: if you don't know how to pass your OnClick event to your fragments you can follow this way in your Activity:
public interface OnConfirmOrderClickListener {
void onConfirmOrderClick(View v);
}
public Fragment getActiveFragment() {
String name = makeFragmentName(pager.getId(), pager.getCurrentItem());
return getSupportFragmentManager().findFragmentByTag(name);
}
public String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
tvConfirmOrder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment current = getActiveFragment();
if (current instanceof OnConfirmOrderClickListener)
((OnConfirmOrderClickListener) current).onConfirmOrderClick(v);
}
});
Don't forget to make your fragments implements OnConfirmOrderClickListener. Hope that helps!
For those who want the button to appear only in one fragment, it's possible to use onPageChangeListener of ViewPager to make the button scroll with the ViewPager
viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
updateButtonPosition(position, positionOffsetPixels);
}
});
//Move the button according to the tab you want it to be fixed.
//Here is the 3rd tab of a 3 tab viewPager, for instance
private void updateButtonPosition(int position, int positionOffsetPixels) {
int fixedRewardXPos;
if (position == 0) {
fixedRewardXPos = viewPager.getWidth() * 2 - positionOffsetPixels;
} else if (position == 1) {
fixedRewardXPos = viewPager.getWidth() - positionOffsetPixels;
} else {
fixedRewardXPos = -positionOffsetPixels;
}
//Add getLeft() to keep the button to its former position in it's fragment
aButton.setX(fixedRewardXPos + aButton.getLeft());
}

Categories

Resources