How to create a Fragment over the Viewpager in android? - android

Explanation:
I tried more but i failed to find the how to set the transparent fragment over the Viewpager. I am working in application. The requirement of my client is who will make a application like below url
https://play.google.com/store/search?q=munchery&hl=en
In above url application. In this application they were added more functionality like navigationDrawer, Tabs with viewpager and etc.
One thing is when i click on the actionBar Today's menu it's open something. I am not able to recognized to find what it actually open while i click on actionBar in the Munchery application.
I tried to implement but not implemented as same as the munchery application.
activity_main.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"
android:fitsSystemWindows="true"
tools:context="com.millu.whatsappdemo.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:popupTheme="#style/AppTheme.PopupOverlay" >
<TextView
android:id="#+id/action_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:textSize="20sp"
android:clickable="true"
android:textColor="#FFFFFF"
android:text="Text view"
android:drawableRight="#drawable/ic_up_arrow">
</TextView>
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
app:tabMode="fixed"
app:tabGravity="fill"/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<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>
MainActivity.java
public class MainActivity extends AppCompatActivity {
public TextView action_text;
public Toolbar toolbar;
TabLayout tabs;
ViewPager viewPager;
List<Fragment> fragmentList;
List<String> tab_title;
boolean flag=false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
tabs = (TabLayout) findViewById(R.id.tabs);
viewPager = (ViewPager) findViewById(R.id.viewpager);
action_text = (TextView) toolbar.findViewById(R.id.action_text);
fragmentList = new ArrayList<>();
tab_title = new ArrayList<>();
tab_title.add("ONE");
tab_title.add("TWO");
fragmentList.add(new OneFragment());
fragmentList.add(new TwoFragment());
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), fragmentList, tab_title);
viewPager.setAdapter(viewPagerAdapter);
viewPager.setCurrentItem(0);
tabs.setupWithViewPager(viewPager);
action_text.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment fragment=new ThirdFragment();
FragmentTransaction fragmentTransaction=getSupportFragmentManager().beginTransaction();
if(!fragment.isHidden()) {
fragmentTransaction.replace(R.id.container,fragment);
flag=true;
}
else{
fragmentTransaction.remove(fragment);
flag=false;
}
fragmentTransaction.commit();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.action_settings:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
In above code i set the flat onClick of the textview over the actionBar for hiding and showing the fragment. In my demo the problem is it show the tab when my third fragment is open and it does not hide.
Please help me to recognized what is it open on click of the actionBar?

Try the code as below: activity_main.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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ScrollingActivity">
<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">
<TextView
android:id="#+id/action_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:clickable="true"
android:drawableRight="#mipmap/ic_launcher"
android:gravity="center"
android:text="Text view"
android:textColor="#FFFFFF"
android:textSize="20sp"></TextView>
</android.support.v7.widget.Toolbar>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
app:tabGravity="fill"
app:tabMode="fixed" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/tabs"
android:background="#android:color/white" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/reltv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
android:background="#80ffffff"
android:visibility="gone">
<RelativeLayout
android:id="#+id/reltv2"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#android:color/white">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Do whatever you like it here."
android:textAppearance="?attr/textAppearanceLargePopupMenu" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="#android:color/darker_gray" />
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
And your ManiActivity.java as below:
public class MainActivity extends AppCompatActivity {
public TextView action_text;
public Toolbar toolbar;
TabLayout tabs;
ViewPager viewPager;
List<Fragment> fragmentList;
List<String> tab_title;
boolean flag = false;
RelativeLayout reltv;
RelativeLayout reltv2;
boolean isShown = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
tabs = (TabLayout) findViewById(R.id.tabs);
viewPager = (ViewPager) findViewById(R.id.viewpager);
action_text = (TextView) toolbar.findViewById(R.id.action_text);
reltv = (RelativeLayout) findViewById(R.id.reltv);
reltv2 = (RelativeLayout) findViewById(R.id.reltv2);
fragmentList = new ArrayList<>();
tab_title = new ArrayList<>();
tab_title.add("ONE");
tab_title.add("TWO");
fragmentList.add(new OneFragment());
fragmentList.add(new TwoFragment());
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), fragmentList, tab_title);
viewPager.setAdapter(viewPagerAdapter);
viewPager.setCurrentItem(0);
tabs.setupWithViewPager(viewPager);
action_text.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!isShown) {
isShown=true;
reltv.setVisibility(View.VISIBLE);
}else {
isShown=false;
reltv.setVisibility(View.GONE);
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_scrolling, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

First, you should use some translucent or transparent colour for the android: background of parent's attribute in the fragment layout e.g DayFragment . This is the fragment you will inflate in the overlay FrameLayout.
For a smooth inflation of that fragment, you can use custom animation to make the transition smooth like in the Munchery app(uses slide from top animation)
protected void replaceFragment(int containerViewId, Fragment fragment, boolean isAddToBackStack, boolean isAnimateTransition) {
String backStateName = fragment.getClass().getName();
FragmentManager fm = this.getSupportFragmentManager();
boolean fragmentPopped = fm.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped && getSupportFragmentManager().findFragmentByTag(backStateName) == null) {
FragmentTransaction ft = fm.beginTransaction();
if(isAnimateTransition) {
animateFragmentTransition(ft);
}
ft.replace(containerViewId, fragment, backStateName);
if (isAddToBackStack) {
ft.addToBackStack(backStateName);
}
ft.commit();
}
}
private void animateFragmentTransition(FragmentTransaction ft) {
ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.slide_in_from_top, R.anim.slide_out_to_top);
}
DayFragment fragment = DayFragment.newInstance(null);
replaceFragment(R.id.container, fragment, false, true);
Alternitively, you can use ObjectAnimators to revael and hide views as you wish. For example:-
private void animate() {
View viewToShiftOut = mNormalModelayoutContainer;
View viewToShiftIn = mEditModelayoutContainer;
ObjectAnimator outAnim = ObjectAnimator.ofFloat(viewToShiftOut, "y", 0, -heightOfScreen);
ObjectAnimator inAnim = ObjectAnimator.ofFloat(viewToShiftIn, "y", heightOfScreen , 0);
outAnim.setDuration(1000);
inAnim.setDuration(1000);
outAnim.start();
inAnim.start();
}

