Converting view with toolbar from Activity to Fragment - android

I have an AppCompatActivity screen with toolbar, navigation drawer and custom view in content. I want to display a configuration. I shall not use dialog as it will be large and will open dialogs. My friend advised me to rewrite the code to have two fragments and switch between them.
Current code:
public class PuzzleActivity extends AppCompatActivity implements
NavigationView.OnNavigationItemSelectedListener
protected void onCreate(Bundle state) {
setContentView(R.layout.activity_puzzle);
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.drawer_open, R.string.drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
activity_puzzle.xml (reduced)
<android.support.v4.widget.DrawerLayout android:id="#+id/drawer_layout"
android:fitsSystemWindows="true" tools:openDrawer="start">
<include
layout="#layout/app_bar_puzzle"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:fitsSystemWindows="true"
app:menu="#menu/drawer_main" />
app_bar_puzzle.xml (reduced)
<android.support.design.widget.CoordinatorLayout
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="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_puzzle" />
And finally content_puzzle.xml (again reduced, and for simplicity custom view replaced with textView)
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Content"/>
Originally I created a Fragment and replaced android.R.id.content with this fragment: I end up with overlapping fragment and original view:
I had a theory that that was caused by FragmentManager unable to replace activity view defined from XML or incompatibility between Activity view and fragments. So I decided to introduce new Fragment and move all UI to this fragment.
PuzzleFragment.java derived from support library:
public class PuzzleFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_puzzle, container, false);
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(getActivity(), drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
return view;
}
But this fails on a toolbar initialization:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.CharSequence android.support.v7.widget.Toolbar.getTitle()' on a null object reference
at android.support.v7.widget.ToolbarWidgetWrapper.<init>(ToolbarWidgetWrapper.java:98)
at android.support.v7.widget.ToolbarWidgetWrapper.<init>(ToolbarWidgetWrapper.java:91)
at android.support.v7.app.ToolbarActionBar.<init>(ToolbarActionBar.java:73)
at android.support.v7.app.AppCompatDelegateImplV7.setSupportActionBar(AppCompatDelegateImplV7.java:205)
at android.support.v7.app.AppCompatActivity.setSupportActionBar(AppCompatActivity.java:99)
at PuzzleFragment.onCreateView(PuzzleFragment.java:30)
The toolbar is null, findViewById does not find it in the Fragment /inflater.inflate(R.layout.activity_puzzle, container, false)/. But it does if it is in the Activity /setContentView(R.layout.activity_puzzle)/.
How can I make it work?

The trick was to move initialization procedure to later phase as shown in the source code:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(logTag, "onCreateView()");
return inflater.inflate(R.layout.activity_puzzle, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
Log.d(logTag, "onActivityCreated()");
super.onActivityCreated(savedInstanceState);
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(getActivity(), drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) getActivity().findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}

Related

navigation drawer wont start new activity after item click

I'm trying to make a navigation drawer that opens a new activity when the user taps an item.
There is 3 items in my drawer and I want each of them to open a different activity but when i click on item nothing happen.
public class MarkerActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_markers);
getWindow().getDecorView().setBackgroundColor(Color.WHITE);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().hide();
mDrawerLayout = findViewById(R.id.drawer);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar,
R.string.open_drawer, R.string.close_drawer);
mDrawerLayout.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.map_button:
Intent intent = new Intent(MarkerActivity.this, MapActivity.class);
startActivity(intent);
break;
case R.id.comingsoon:
Toast.makeText(this, "Coming soon", Toast.LENGTH_SHORT).show();
break;
case R.id.comingsoon2:
Toast.makeText(this, "Coming soon", Toast.LENGTH_SHORT).show();
break;
}
mDrawerLayout.closeDrawer(GravityCompat.START);
return true;
}
}
My activity_markers.xml
<android.support.v4.widget.DrawerLayout
android:id="#+id/activity_markers"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.NavigationView
android:id="#+id/drawer"
app:headerLayout="#layout/header"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#color/white"
app:menu="#menu/drawermenu"
android:layout_gravity="start">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
drawermenu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/map_button"
android:title="Map"/>
<item android:id="#+id/comingsoon"
android:title="Coming Soon"/>
<item android:id="#+id/comingsoon2"
android:title="Coming Soon"/>
</menu>
You probably put each item individually in the navigation drawer layout.
If so, you need to define these elements in onCreate() method and setOnClickListener for them.
Can you please share the navigation drawer layout xml.
Otherwise, you defined a ListView, but haven't initialised it.
The id of the navigationview and drawer are incorrect
Try this:
mDrawerLayout = findViewById(R.id.activity_markers);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar,
R.string.open_drawer, R.string.close_drawer);
mDrawerLayout.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = findViewById(R.id.drawer);
navigationView.setNavigationItemSelectedListener(this);
I found the answer. You just need to paste this line
navigationView.bringToFront(); after NavigationView navigationView = findViewById(R.id.your_id);

