Why my toolbar not setting menu on fragment? - android

I am building android shopping app that have the cart menu item and all products are opening in fragment and i want to set the MainActivity menu items on the product fragment and other fragments.
So the user is easy to open the cart from the product view fragment.below code
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.product_view_fragment, null);
setHasOptionsMenu(true);
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar(toolbar);
getActivity().invalidateOptionsMenu();
toolbar = (Toolbar)view.findViewById(R.id.toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getActivity().onBackPressed();
}
});
this.context = getContext();
String id=getArguments().getString("message");
//String size=getArguments().getString("size");
viewPager = (ViewPager)view.findViewById(R.id.viewPager);
SessionManager sessionManager = new SessionManager(getContext());
email = sessionManager.getUserDetails().get("id");
sliderDotspanel = (LinearLayout)view.findViewById(R.id.SliderDots);
GetOneProduct(id);
return view;
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
xmlns:segmentedgroup="http://schemas.android.com/tools"
android:orientation="vertical"
android:clickable="true"
android:background="#color/colorWhite"
android:layout_height="wrap_content">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#android:style/Animation.Activity">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:navigationIcon="?attr/homeAsUpIndicator"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:titleTextColor="#color/Black" />
</android.support.design.widget.AppBarLayout>
Blockquote

I assume you use a single activity approach.
Then your activity should include Toolbar in its layout something like this.
<android.support.constraint.ConstraintLayout 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=".navigation.HomeActivity">
<androidx.appcompat.widget.Toolbar></androidx.appcompat.widget.Toolbar>
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/app_navigation" />
<com.google.android.material.bottomnavigation.BottomNavigationView>
// if you have bottom nav.
</com.google.android.material.bottomnavigation.BottomNavigationView>
Then set up the toolbar as you wish in your activity.

Related

Fragment opened separately from Activity doesnt show up actionbar

I have been using the NavigationDrawer activity. I have been calling the fragment from the activity. It gets called successfully but the actionbar is not showing up.
Code: Gallery_Frag - an activity created to extend teh fragment that i want to show up.
public class Gallery_Frag extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_bar_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (savedInstanceState == null){
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, new GalleryFragment()).commit(); }
}
CODE: GalleryFragment
public class GalleryFragment extends Fragment {
private GalleryViewModel galleryViewModel;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
galleryViewModel =
ViewModelProviders.of(this).get(GalleryViewModel.class);
View root = inflater.inflate(R.layout.fragment_gallery, container, false);
/* final TextView textView = root.findViewById(R.id.text_gallery);
galleryViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});*/
return root;
}}
CODE: manifest
<activity android:name=".Gallery_Frag"
android:label="My Bookings"
android:theme="#style/AppTheme.NoActionBar"/>
CODE:app_bar_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<androidx.appcompat.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" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
CODE: content_main
<?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:showIn="#layout/app_bar_main">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
</RelativeLayout>
You may have a container inside this content_main.xml;
if yes, pass that id to the add(R.id.container_id, new GalleryFragment())...
Otherwise change <include layout="#layout/content_main" /> to
<include layout="#layout/content_main"
android:id="#+id/fragment_container"/>
and use
add(R.id.fragment_container, new GalleryFragment())...
First of all, you have to set layout to Activity using setContentView which contain Toolbar
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Set it first
setContentView(R.layout.your_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (savedInstanceState == null){
getSupportFragmentManager().beginTransaction()
.add(R.id.content, new GalleryFragment()).commit(); }
}
Got it
In your content_main.xml file, add an id to the parent relative layout like below,
<RelativeLayout
android:id="#+id/fragment_container"
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:showIn="#layout/app_bar_main">
And replace,
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, new GalleryFragment()).commit();
with
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new GalleryFragment()).commit();
This will hopefully work.

Error sending data from one fragment to another fragment. ( Both fragments are hosted by one activity)