Related

When I am adding fragment to my view pager (in nested scroll view), I can not exit from application with device back button

This is my activity_main code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layoutDirection="rtl"
tools:context=".MainActivity"
tools:openDrawer="start">
<android.support.design.widget.CoordinatorLayout
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:fitsSystemWindows="true"
android:paddingTop="#dimen/appbar_padding_top"
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"
android:layoutDirection="rtl"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:title="#string/app_name">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutDirection="rtl" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<com.duolingo.open.rtlviewpager.RtlViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutDirection="rtl"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:layoutDirection="rtl"
app:headerLayout="#layout/drawer_header"
app:menu="#menu/menu_drawer" />
</android.support.v4.widget.DrawerLayout>
I want to add some fragments to ViewPager in NestedScrollView.
Without adding fragments to ViewPager everything is ok and I can exit from app by device back button, but when I am adding fragment(s) to ViewPager I can not exit from app by pressing device back button.(Back button is working and for example can close soft keyboard)
this is my fragment code:
(empty fragment!)
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable
ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_jadvalyab,container,false);
}
and this is my adapter:
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragmentsList = new ArrayList<>();
private ArrayList<String> fragsTitleList = new ArrayList<>();
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
public void addFragment(Fragment fragment,String title){
fragmentsList.add(fragment);
fragsTitleList.add(title);
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return fragsTitleList.get(position);
}
#Override
public Fragment getItem(int position) {
return fragmentsList.get(position);
}
#Override
public int getCount() {
return fragmentsList.size();
}
}
Does anyone have an idea to solving this problem?
Thanks.
Edit:
Problem solved by removing NestedScrollingView from coordinator layout in activity_main and putting that in fragment layout (inside viewpager).
But still I don't know why device back button did not worked in former state.
I think the problem is occurring because you have used a third party library for ViewPager.
Just copy and paste the following code in the place of your "activity_main.xml" file.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<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=".Main2Activity">
<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:popupTheme="#style/AppTheme.PopupOverlay" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main2" />
<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"
app:srcCompat="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/drawer_header"
app:menu="#menu/menu_drawer" />
</android.support.v4.widget.DrawerLayout>
I have initialized fragment to ViewPager like this
ViewPager viewPager2 = findViewById(R.id.viewpager);
MyFragmentPagerAdapter pagerAdapter2 = new MyFragmentPagerAdapter(getSupportFragmentManager());
pagerAdapter2.addFragment(TestFragment.createInstance(),"Home");
viewPager2.setAdapter(pagerAdapter2);
TabLayout tabLayout2 = findViewById(R.id.tabs);
tabLayout2.setupWithViewPager(viewPager2);
Here is the Testfragment.java class
public class TestFragment extends Fragment {
public static TestFragment createInstance() {
TestFragment profileFragment = new TestFragment();
return profileFragment;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_jadvalyab, container, false);
return rootView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
}
And the full code of "Main2Activity.java" class is here
public class Main2Activity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
initViewPager();
}
private void initViewPager() {
ViewPager viewPager2 = findViewById(R.id.viewpager);
MyFragmentPagerAdapter pagerAdapter2 = new MyFragmentPagerAdapter(getSupportFragmentManager());
pagerAdapter2.addFragment(TestFragment.createInstance(),"Home");
viewPager2.setAdapter(pagerAdapter2);
TabLayout tabLayout2 = findViewById(R.id.tabs);
tabLayout2.setupWithViewPager(viewPager2);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main2, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
Edit:
Code of "content_main2.xml"
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.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"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.v4.widget.NestedScrollView>
Code for "fragment_jadvalyab.xml" is in te following
<?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">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Best Wishes"
android:gravity="center"/>
</LinearLayout>
Try this
#Override
public void onBackPressed() {
//Your Action
}
Override onBackPress(){} event in your MainActivity which holds your above xml layout.
#Override
public void onBackPressed() {
finish();
}
override OnBackPressed() method , or you can write your adapter as this.
public class Adapter extends FragmentStatePagerAdapter {
public Adapter (FragmentManager fm) {
super(fm);
}
// you can add fragments according to your requirement
#Override
public Fragment getItem(int position) {
Fragment fragment= null;
switch (position){
case 0:
fragment= new fragmentDay();
break;
case 1:
fragment= new fragmentWeek();
break;
case 2:
fragment= new fragmentMonth();
break;
}
return fragment;
}
#Override
public int getCount() {
return 3;
}
}
and inside activity pass fragment manager to adapter constructor.
fragmentManager= getSupportFragmentManager();
adapter= new Adapter(fragmentManager);
viewPager.setAdapter(adapter);
I have used tablayout with viewpager
tabLayout.setupWithViewPager(viewPager);
tabLayout.setTabsFromPagerAdapter(adapter);
tabLayout.getTabAt(0).setText("Day");
tabLayout.getTabAt(1).setText("Week");
tabLayout.getTabAt(2).setText("Month");
tabLayout.getTabAt(1).select();
tabLayout.setSelectedTabIndicatorColor(Color.WHITE);

Collapsing AppBarLayout not scrolling with TabLayout and NestedScrollView

I have an issue with scrolling Collapsing AppBar, when I am trying to scroll it touching the AppBarLayout part. And also it sometimes scrolling not smoothly.
Here is short (1m 30s) video of issue: https://www.youtube.com/watch?v=n32N9Z4S3SA&feature=youtu.be
Here is link to simple project (only this issue on github): https://github.com/yozhik/Reviews/tree/master/app/src/main/java/com/ylet/sr/review
I'm using: com.android.support:appcompat-v7:27.1.1
There is issue on offsite: https://issuetracker.google.com/issues/37050152
How it is: https://www.youtube.com/watch?v=xWadOVEaTSY&feature=youtu.be
How it should be: https://www.youtube.com/watch?v=J8ITp6RusZo&feature=youtu.be
Does anybody know how to fix this issue you saw on video? I created absolutely simple layouts to avoid any side effects, but bug still reproduced. Thanks in advance.
Description:
CollapsingActivity - activity with Collapsing AppBarLayout. Which loads one or two fragments into "fragment_content_holder" and it has TabLayout
to switch between fragments in view pager.
In activity method onCreate() - I'm just simulating request to server (loadData), and when some fake data is loaded - I am showing fragments in view pager, on first call - I am creating new TabMenuAdapter extends FragmentPagerAdapter, populate it with fragments and save links to instances. On the next call -
I don't create fragments from scratch and just populate them with fresh data.
MenuFragment1, MenuFragment1 - two fragments.
MenuFragment1 - has method public void setupData(SomeCustomData data), to set new data, not recreating fragment on network reconnect.
NetworkStateReceiver - listens to network change and send notifications.
TabMenuAdapter - just simple class to hold fragments.
Next is just copy/paste of code:
public class CollapsingActivity extends AppCompatActivity implements ChangeNetworkNotification {
private static int dataReloadIteration = 0;
private SomeCustomData dummyDataFromServer;
#BindView(R.id.root_layout)
CoordinatorLayout root_layout;
#BindView(R.id.app_bar_layout)
AppBarLayout app_bar_layout;
#BindView(R.id.collapsing_toolbar_layout)
CollapsingToolbarLayout collapsing_toolbar_layout;
#BindView(R.id.view_pager_layout)
ViewPager viewPager;
#BindView(R.id.tab_layout)
TabLayout tabLayout;
#BindView(R.id.collapsing_data_1_txt)
TextView collapsing_data_1_txt;
private NetworkStateReceiver networkStateReceiver;
private boolean isConnected;
protected Fragment currentFragment;
protected Fragment previousFragment;
protected FragmentManager fragmentManager;
private boolean dataLoading = false;
private boolean isCreated = false;
private MenuFragment1 menu1Fragment1;
private MenuFragment2 menu1Fragment2;
private TabMenuAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d("TEST", "CollapsingActivity.onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collapsing);
ButterKnife.bind(this);
fragmentManager = getSupportFragmentManager();
networkStateReceiver = new NetworkStateReceiver();
networkStateReceiver.setNetworkReceiver(this);
IntentFilter intentFilterForNetwork = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(networkStateReceiver, intentFilterForNetwork);
initToolbar();
loadData();
}
#Override
protected void onStart() {
Log.d("TEST", "CollapsingActivity.onStart");
super.onStart();
IntentFilter intentFilterForNetwork = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(networkStateReceiver, intentFilterForNetwork);
}
private void initToolbar() {
Log.d("TEST", "CollapsingActivity.initToolbar");
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_layout);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
private void loadData() {
Log.d("TEST", "CollapsingActivity.loadData");
dataLoading = true;
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(CollapsingActivity.this, "Data loaded.", Toast.LENGTH_SHORT).show();
Log.d("TEST", "CollapsingActivity.Data loaded.");
dataReloadIteration++;
dummyDataFromServer = getDummyObjectFromServer();
collapsing_data_1_txt.setText(dummyDataFromServer.Name); //Set data from server in collapsing part of Activity
boolean showOneView = false;
if (showOneView) {
initSingleView();
} else {
if (!isCreated) {
initTabView();
} else {
menu1Fragment1.setupData(dummyDataFromServer); //Set the data from server to fragment, not reloading it, just updating data
}
}
dataLoading = false;
}
});
}
});
t.start();
}
private SomeCustomData getDummyObjectFromServer() {
SomeCustomData dto = new SomeCustomData();
dto.Age = dataReloadIteration;
dto.Name = "Name " + dataReloadIteration;
return dto;
}
private void initSingleView() {
Log.d("TEST", "CollapsingActivity.initSingleView");
tabLayout.setVisibility(View.GONE);
viewPager.setVisibility(View.GONE);
showFragmentWithoutBackStack(R.id.fragment_content_holder, new MenuFragment1());
}
private void initTabView() {
if (!isCreated) {
Log.d("TEST", "CollapsingActivity.initTabView");
tabLayout.setVisibility(View.VISIBLE);
viewPager.setVisibility(View.VISIBLE);
setupViewPager(viewPager);
tabLayout.setupWithViewPager(viewPager);
isCreated = true;
}
}
private void setupViewPager(ViewPager viewPager) {
Log.d("TEST", "CollapsingActivity.setupViewPager");
menu1Fragment1 = MenuFragment1.newInstance(dummyDataFromServer);
menu1Fragment2 = MenuFragment2.newInstance();
adapter = new TabMenuAdapter(getSupportFragmentManager());
adapter.addFragment(menu1Fragment1, "Menu 1");
adapter.addFragment(menu1Fragment2, "Menu 2");
viewPager.setAdapter(adapter);
}
#Override
protected void onDestroy() {
Log.d("TEST", "CollapsingActivity.onDestroy");
super.onDestroy();
unregisterReceiver(networkStateReceiver);
}
#Override
public void networkStateIsChanged(boolean isConnected) {
this.isConnected = isConnected;
Log.d("TEST", "CollapsingActivity.networkStateIsChanged.isConnected: " + isConnected);
if (isConnected) {
Toast.makeText(CollapsingActivity.this, "Connection received.", Toast.LENGTH_SHORT).show();
if (!dataLoading) {
loadData();
}
} else {
Toast.makeText(CollapsingActivity.this, "Connection lost.", Toast.LENGTH_SHORT).show();
}
}
protected void showFragmentWithoutBackStack(int containerViewId, Fragment fragment) {
Log.d("TEST", "CollapsingActivity.showFragmentWithoutBackStack");
previousFragment = currentFragment;
currentFragment = fragment;
String fragmentTag = fragment.getClass().getSimpleName();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if (previousFragment != null) {
fragmentTransaction.remove(previousFragment);
}
fragmentTransaction.add(containerViewId, fragment, fragmentTag)
.commitNowAllowingStateLoss();
}
}
activity's 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/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="false"
android:background="#color/white"
android:stateListAnimator="#drawable/appbar_shadow"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/green"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title=""
app:titleEnabled="false">
<include
layout="#layout/appbar_collapsing_part"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="?attr/actionBarSize"
app:layout_scrollFlags="scroll|exitUntilCollapsed" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/green"
android:stateListAnimator="#drawable/appbar_shadow"
app:layout_collapseMode="pin"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:theme="#style/ToolbarMenuItemsBackGroundTheme">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/title_txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_toStartOf="#+id/star_img"
android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:gravity="center_vertical"
android:maxLines="1"
android:textColor="#color/colorPrimaryDark"
android:textSize="19sp" />
<ImageView
android:id="#+id/star_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:layout_marginEnd="24dp"
android:padding="10dp"
android:src="#drawable/ic_favorite_filled" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:background="#45b0b2"
android:visibility="gone"
app:tabBackground="#drawable/backgr_blue_transparent_selector"
app:tabGravity="center"
app:tabIndicatorColor="#color/colorPrimaryDark"
app:tabIndicatorHeight="2dp"
app:tabMinWidth="500dp"
app:tabMode="fixed"
app:tabSelectedTextColor="#color/colorPrimaryDark"
app:tabTextAppearance="#style/CustomTabLayout"
app:tabTextColor="#color/green" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/fragment_content_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/blue"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.v4.view.ViewPager
android:id="#+id/view_pager_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
Fragment 1:
public class MenuFragment1 extends Fragment {
public SomeCustomData transferedDataFromActivity;
private TextView data_1_txt;
public static MenuFragment1 newInstance(SomeCustomData data) {
Log.d("TEST", "MenuFragment1.newInstance");
MenuFragment1 fragment = new MenuFragment1();
Bundle args = new Bundle();
args.putSerializable("DATA_FROM_ACTIVITY", data);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("TEST", "MenuFragment1.onCreate");
if (getArguments() != null) {
this.transferedDataFromActivity = (SomeCustomData) getArguments().getSerializable("DATA_FROM_ACTIVITY");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d("TEST", "MenuFragment1.onCreateView");
View v = inflater.inflate(R.layout.menu_fragment_1, container, false);
data_1_txt = (TextView) v.findViewById(R.id.data_1_txt);
setupInOnCreateView();
return v;
}
protected void setupInOnCreateView() {
Log.d("TEST", "MenuFragment1.setupInOnCreateView");
//initialization of all view elements of layout with data is happens here.
setupData(transferedDataFromActivity);
}
public void setupData(SomeCustomData data) {
Log.d("TEST", "MenuFragment1.setupData");
this.transferedDataFromActivity = data;
if (transferedDataFromActivity != null) {
data_1_txt.setText(transferedDataFromActivity.Name);
}
}
}
Fragment 1 layout:
<?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:background="#color/green"
android:orientation="vertical">
<TextView
android:id="#+id/data_1_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/yellow"
android:text="Test"
android:textSize="20sp" />
<include layout="#layout/description_layout" />
</LinearLayout>
Fragment 2:
public class MenuFragment2 extends Fragment {
public static MenuFragment2 newInstance() {
Log.d("TEST", "MenuFragment2.newInstance");
MenuFragment2 fragment = new MenuFragment2();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d("TEST", "MenuFragment2.onCreateView");
View v = inflater.inflate(R.layout.menu_fragment_2, container, false);
setupInOnCreateView();
return v;
}
protected void setupInOnCreateView() {
Log.d("TEST", "MenuFragment2.setupInOnCreateView");
//initialization of all view elements of layout with data is happens here.
}
}
Fragment 2 layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/comments_scrollable_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible">
<LinearLayout
android:id="#+id/comments_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/yellow" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/blue" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/yellow" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
TabMenuAdapter:
public class TabMenuAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragments = new ArrayList<>();
private final List<String> mFragmentTitles = new ArrayList<>();
public TabMenuAdapter(FragmentManager fm) {
super(fm);
}
public void addFragment(Fragment fragment, String title) {
mFragments.add(fragment);
mFragmentTitles.add(title);
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
#Override
public int getCount() {
return mFragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitles.get(position);
}
}
Try this
Activity layout
<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">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title=""
app:titleEnabled="false">
<ImageView
android:layout_width="match_parent"
android:layout_height="256dp"
android:scaleType="fitXY"
android:src="#drawable/abc"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
app:layout_anchor="#id/appBar"
app:tabGravity="fill"
app:tabTextColor="#FFFFFF"
app:tabSelectedTextColor="#ff00"
app:tabMode="scrollable"
app:layout_anchorGravity="bottom" />
</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>
Activity code
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new BlankFragment(), "TAB-ONE");
adapter.addFragment(new BlankFragment(), "TAB-TWO");
adapter.addFragment(new BlankFragment(), "TAB-THREE");
viewPager.setAdapter(adapter);
}
}
Fragment Code
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
}
Fragment Layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 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">
<LinearLayout
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".BlankFragment">
<ImageView
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_margin="5dp"
android:scaleType="centerCrop"
android:src="#drawable/kid_goku" />
<ImageView
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_margin="5dp"
android:scaleType="centerCrop"
android:src="#drawable/kid_goku" />
<ImageView
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_margin="5dp"
android:scaleType="centerCrop"
android:src="#drawable/kid_goku" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
ViewPagerAdapter code
public 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);
}
}
You can see the video here CollapsingToolbarLayout WITH TabLayout
You download the complete project from here CollapsingToolbarLayout WITH TabLayout
Try the below layout foryour activity
<?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/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="false"
android:background="#color/white"
android:stateListAnimator="#drawable/appbar_shadow"
android:theme="#style/AppTheme.AppBarOverlay"
tools:targetApi="lollipop">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/green"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title=""
app:titleEnabled="false">
<include
layout="#layout/appbar_collapsing_part"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="?attr/actionBarSize"
app:layout_scrollFlags="scroll|exitUntilCollapsed" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/green"
android:stateListAnimator="#drawable/appbar_shadow"
app:layout_collapseMode="pin"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:theme="#style/ToolbarMenuItemsBackGroundTheme"
tools:targetApi="lollipop">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/title_txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_toStartOf="#+id/star_img"
android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:gravity="center_vertical"
android:maxLines="1"
android:textColor="#color/colorPrimaryDark"
android:textSize="19sp" />
<ImageView
android:id="#+id/star_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:layout_marginEnd="24dp"
android:padding="10dp"
android:src="#drawable/ic_favorite_filled" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:background="#45b0b2"
android:visibility="gone"
app:tabBackground="#drawable/backgr_blue_transparent_selector"
app:tabGravity="center"
app:tabIndicatorColor="#color/colorPrimaryDark"
app:tabIndicatorHeight="2dp"
app:tabMinWidth="500dp"
app:tabMode="fixed"
app:tabSelectedTextColor="#color/colorPrimaryDark"
app:tabTextAppearance="#style/CustomTabLayout"
app:tabTextColor="#color/green" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/fragment_content_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.v4.view.ViewPager
android:id="#+id/view_pager_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
Try scrolling to top in the fragment in the view pager by calling scrollView.fullScroll(View.FOCUS_UP) whenever you click on a tab. If your fragment inside the viewpager is scrolled up then your scrolling should work correctly.
You have done it almost correctly. But need some minor tweaks and modifications.
Step 1 : Set some height to your appBar. Say 224dp.
Step 2 : Set match_parent property to CollapsingToolbarLayout height.
Step 3 : Set following scroll flags to the CollapsingToolbarLayout
`app:layout_scrollFlags = "scroll|enterAlways|enterAlwaysCollapsed"`
Step 4 : Set the toolbar collapsemode to none
Check if it works fine. Let me know.
I have spend a lot of time investigating my issue with AppBar + Collapsing Layouts. And what I did find out is that it's a bug in google support library. So I created the issue for google and they assigned it to one of developers: https://issuetracker.google.com/issues/78686882
But to solve this issue right now I made a workaround - if users will get stuck with scrolling on collapsing part of the layout - they will probably try to click on one of tabs in my TabLayout. So I added code to auto collapse with animation collapsing part of layout: appBarLayout.setExpanded(false, true);
Here is the code:
tabLayout.addOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPagerLayout) {
#Override
public void onTabSelected(TabLayout.Tab tab) {
appBarLayout.setExpanded(false, true);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
//no ui effects
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
appBarLayout.setExpanded(false, true);
}
});
To solve this issue, there is a workaround to do on the AppBarLayout :
class CustomAppBarLayout #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppBarLayout(context, attrs, defStyleAttr) {
override fun getBehavior(): CoordinatorLayout.Behavior<AppBarLayout> {
return Behavior().also {
it.setDragCallback(object : Behavior.DragCallback() {
override fun canDrag(appBarLayout: AppBarLayout) = true
})
}
}
}
Found here : https://github.com/material-components/material-components-android/issues/1878

