I've seen many posts on this matter, but I can't figure it out for my code. I have created a tabbed activity and set three buttons at the bottom. The buttons switch between different fragments. A button in a MainActivity opens this tabbed activity, but the problem is that the fragment layout is empty (see image below).
The buttons work perfectly and send me to the right fragments, but when it opens, no fragments are loaded.
The code, which I build following an YouTube tutorial looks like this:
TabbedActivity.class
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
public class TabbedActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabbed_activity);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
int intentFragment = getIntent().getExtras().getInt("frgToLoad");
switch (item.getItemId()) {
case R.id.navigation_home:
transaction.replace(R.id.content,new Fragment_B1()).commit();
/* mTextMessage.setText(R.string.title_home);*/
return true;
case R.id.navigation_dashboard:
transaction.replace(R.id.content,new Fragment_B2()).commit();
/*mTextMessage.setText(R.string.title_dashboard);*/
return true;
case R.id.navigation_notifications:
transaction.replace(R.id.content,new Fragment_B3()).commit();
/*mTextMessage.setText(R.string.title_notifications);*/
return true;
}
return false;
}
};
}
The fragments have the same code pattern inside, which is basic and it makes no point to add it here. The xml of the TabbedActivity looks like this:
<?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="TabbedActivity">
<FrameLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="#+id/appbar">
</FrameLayout>
<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"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/navigation" />
</android.support.constraint.ConstraintLayout>
Can anyone help me to figure out how to open Fragment_B1 by default? I have tried adding the code from the best answer from here, but still doesn't work.
You can just added the original fragment direct on the onCreate, like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabbed_activity);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
if(savedInstanceState == null) {
getSupportFragmentManager().
beginTransaction().replace(R.id.content,new Fragment_B1()).commit();
}
}
In the last add, navigation.setSelectedItemId(navigation_home);
Related
I have followed the material guideline here but for some reason, the bottom navigation is not working for me. My app simply displays a white frame where the bottom navigation should be. What am I doing wrong? Please note that I commented out the onCreateOptionsMenu in my MainActivity.java shown below. If I uncomment this code, the items in my menu_bottom_navigation.xml show up in the app bar menu but I want to have them show up in the bottom navigation bar.
Build.gradle
...
implementation 'com.google.android.material:material:1.1.0'
...
Menu resource:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/discover"
android:enabled="true"
android:title="#string/title_activity_discover_movies"
android:icon="#drawable/ic_search_24px"/>
<item
android:id="#+id/favorites"
android:enabled="true"
android:title="#string/title_activity_favorite_movies"
android:icon="#drawable/ic_favorite_24px" />
</menu>
Layout resource:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context=".features.movieoptions.movielist.MainActivity">
<include
layout="#layout/toolbar_discover_movies"
android:id="#+id/toolbar_movie_list" />
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?attr/actionBarSize"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
android:background="#color/colorPrimary"
app:itemBackground="#color/colorPrimary"
app:itemTextColor="#color/colorTextIcons"
app:menu="#menu/menu_bottom_navigation"/>
</FrameLayout>
</LinearLayout>
MainActivity.java
package edu.bu.metcs.activitylifecycle.features.movieoptions.movielist;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import edu.bu.metcs.activitylifecycle.R;
import edu.bu.metcs.activitylifecycle.features.movieoptions.movielist.discover.DiscoverFragment;
import edu.bu.metcs.activitylifecycle.features.movieoptions.movielist.favorites.FavoritesFragment;
import edu.bu.metcs.activitylifecycle.shared.FragmentUtility;
/**********************************************************************************************************************
* This activity manages the apps fragments and decides which fragment should be displayed to the user.
*
* #author mlewis
* #version June 5, 2020
*********************************************************************************************************************/
public class MainActivity extends AppCompatActivity {
// Invariant of the MovieListActivity.java class
// 1. A shareActionProvider sends an implicit intent to apps capable of handling the text/plain MIME type.
// 2. The TAG is used by the Logcat for informational purposes.
private DiscoverFragment discoverFragment;
private FavoritesFragment favoritesFragment;
private static final String TAG = MainActivity.class.getSimpleName();
/**
* protected void onCreate(Bundle savedInstanceState)
* Performs initial Activity set up.
*
* #param savedInstanceState A bundle for any saved state from prior sessions that were destroyed.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
discoverFragment = DiscoverFragment.newInstance();
favoritesFragment = FavoritesFragment.newInstance();
// Show discover fragment by default
setUpFragment(discoverFragment);
}
setUpBottomNavigation();
setUpToolbar();
}
// #Override
// public boolean onCreateOptionsMenu(Menu menu) {
// super.onCreateOptionsMenu(menu);
// getMenuInflater().inflate(R.menu.menu_bottom_navigation, menu);
// return true;
// }
private void setUpFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentUtility.fragmentTransaction(fragmentManager, R.id.fragment_container, fragment);
}
private void setUpBottomNavigation() {
Log.d(TAG, "Setting bottom nav.");
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.discover:
Log.d(TAG, "discover was clicked.");
setUpFragment(discoverFragment);
return true;
case R.id.favorites:
Log.d(TAG, "favorites was clicked.");
setUpFragment(favoritesFragment);
return true;
}
return false;
}
});
}
private void setUpToolbar() {
Toolbar toolbar = findViewById(R.id.toolbar_movie_list);
setSupportActionBar(toolbar);
}
}
Please see the white section at the bottom of the screen to see the issue:
As i Checked your layout. i found the mistake
1. Fragment Container(Frame layout) having wrong margin bottom
2. Need to add wight for fragment container(Frame Layout)
Corrected code as below
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context=".features.movieoptions.movielist.MainActivity">
<include
layout="#layout/toolbar_discover_movies"
android:id="#+id/toolbar_movie_list" />
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"
app:itemBackground="#color/colorPrimary"
app:itemTextColor="#color/colorTextIcons"
app:menu="#menu/menu_bottom_navigation"/>
</FrameLayout>
</FrameLayout>
</LinearLayout>
I am trying to use bottom navigation but the buttons or icons appears in the middle not in the bottom, I have use drawer navigation in the same activity i.e. I declare a drawer layout in the xml resource layout.
?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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello"/>
</LinearLayout>
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="168dp"
android:layout_height="168dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/navigation" />
<android.support.design.widget.NavigationView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:menu="#menu/drawer"
android:layout_gravity="start">
</android.support.design.widget.NavigationView>
The code of this activity:
package com.example.welcome.madrasti;
import android.content.ClipData;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView mTextMessage;
Intent intent1;
private DrawerLayout d;
private ActionBarDrawerToggle a;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_dashboard:
return true;
case R.id.navigation_home:
return true;
}
return false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
d = (DrawerLayout) findViewById(R.id.container);
a= new ActionBarDrawerToggle(MainActivity.this,d,R.string.open,R.string.close);
d.addDrawerListener(a);
a.syncState();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
intent1= new Intent(getApplicationContext(),MapsActivity.class);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(a.onOptionsItemSelected(item)){
return true;
}
return super.onOptionsItemSelected(item);
}
}
Is there any idea ?. I have got the bottom navigation as follows : here
Changing padding at the Bottom to small a value like:
android:paddingBottom="2dp"
Also your BottomNavigationView appears to be a square of 168dp size. Is this intentionally? Change the height it or view its layout bounds. It may be very big by itself like a square.
I have been implementing a bottom navigation bar into my app, the problem is no matter which activity I am on the dashboard icon is the highlighted one. How do I get it so whichever activity I am on is the highlighted one?
public class Dashboard extends AppCompatActivity
implements View.OnClickListener
{
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener()
{
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item)
{
switch (item.getItemId())
{
case R.id.navigation_request:
Intent r = new Intent(Dashboard.this, Request.class);
startActivity(r);
finish();
break;
case R.id.navigation_settings:
Intent s = new Intent(Dashboard.this, AppSettings.class);
startActivity(s);
finish();
break;
}
return false;
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
Here is my XML Menu file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_home"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/title_home" />
<item
android:id="#+id/navigation_request"
android:icon="#drawable/ic_request_icon"
android:title="#string/title_request" />
<item
android:id="#+id/navigation_settings"
android:icon="#drawable/ic_icon_settings"
android:title="#string/title_settings" />
</menu>
Here is how I use the navigation in my activity_dashboard
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<!-- ONLY TEXTVIEWS ARE HERE -->
</FrameLayout>
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"
app:menu="#menu/navigation" />
</LinearLayout>
Using many different Activity instances that all duplicate the BottomNavigationView and its associated code (like the OnNavigationItemSelectedListener etc) is not recommended. Instead, you would generally use a single Activity that hosts the BottomNavigationView as well as multiple Fragment instances that are .replace()d into your content area as the user interacts with the BottomNavigationView.
That being said, let's see if we can solve your problem.
There are two pieces to this puzzle. The first is simple: you have to indicate which item in your BottomNavigationView should be selected. This can be achieved by calling setSelectedItemId(). Add something like this to your onCreate() method.
navigation.setSelectedItemId(R.id.navigation_settings);
The second is a little more complicated. When you call setSelectedItemId(), the system is going to behave as though a user had tapped on that item. In other words, your OnNavigationItemSelectedListener will be triggered.
Looking at your posted listener, I notice that you always return false. If you check the documentation for onNavigationItemSelected(), you will find
Returns:
true to display the item as the selected item and false if the item should not be selected
So the call to setSelectedItemId() won't work without also changing your listener to return true.
You could still solve the problem with just a setSelectedItemId() call if you place that call before your setOnNavigationItemSelectedListener() call, but that's just masking the problem. It'd be better to fix your listener to return true in cases where you want the tapped item to appear as selected.
Step - 1 put below code into app level Build.gradle
implementation 'androidx.navigation:navigation-fragment:2.3.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.navigation:navigation-ui:2.3.0'
Step - 2 put below code into activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
<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_constraintBottom_toTopOf="#id/nav_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Step - 3 put below code into menu/bottom_nav_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_home"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/title_home" />
<item
android:id="#+id/navigation_dashboard"
android:icon="#drawable/ic_dashboard_black_24dp"
android:title="Orders" />
<item
android:id="#+id/navigation_notifications"
android:icon="#drawable/ic_notifications_black_24dp"
android:title="Services" />
<item
android:id="#+id/navigation_account"
android:icon="#drawable/ic_notifications_black_24dp"
android:title="Account" />
</menu>
Step - 4 put below code into MainActivity.java
import android.os.Bundle;
import android.view.MenuItem;
import com.example.bottomnavigationdemo.ui.account.AccountFragment;
import com.example.bottomnavigationdemo.ui.dashboard.DashboardFragment;
import com.example.bottomnavigationdemo.ui.home.HomeFragment;
import com.example.bottomnavigationdemo.ui.notifications.NotificationsFragment;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navView = findViewById(R.id.nav_view);
navView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
Fragment fragment = new HomeFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, fragment, fragment.getClass().getSimpleName())
.commit();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.nav_host_fragment, fragment, fragment.getClass().getSimpleName());
transaction.commit();
return true;
case R.id.navigation_dashboard:
Fragment fragment2 = new DashboardFragment();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.nav_host_fragment, fragment2, fragment2.getClass().getSimpleName());
transaction.commit();
return true;
case R.id.navigation_notifications:
Fragment fragment3 = new NotificationsFragment();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.nav_host_fragment, fragment3, fragment3.getClass().getSimpleName());
transaction.commit();
return true;
case R.id.navigation_account:
Fragment fragment4 = new AccountFragment();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.nav_host_fragment, fragment4, fragment4.getClass().getSimpleName());
transaction.commit();
return true;
}
return true;
}
});
}
}
Step - 5 put below code into HomeFragment.java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import com.example.bottomnavigationdemo.R;
import com.example.bottomnavigationdemo.ui.dashboard.DashboardFragment;
public class HomeFragment extends Fragment {
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_home, container, false);
return root;
}
}
Just use method setSelectedItemId(int id) which let's you mark an item as selected as if it was tapped.
Like this:
BottomNavigationView bottomNavigationView;
bottomNavigationView = (BottomNavigationView)
findViewById(R.id.bottomNavigationView);
bottomNavigationView.setSelectedItemId(R.id.my_menu_item_id);
Im working on a small google maps app that lets users find places close to them, I want to add functionality that lets the user add a place to a list of favourites, So far ive created classes that may do the functionality.
My main activity is my home page which opens other activities, code below:
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageButton;
public class MainActivity extends AppCompatActivity {
ImageButton btnNearBy;
ImageButton btnFavourites;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnNearBy = (ImageButton) findViewById(R.id.btnNearby);
btnNearBy.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent mapIntent = new Intent(getBaseContext(), MapsActivity.class);
startActivity(mapIntent);
}
});
btnFavourites = (ImageButton) findViewById(R.id.btnFavourites);
btnFavourites.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fragmentManager = MainActivity.this.getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FavouriteListFragment fragment = new FavouriteListFragment();
fragmentTransaction.add(R.id.fragment_container, fragment); //ERROR ON THIS LINE
fragmentTransaction.commit();
}
});
}
}
Ive created a button that should open up the fragment that holds the list of favourites ,My fragment is declared like this:
public class FavouriteListFragment extends Fragment { ... }
Im a little unsure how to open the fragment from the MainActivity when clicking a button.
Any ideas?
Thanks!
There are two ways of displaying fragments:
1- First you need to define a fragment container in your code like the following:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="do something"
android:onClick="openFragment" />
<FrameLayout
android:id="#+id/fragment_container"
android:layout_height="wrap_content"
android:layout_width="match_content" />
</LinearLayout>
and then you need to create a function called openFragment in your activity and use the following code in openFragment:
getSupportFragmentManager().beginTransaction().add(R.id_fragment_container,new FavouriteListFragment()).commit();
2- You can define the fragment in your activity xml file like:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/my_fragment"
android:name="com.example.android.something.FavouriteListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.something.FavouriteListFragment"
tools:layout="#android:layout/fragment_layout" />
The first one is called dynamic fragment creation and the second one is called static. You have more freedom with the first one but if your fragment doesn't change throughout the activity it is simpler to use the second one
Since you are using android.support.v4.app.Fragment and there has been a lot of confusion in importing correct version. Try like this:
android.support.v4.app.FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FavouriteListFragment fragment = new FavouriteListFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
Where fragment_container is FrameLayout inside activity_main.
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
Reference
I have been working on a navigation drawer using toolbar and while clicking on the drawer items , respective fragments will be displayed,but here is the problem,when ever I am clicking the drawer items ,fragments with two toolbars are displayed.please help.
fragment.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"
tools:context="archerpenny.impdrawerfragment.BlankFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<!-- TODO: Update blank fragment layout -->
<TextView android:layout_width="match_parent" android:layout_height="match_parent"
android:text="#string/hello_blank_fragment" />
</LinearLayout>
</FrameLayout>
My Activity_main.xml..
`<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/Container"
android:orientation="vertical">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<FrameLayout
android:id="#+id/container_body"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="hi"/>
</FrameLayout>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="#+id/DrawerList"
android:layout_marginTop="?android:attr/actionBarSize"
android:background="#mipmap/menu_bg"
android:layout_gravity="left"/>
</android.support.v4.widget.DrawerLayout>
MainActivity.java....
`
import android.app.Fragment;
import android.app.FragmentManager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
public class MainActivity extends AppCompatActivity {
ActionBarDrawerToggle mDrawerToggle;
RecyclerView.Adapter mAdapter;
RecyclerView recyclerView;
DrawerLayout mDrawerLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new NavigationDrawerAdapter(this);
mDrawerLayout=(DrawerLayout)findViewById(R.id.drawer_layout);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
NavigationDrawerAdapter adapter;
recyclerView = (RecyclerView)findViewById(R.id.DrawerList);
recyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
recyclerView.setLayoutManager(llm);
recyclerView.setAdapter(mAdapter);
getSupportActionBar().setDisplayShowTitleEnabled(false);
mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout,toolbar,R.string.open,R.string.close) {
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(MainActivity.this, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
// do whatever
if(position==0)
{
BlankFragment blankFragment=new BlankFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.Container, blankFragment)
.commit();
}
mDrawerLayout.closeDrawers();
}
})
);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
BlankFragment.java
import android.os.Bundle;
import android.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class BlankFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
// TODO: Rename and change types and number of parameters
public static BlankFragment newInstance(String param1, String param2) {
BlankFragment fragment = new BlankFragment();
Bundle args = new Bundle();
return fragment;
}
public BlankFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
AppCompatActivity activity = (AppCompatActivity) getActivity();
View view=inflater.inflate(R.layout.fragment_blank, container, false);
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
activity.setSupportActionBar(toolbar);
activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Inflate the layout for this fragment
return view;
}
}
Remove the include statement in your fragment
<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"
tools:context="archerpenny.impdrawerfragment.BlankFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- TODO: Update blank fragment layout -->
<TextView android:layout_width="match_parent" android:layout_height="match_parent"
android:text="#string/hello_blank_fragment" />
</LinearLayout>
For those who came here from search for two Toolbars in a fragment.
There is a similar topic: Double Toolbar Is Showing on Fragment.
In AndroidManifest set a theme:
<activity
android:name=".YourActivity"
android:label="#string/title"
android:theme="#style/AppTheme.NoActionBar" />
The theme is:
<style name="AppTheme.NoActionBar" parent="AppTheme">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style>
In YourActivity extend it from AppCompatActivity and add ActionBar, so write:
class YourActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fragment)
setToolbar(toolbar)
showFragment()
// Handle onResume() in fragments, if needed.
supportFragmentManager.addOnBackStackChangedListener {
supportFragmentManager.fragments.lastOrNull()?.onResume()
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// 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.
return when (item.itemId) {
android.R.id.home -> {
onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
}
}
fun setToolbar(toolbar: Toolbar) {
setSupportActionBar(toolbar)
// Show back arrow.
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
// Additional settings, if needed.
toolbar.setBackgroundColor(ContextCompat.getColor(this, R.color.white))
val toolbarTextColor = ContextCompat.getColor(this, R.color.blue)
toolbar.setTitleTextColor(toolbarTextColor)
toolbar.navigationIcon?.setColorFilter(toolbarTextColor, PorterDuff.Mode.SRC_ATOP)
toolbar.overflowIcon?.setColorFilter(toolbarTextColor, PorterDuff.Mode.SRC_ATOP)
}
private fun showFragment() {
if (supportFragmentManager.findFragmentByTag(YourFragment.TAG) == null) {
val fragment = YourFragment.newInstance()
supportFragmentManager.beginTransaction()
.replace(R.id.container, fragment, YourFragment.TAG)
.commit()
}
}
}
This is a layout for YourActivity:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
>
<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="?android:attr/actionBarSize"
app:popupTheme="#style/AppTheme.PopupOverlay"
/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>
Previous attempts (do not repeat).
I made many experiments. Created a new project. Copied all suspecting activities and fragments, styles, colors, strings, dimens, changed AndroidManifest. Set a theme of the activity not from ...NoActionBar style. Removed Toolbar with surrounding <android.support.design.widget.AppBarLayout> tag in activity layout. In onCreate() wrote:
// setSupportActionBar(toolbar) // Crashing string.
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
Then I copied the project to another folder and after compilation it showed one Toolbar. Even if in the source folder I launched File > Invalidate caches and Restart, nothing happened. So, after invalidating caches, Build > Rebuild Project (probably Build > Clean Project) it showed one Toolbar. I even returned back AppBarLayout. I blamed Android Studio.
But on the next day this magic stopped to execute. I compiled the same project and again got two Toolbars. And copying folders, invalidating, deleting /build folders didn't help. So I began to research repository commits in order to catch a solution. It is written in the beginning of the answer.