I am having troubling sending data from one fragment to another fragment. I was following the android guideline which tells me to create an interface to communicate with activity and fragments. I'm using the bottom navigation to switch over fragments.
Anyway, here's the error from android studio:
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.makkhay.cameratranslate.Favorite.displayReceivedData(java.lang.String)' on a null object reference
at com.example.makkhay.cameratranslate.HomeActivity.sendData(HomeActivity.java:143)
at com.example.makkhay.cameratranslate.HomeFragment$2.onClick(HomeFragment.java:162)
at android.view.View.performClick(View.java:6256)
at android.view.View$PerformClick.run(View.java:24697)
at android.os.Handler.handleCallback(Handler.java:789)
For some reason, my fragments are always null even after initializing it. I tried initializing it both ways, onCreate method, and the sendData method, the instance always seems to be null. I think the main culprit might be the DrawerLayout. Since it is the parent xml and there is another xml called "app_bar_home.xml"; which is hosting the two fragments using bottom navigation, the newly created instances are always null
Here's my main activity which is holding two fragments
HomeActivity.java
public class HomeActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener,HomeFragment.SendMessage {
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.navigation_home:
selectedFragment = new HomeFragment();
break;
case R.id.navigation_favorite:
selectedFragment = new Favorite();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.app_bar,
selectedFragment).commit();
return true;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
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);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
//I added this if statement to keep the selected fragment when rotating the device
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.app_bar,
new HomeFragment()).commit();
}
}
#Override
public void sendData(String message) {
Favorite f = (Favorite) getSupportFragmentManager().findFragmentById(R.id.favFragment);
f.displayReceivedData(message);
}
}
Here's my xml for my activity
activity_home.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
android:id="#+id/app_bar"
layout="#layout/app_bar_home"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<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_home"
app:menu="#menu/activity_home_drawer" />
</android.support.v4.widget.DrawerLayout>
Here's the app_bar_home.xml which is also part of the activity
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".HomeActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
>
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin"
android:id="#+id/toolbar"
/>
</android.support.design.widget.AppBarLayout>
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
app:layout_constraintBottom_toBottomOf="parent"
android:background="#000"
app:itemIconTint="#color/color_selector"
app:itemTextColor="#color/color_selector"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/navigation" />
</android.support.constraint.ConstraintLayout>
Here's the fragment 1 from which I want to send the data to another fragment.
HomeFragment.java
public class HomeFragment extends Fragment implements View.OnClickListener{
SendMessage SM;
private Button clearButton, favButton, shareButton;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_home, container, false);
return v;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
favButton = view.findViewById(R.id.favButton);
favButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SM.sendData(" test");
}
});
}
interface SendMessage {
void sendData(String message);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
SM = (SendMessage) getActivity();
} catch (ClassCastException e) {
throw new ClassCastException("Error in retrieving data. Please try again");
}
}
}
HomeFragment.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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/homeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".HomeFragment"
>
<android.support.design.widget.AppBarLayout
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="?actionBarSize"
app:layout_collapseMode="pin" />
</android.support.design.widget.AppBarLayout>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="6dp"
android:layout_marginEnd="6dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginStart="6dp"
android:layout_marginTop="56dp"
android:background="#drawable/card_shadow"
android:divider="?android:dividerHorizontal"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:showDividers="middle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="16dp"
android:gravity="right"
android:orientation="vertical">
<Button
android:id="#+id/favButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginTop="4dp"
android:background="#drawable/ic_favorite_black_12dp"
/>
</LinearLayout>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
Finally here's the 2nd fragment where I want to recieve the data
Favorite.java
public class Favorite extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_favorite, container, false);
favText = v.findViewById(R.id.tv_recycler_item_1);
return v;
}
protected void displayReceivedData(String message)
{
Toast.makeText(getContext(),"rec:" + message,Toast.LENGTH_SHORT).show();
}
}
fragment_favorite.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/favFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Favorite">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_scrolling"
android:layout_width="match_parent"
android:layout_height="180dp"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="#drawable/bg_red" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/Widget.AppCompat.PopupMenu.Overflow" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
>
<TextView
android:id="#+id/txtData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="548dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/recycler_view_recycler_view"
app:layout_constraintStart_toStartOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view_recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="382dp"
android:layout_marginEnd="344dp"
android:layout_marginRight="344dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
</android.support.design.widget.CoordinatorLayout>
Let me know if you need more info. thanks in advance :)
you can pass data between fragment by putting as argument in bundle like following:
Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);
For retrieving you can do following
Bundle bundle = this.getArguments();
if (bundle != null) {
int myInt = bundle.getInt(key);
}
On my view best way of communication is by using EventBus between Activity-fragment, fragment-fragment, Activity-Activty, very easy and less complicated
Here is an Example
Create a model of what you want to share, so here is model for sending string declare the string variable use constructor and getter for setting and getting message
public MessageEvent(String Message)
{
this.msg=msg;
}
public String getMsg() {
return msg;}
Now in your fragment 1 post the message before that register eventbus on OnAttach and deregister it in OnDettach
EventBus.getDefault().post(new MessageEvent("My Message));
In Fragment 2 get the message in OnEvent Method(even in this fragment don't forget to register and deregister Event Bus)
#Subscribe
public void onEvent(MessageEvent event) {
this.msg=event.getMsg();
callTheMethodToDoYourOperation(msg);
}
This a basic example, but check about event bus before using this and moreover in both fragment you require to Register, deregister and subscribe onevent, and if this is one way communication let onEvent be empty
Hope this helps
The NullPointerException occurred because your Fragment is not initialized yet, so before interacting with is make sure you check is it initialized and visible or not.
if (f!= null && f.isVisible()) {
f.displayReceivedData(message);
}
You can also use Bundle to pass data between Fragment too.
Note: Before posting question understand the error and try to debug the root cause of the error. You'll definitely solve it on your own.
Happy coding :)
You are getting Null pointer on method where you receive data, that fragment instance is null. Favorite f is null.
Create one instance if that fragment and then call .replace

Bottomnavigationview hides when switching from a tab with collapsing toolbar

I have a MainActivity XML that contains a bottomNavigationView (bar) with 5 tabs. Each tab calls a different fragment. Switching from a fragment with a collapsing toolbar in its XML (labelled A in picture) to a fragment with a plain fragment (labelled B in picture) causes the bottomNavigationView (bar) to hide partially off the screen.
Is there a way of preventing this?
Screen with fragment containing collapsing toolbar.
Screen of another tab with a plain fragment.
Fragment Class containing code for collapsing toolbar
public class Profile extends Fragment {
public Profile() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_profile, container, false);
Toolbar toolbar = rootView.findViewById(R.id.toolbar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar(toolbar);
activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
CollapsingToolbarLayout collapsingToolbar = rootView.findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle("test");
return rootView;
}
Corresponding xml containing collapsing toolbar code
<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/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler"
android:layout_width="match_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="180dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/ani_dog_one"
android:contentDescription="whut"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
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" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Plain fragment class
public class Review extends Fragment {
public Review() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_review, container, false);
//setHasOptionsMenu(true);
return rootView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.search_bar_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
XML for plain fragment class contains just a plain FrameLayout
MainActivity
public class MainActivity extends AppCompatActivity {
private Intent intent;
private android.support.v4.app.FragmentManager manager;
private android.support.v4.app.FragmentTransaction transaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = getSupportFragmentManager();
transaction = manager.beginTransaction();
Discover discoverFragment = new Discover();
transaction.replace(R.id.container, discoverFragment, discoverFragment.getTag()).commit();
setupBottomNavigationView();
}
private void setupBottomNavigationView() {
BottomNavigationViewEx bottomNavigationViewEx = (BottomNavigationViewEx) findViewById(R.id.bottom_navigation);
BottomNavigationViewHelper.setupBottomNavigationView(bottomNavigationViewEx);
BottomNavigationViewHelper.enableNavigation(this, bottomNavigationViewEx);
}
public void goToOptions(MenuItem menu) {
intent = new Intent(this, Options.class);
overridePendingTransition(R.anim.left_in, R.anim.right_out);
startActivity(intent);
}
}
XML for MainActivity
<LinearLayout 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:orientation="vertical"
tools:context="com.example.android.project_qwer.MainActivity">
<!-- main fragments goes here -->
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</FrameLayout>
<!-- bottom navigation view -->
<com.ittianyu.bottomnavigationviewex.BottomNavigationViewEx
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"
app:menu="#menu/bottom_navigation_menu" >
</com.ittianyu.bottomnavigationviewex.BottomNavigationViewEx>
</LinearLayout>
Try to remove
android:fitsSystemWindows="true"
on your CollapsingToolbarLayout.
try
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
when you switch to tab with collapsing toolbar and
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
when switch to another
Try to put
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
</android.support.design.widget.CoordinatorLayout>
as the root of all the other fragments you are loading from the BottomNavigationView.
If you use a custom toolbar in the profile fragment,you put this code to onCreateView method:
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
I had the same problem and this was solved.
Remove android:fitsSystemWindows="true"
from root CoordinatorLayout.

Cannot scroll RecyclerView inside a Fragment?

I am having troubles integrating a RecyclerView (using cardviews for the rows) inside a fragment. For some reason I cannot scroll the card view? Please, any suggestions?
This is my app design:
This is my fragment code:
public class PageFragment2 extends Fragment {
public static final String ARG_PAGE2 = "ARG_PAGE";
private int mPage2;
public static PageFragment2 newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE2, page);
PageFragment2 fragment = new PageFragment2();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage2 = getArguments().getInt(ARG_PAGE2);
Log.d("MainActivity", "onCreate" + mPage2);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page2,container,false);
RecyclerView recList = (RecyclerView) view;
recList.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
recList.setLayoutManager(llm);
ArrayList<String> names = new ArrayList<>();
names.add("Georgi Koemdzhiev");
names.add("Mariya Menova");
names.add("Simeon Simeonov");
names.add("Ivan Dqkov");
names.add("Dymityr Vasilev");
names.add("Petar Dimov");
CardAdapter adapter = new CardAdapter(names);
recList.setAdapter(adapter);
Log.d("MainActivity","onCreateView" + mPage2);
return view;
}
}
This is my fragment XML code:
<android.support.v7.widget.RecyclerView
android:id="#+id/cardList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="true"
xmlns:android="http://schemas.android.com/apk/res/android"/>
My activity_main 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"
tools:context="koemdzhiev.com.newtablayouttest.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"/>
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:background="#android:color/white" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main"/>
The Activity from the "Tabbed Activity" template, which contains the ViewPager which is containing your Fragment, uses an AppBarLayout.
This AppBarLayout is stealing the vertical movement, since it doesn't know there's a scrollable nested view (the RecyclerView) inside the ViewPager. Remove the AppBarLayout from the XML file of your Activity (you can take the TabLayout and ToolBar to the upper level).