Recyclerview in Coordinatorlayout cutting off last item

I have a Bottom Navigation Bar, and a frame layout which is the fragment container. So when a an icon on a Bottom Navigation Bar is clicked, the fragment above changes.
In one of the fragment, I have a coordinator layout, collapsing toolbar, and recycler view. At the moment, the data is just a dummy data.
The problem that I am encountering is that whenever that fragment is inflated for the first time, the Recyclerview works fine and shows all of the items in the list. But when I change the fragment and come back to this fragment again, the last item of the Recyclerview is being cut off and is being hidden behind the Bottom Navigation Bar.
Here is my code for activity_home_screen.xml
<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"
tools:context="com.smartinc.livesportstv.activities.HomeScreen">
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="55dp"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom"
app:itemBackground="?attr/colorPrimary"
app:itemIconTint="#drawable/selector_bottombar_item"
app:itemTextColor="#drawable/selector_bottombar_item"
app:menu="#menu/bottombar_menu" />
<FrameLayout
android:id="#+id/frame_fragmentholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/bottom_nav"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
Here is the fragment_events.xml
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:id="#+id/coordinator">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="120dp"
>
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="#color/colorPrimary"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title="Events"
app:expandedTitleTextAppearance="#style/TransparentText"
app:collapsedTitleTextAppearance="#style/Toolbar_text_black"
app:collapsedTitleGravity="center_horizontal"
android:paddingEnd="20dp"
android:fitsSystemWindows="true"
>
<!-- You can add views that you want to appear on the
collapsing toolbar here -->
<TextView
android:id="#+id/events_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Events"
android:textSize="30sp"
android:textColor="#color/black"
android:layout_marginTop="30dp"
android:layout_marginStart="20dp"
android:textStyle="bold"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="29 March, Thursday"
android:textSize="20sp"
android:textColor="#color/grey_800"
android:layout_marginTop="70dp"
android:layout_marginStart="20dp"
/>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
android:minHeight="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
android:gravity="center_horizontal"
app:popupTheme="#style/AppTheme"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view_events"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Request"
android:textSize="17sp"
android:layout_gravity="end"
android:textColor="#color/colorPrimaryDark"
android:padding="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="5dp"
/>
Here is HomeScreen.java
public class HomeScreen extends AppCompatActivity {
private BottomNavigationView bottomNavigationView;
private String fragName = "";
#Override
public void startActivity(Intent intent) {
super.startActivity(intent);
Constants.overridePendingTransitionEnter(this);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_screen);
init();
setMainFragment();
setBottomNavigation();
}
private void init(){
bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_nav);
}
private void setBottomNavigation(){
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.bottombaritem_events:
if(!fragName.equals("events")) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.left_slide_in, R.anim.right_slide_out);
ft.replace(R.id.frame_fragmentholder, new EventsFragment());
ft.commit();
fragName = "events";
}
return true;
case R.id.bottombaritem_channels:
FragmentTransaction ft2 = getSupportFragmentManager().beginTransaction();
if(fragName.equals("events")) {
ft2.setCustomAnimations(R.anim.right_slide_in, R.anim.left_slide_out);
} else {
ft2.setCustomAnimations(R.anim.left_slide_in, R.anim.right_slide_out);
}
ft2.replace(R.id.frame_fragmentholder, new ChannelsFragment());
ft2.commit();
fragName = "channels";
return true;
case R.id.bottombaritem_more:
if(!fragName.equals("more")) {
FragmentTransaction ft3 = getSupportFragmentManager().beginTransaction();
ft3.setCustomAnimations(R.anim.right_slide_in, R.anim.left_slide_out);
ft3.replace(R.id.frame_fragmentholder, new MoreFragment());
ft3.commit();
fragName = "more";
}
return true;
}
return false;
}
});
}
private void setMainFragment(){
fragName = "events";
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.frame_fragmentholder, new EventsFragment());
ft.commit();
}
#Override
public void onBackPressed() {
super.onBackPressed();
Constants.overridePendingTransitionExit(this);
}
}
And here is EventsFragment.java
public class EventsFragment extends Fragment {
private RecyclerView mRecyclerView;
private ArrayList<String> mData;
private CollapsingToolbarLayout collapsing_toolbar;
private Context mContext;
public EventsFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_events, container, false);
mContext = getActivity();
final CollapsingToolbarLayout collapsingToolbarLayout = (CollapsingToolbarLayout) view.findViewById(R.id.collapsing_toolbar);
AppBarLayout appBarLayout = (AppBarLayout) view.findViewById(R.id.app_bar);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean isShow = true;
int scrollRange = -1;
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (scrollRange == -1) {
scrollRange = appBarLayout.getTotalScrollRange();
}
if (scrollRange + verticalOffset == 0) {
collapsingToolbarLayout.setTitle("Events");
isShow = true;
} else if(isShow) {
collapsingToolbarLayout.setTitle(" ");//carefull there should a space between double quote otherwise it wont work
isShow = false;
}
}
});
// Initialize the RecyclerView
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view_events);
setUpRecyclerView();
return view;
}
private void setUpRecyclerView() {
LinearLayoutManager llm = new LinearLayoutManager(mContext);
llm.setAutoMeasureEnabled(true);
mRecyclerView.setLayoutManager(llm);
EventsAdapter eventsAdapter = new EventsAdapter(mContext);
mRecyclerView.setAdapter(eventsAdapter);
}
}
Any help would be really appreciated. Thanks!
Remove this line from Event XML.
android:fitsSystemWindows="true"
And everything would be good to go.
override the fragment's setUserVisibleHint(),call view?.requestlayout()
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
view?.requestLayout()
super.setUserVisibleHint(isVisibleToUser)
}
collapsingToolbarLayout.setTitle("Events");
this layout is hiding your last Recycler view, when this is shown your last item is hidden, when you set
collapsingToolbarLayout.setTitle("");
your last item is visible.
So, set padding to parent layout accordingly