Navigation Drawer Header is not hiding

I tried to create one simple app with Drawer Menu. I created a project with Android Studio and select Navigation Drawer Layout. I'm trying to hide navigation drawer header and put it on toolbar... I found the way to put on toolbar but I can't find hide RED part of header in picture. Can you help me please.
Here is my layout page xml codes
<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_main"
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"
android:layout_marginTop="?attr/actionBarSize" //With this code i put menu under toolbar
app:menu="#menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
Here is my MainActivity.java
public class MainActivity 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);
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.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
FragmentManager fragmentManager = getFragmentManager();
if (id == R.id.nav_first_layout) {
fragmentManager.beginTransaction().replace(R.id.content_frame,new FirstFragment()).commit();
} else if (id == R.id.nav_second_layout) {
fragmentManager.beginTransaction().replace(R.id.content_frame,new SecondFragment()).commit();
} else if (id == R.id.nav_third_layout) {
fragmentManager.beginTransaction().replace(R.id.content_frame,new ThirdFragment()).commit();
} else if (id == R.id.nav_home) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
How can I hide that red part??
Set fitsystemwindow=false under android.support.design.widget.NavigationView in xml.
Use this In your MainActivity if you want to do it programmatically else see the second option below.
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
View header = navigationView.getHeaderView(0);
header.setVisibility(View.GONE);
OR if you not wanna use that and want to accomplish this via xml then check below option.
In your xml file of main activity you should have NavigationView like this
<android.support.design.widget.NavigationView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/navigation_view_I"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="#menu/drawer_menu"
app:headerLayout="#layout/navigation_drawer_header">
Remove last line from the above NavigationView which is this
app:headerLayout="#layout/navigation_drawer_header"
Add below code inside of onCreateView() of NavigationDrawer Fragment class
View headerView= LayoutInflater.from(this).inflate(R.layout.drawer_header, null);
navigationView.addHeaderView(headerView);
navigationView.getHeaderView(0).setVisibility(View.GONE);
Note:- relace R.layout.drawer_header by your header view resource file.

Toggle Inside Fragment