Inflating AppBarLayout with Toolbar + TabLayout

I currently have a DrawerLayout in my main.xml. There's a Toolbar wrapped in an AppBarLayout, and then a simple LinearLayout to swap out fragments.
One of the fragments I navigate to, I want it to contain a TabLayout for a ViewPager of fragments. Currently, I have both of these in the fragment's layout file, but this causes a drop shadow to appear between the Toolbar and the TabLayout, which is something I don't want. I also don't want to use setElevation() because it won't work for pre-Lollipop devices.
A possible solution would be to inflate the AppBarLayout from my fragment, so that it holds both the Toolbar+Tabs. However, I'm not really sure how to do this, so any help would be appreciated.
Here is my main.xml file:
<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/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lumivote.lumivote.ui.MainActivity">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbarlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_header"
app:itemIconTint="#333"
app:itemTextColor="#333"
app:menu="#menu/navigation_drawer_items" />
</android.support.v4.widget.DrawerLayout>
And here is my fragment's xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.alexdao.democracy.ui.candidate_tab.CandidateListFragment">
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/myPrimaryColor"
app:tabMode="fixed"
app:tabGravity="fill"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white" />
</LinearLayout>
You are able to have separate toolbar for each fragment. Its possible to set fragments toolbar as activity actionbar. Example code:
Toolbar toolbar = (Toolbar) v.findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
It should be possible to have titles, icons and other stuff as well.
With it you can mimic shadow on pre lollipop devices, no matter what you have on them.
I modified the solution given by bleeding182 and got it to work for AppBarLayout as well (to resolve the problem pointed out by bopa).
#Override
public void onAttach(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().findViewById(R.id.appbar).setElevation(0);
}
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().findViewById(R.id.appbar).setElevation(R.dimen.toolbar_elevation);
}
}
What I did was replace the call to getSupportActionBar() by giving an ID to my AppBarLayout and then calling findViewById() on it and then calling setElevation on its result. Tested on API 23.
I had a similar issue where I wanted a TabLayout just inside of one fragment.
Without changing any other code you can solve this by using onAttach and onDetach inside your fragment with the TabLayout.
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// todo add some further checks, e.g. instanceof, actionbar != null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
((AppCompatActivity) activity).getSupportActionBar().setElevation(0);
}
}
#Override
public void onDetach() {
super.onDetach();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
((AppCompatActivity) getActivity()).getSupportActionBar()
.setElevation(getResources().getDimension(R.dimen.toolbar_elevation));
}
}
Be sure to set the same elevation on your TabLayout and everything works fine! ;D
You can simply add TabLayout programmatically from Fragment in wich you need TabLayout
tabLayout = (TabLayout) inflater.inflate(R.layout.tablay, null);
appBarLayout = (AppBarLayout) getActivity().findViewById(R.id.appbar);
appBarLayout.addView(tabLayout, new LinearLayoutCompat.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
and remove TabLayout from AppBar in onDetach()
#Override
public void onDetach() {
appBarLayout.removeView(tabLayout);
super.onDetach();
}
To fix my problem I ended up putting the Toolbar, TabLayout, and ViewPager all in my MainActivity.
main_activity.xml:
<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/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<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"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white" />
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_header"
app:itemIconTint="#333"
app:itemTextColor="#333"
app:menu="#menu/navigation_drawer_items" />
</android.support.v4.widget.DrawerLayout>
Then, in all of my fragments, I set the visibility for the TabLayout and the ViewPager programmatically in onCreateView:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TabLayout tabLayout = (TabLayout) getActivity().findViewById(R.id.tabLayout);
tabLayout.setVisibility(View.GONE);
ViewPager mViewPager = (ViewPager) getActivity().findViewById(R.id.viewpager);
mViewPager.setVisibility(View.GONE);
return inflater.inflate(R.layout.fragment_layout, container, false);
}
Of course, in the fragment with tabs, you would want to set the visibility to View.VISIBLE instead of View.GONE.
The Artem_lens approach worked for me with some modifications.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
mTabLayout = (TabLayout) inflater.inflate(
R.layout.partial_tab_layout,
container,
false);
mAppBarLayout = (AppBarLayout) getActivity().findViewById(R.id.app_bar);
mAppBarLayout.addView(mTabLayout,
new LinearLayoutCompat.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
...
}
And removing the view at onDestroyView()
#Override
public void onDestroyView() {
mAppBarLayout.removeView(mTabLayout);
super.onDestroyView();
}
The solution is simple in the XML. Just add the following code to your AppBarLayout: app:elevation="0dp". So the AppBarLayout should look like this:
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
android:theme="#style/AppTheme.AppBarOverlay">

Categories

Resources