Why this tab layout doesn't stay in the bottom?

I've created my application with Navigation Drawer. In my Activity I put this code:
public class MenuActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
{
public void onDrawerOpened(View view)
{
super.onDrawerOpened(view);
}
public void onDrawerClosed(View v)
{
super.onDrawerClosed(v);
}
};
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
onNavigationItemSelected(navigationView.getMenu().getItem(0));
navigationView.setNavigationItemSelectedListener(this);
}
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
if (id == R.id.action_settings)
{
return true;
}
return super.onOptionsItemSelected(item);
}
public boolean onNavigationItemSelected(MenuItem item) {
Fragment fragment = null;
String title = null;
int id = item.getItemId();
Class fragmentClass=null;
if (id == R.id.Home)
{
fragmentClass = HomeFragment.class;
title="Home";
}
else if (id == R.id.Profile)
{
fragmentClass= ProfileFragment.class;
title="Profile";
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
if (getSupportActionBar() != null)
{
getSupportActionBar().setTitle(title);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
now in the HomeFragment I want to put a tab in the bottom of the screen. So i put this code:
public class HomeFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = 3 ;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View inflatedView = inflater.inflate(R.layout.fragment_home, null);
tabLayout = (TabLayout) inflatedView.findViewById(R.id.tabs);
viewPager = (ViewPager) inflatedView.findViewById(R.id.viewpager);
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return inflatedView;
}
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
/**
* Return fragment with respect to Position .
*/
#Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new SearchFragment();
case 1 : return new CardFragment();
case 2 : return new MapFragment();
}
return null;
}
public int getCount() {
return int_items;
}
This is fragment_home.xml:
<FrameLayout 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"
tools:context=".HomeFragment">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
app:tabGravity="fill"
app:tabMode="fixed"
android:background="#color/material_blue_grey_800"
app:tabIndicatorColor="#color/black_overlay"
app:tabSelectedTextColor="#000"
app:tabTextColor="#FFFFFF"
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true">
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/tabs">
</android.support.v4.view.ViewPager>
</RelativeLayout>
</FrameLayout>
and this the activity xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_menu"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/containerView">
</FrameLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_menu"
app:menu="#menu/activity_menu_drawer" />
</android.support.v4.widget.DrawerLayout>
But finally I get this result:
How could I put this tabLayout in the toolbar?
You don't need to take frame layout for fragment_home as root layout. Simplify your xml file as:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
app:tabGravity="fill"
app:tabMode="fixed"
android:background="#color/material_blue_grey_800"
app:tabIndicatorColor="#color/black_overlay"
app:tabSelectedTextColor="#000"
app:tabTextColor="#FFFFFF"
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true">
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/tabs">
</android.support.v4.view.ViewPager>
</RelativeLayout>