I have made one Activity with a NavigationView (opened with a toggle button):
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
private DrawerLayout drawer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.app_name, R.string.app_name);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
if (navigationView != null) {
navigationView.setNavigationItemSelectedListener(this);
navigationView.setItemIconTintList(null);
navigationView.getMenu().getItem(0).setChecked(true);
}
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer != null) {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
Fragment fragment = null;
Class fragmentClass;
fragmentClass = FirstFragment.class;
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
break;
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.layout, fragment).commit();
item.setChecked(true);
setTitle(item.getTitle());
drawer.closeDrawers();
return true;
}
}
When I select one item of NavigationView it starts a Fragment:
public class FirstFragment extends Fragment {
private View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_layout, container, false);
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) view.findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
getActivity(), drawer, toolbar, R.string.app_name, R.string.app_name);
drawer.addDrawerListener(toggle);
toggle.syncState();
return view;
}
}
Problem:
When I select the button ≡ to open the NavigationView inside Fragment and I select the items it doesn't open FirstFragment.
If I swipe from the left to open NavigationView inside Fragment and I select the items it opens FirstFragment.
How can I reuse onNavigationItemSelected from MyActivity on FirstFragment?
Edit:
This is the acitivity_layout.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"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ddffff"
android:fitsSystemWindows="true">
<LinearLayout
android:id="#+id/list_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
//FragmentLayout
<RelativeLayout
android:id="#+id/layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<include
android:id="#+id/bar"
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
...
</RelativeLayout>
</LinearLayout>
<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:background="#ddffff"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
The root cause of this is that you're using the same layout in your Fragment as you are in the Activity, and the Toolbar is inside the container ViewGroup you transact the Fragment into. Once a Fragment has been loaded with its own DrawerLayout and Toolbar, it covers the Activity's Toolbar, so nothing looks out of the ordinary. However, the toggle in the Fragment is operating the drawer in the Fragment, and that drawer is a second NavigationView that hasn't been setup like the one in the Activity, so nothing happens when you click on the drawer opened with the toggle. But, if you drag the drawer open, the one that's opening is actually the Activity's drawer, and that NavigationView was setup correctly, so clicking on that one works as expected.
The first correction is to move the Toolbar - its <include> element, that is - to outside of the RelativeLayout you're using as the Fragment container. This will prevent the Activity's Toolbar from being obscured when Fragments are loaded.
The second step is to define separate, different layout XML files for the Fragments. You don't want to use the same layout in the Fragments as you are in the Activity, mostly because that's probably not really what you intend, and also because you really don't want to have multiple, redundant DrawerLayouts, Toolbars, and NavigationViews, which can cause problems, as you've seen.

Your content must have a ListView whose id attribute is 'android.R.id.list' im trying to create a listfragment

I'm new in android studio and I'm trying to create a fragment with a list and show it on a drawer class that I use to show all my fragments, I already read a lot of post but I can't find the answer I'm looking for, let me paste you my code so you can check it.
layout code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/lista"
android:layout_gravity="center_horizontal" />
</LinearLayout>
fragment class code:
public class FragmentoPrincipalChofer extends ListFragment {
private List<ParseObject> mViaje;
private ListView mLista;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View x = inflater.inflate(R.layout.fragmento_principal_chofer, container, false);
mLista = (ListView)x.findViewById(R.id.lista);
String[] nombres= new String[2];
nombres[0]="gaston";
nombres[1]="gaston";
ArrayAdapter<String> adaptador = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, nombres);
mLista.setAdapter(adaptador);
return x;
}
drawer class code:
public class DrawerPrincipal extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener,FragmentoPrincipalUsuario.OnFragmentInteractionListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawer_principal);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//cargar fragment principal usuario
FragmentoPrincipalChofer fragmento=(FragmentoPrincipalChofer) getSupportFragmentManager().findFragmentByTag("fragmento");
if (fragmento==null){
fragmento=new FragmentoPrincipalChofer();
android.support.v4.app.FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(android.R.id.content,fragmento,"fragmento");
transaction.commit();
}
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.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
You're using a ListFragment so...
ListFragment has a default layout that consists of a single list view. However, if you desire, you can customize the fragment layout by returning your own view hierarchy from onCreateView(LayoutInflater, ViewGroup, Bundle). To do this, your view hierarchy must contain a ListView object with the id "#android:id/list" (or list if it's in code)
Change the ListView XML to the following
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#android:id/list"
android:layout_gravity="center_horizontal" />
And your reference to it as such
mLista = (ListView)x.findViewById(android.R.id.list);

hamburger doesn't toggle if drawer is not opened previously

i have a v7 Toolbar inside an AppBarLayout and when i try to toggle it from the hamburger icon it does not toggle the drawer unless i open it swiping it, after this the hamburguer works properly.
The code below contains the Layout content and the toolbar related code inside onCreate:
<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=".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="#color/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
also i've tried to make it work adding a NavigationOnClickListener by myself and, although it prints the Log it does not open the drawer (i've tried it with and without the syncState() call):
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "OPEN");
toggle.syncState();
drawer.openDrawer(GravityCompat.START);
}
});
Check these codes and if you haven't include them yet, try them:
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
toggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
toggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (toggle.onOptionsItemSelected(item)) {
return true;
}
...
}
Other than onCreate, these codes are also needed per the official reference.

Categories

Resources