How to add Material design Navigation drawer with sliding tabs?

I want something very similar to this:
I have already added Sliding tabs and it's working perfectly fine but I am not able to figure out how to add a navigation drawer to existing code.
So far, I have created a PagerAdapter class to view different Fragment class. Following is my MainActivity class:
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Tab1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab2"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter
(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Menu_main.xml
<menu 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"
tools:context=".MainActivity">
......
......
<item
android:id="#+id/action_user"
android:orderInCategory="300"
android:title="User"
android:icon="#drawable/ic_drawer"
app:showAsAction="ifRoom"></item>
</menu>
In above code I added a icon for open drawer. This my Ëšactivity_main.xml
<RelativeLayout
android:id="#+id/main_layout"
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=".MainActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
<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:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="#id/tab_layout"/>
</RelativeLayout>
Any hint how to add Navigation Drawer to android bar ?
here is useful template for Android Studio, which adds Material Design Navigation Drawer
UPD
To add sliding tabs, include ViewPager with PagerTabStrip in activity_main layout file
<android.support.v4.view.ViewPager
android:id="#+id/tabanim_viewpager"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" >
<android.support.v4.view.PagerTabStrip
android:id="#+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#color/primary_500"
android:textColor="#color/white"
android:paddingTop="5dp"
android:layout_marginBottom="5dp" />
</android.support.v4.view.ViewPager>
activity onCreate:
PagerTabStrip pagerTabStrip = (PagerTabStrip) findViewById(R.id.pager_title_strip);
pagerTabStrip.setDrawFullUnderline(false);
pagerTabStrip.setTabIndicatorColor(getResources().getColor(R.color.red_dark));
final ViewPager viewPager = (ViewPager) findViewById(R.id.tabanim_viewpager);
setupViewPager(viewPager);
Code in Activity:
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
//adding tabs
adapter.addFrag(new PinsFragment(), "Pins");
adapter.addFrag(new BoardsFragment(), "Boards");
adapter.addFrag(new InterestsFragment(), "Likes");
adapter.addFrag(new SubscriptionsFragment(), "Subscriptions");
adapter.addFrag(new FollowersFragment(), "Followers");
viewPager.setAdapter(adapter);
}

Categories

Resources