I am trying to move an old app over to the new Material design guidelines. I used the Navigation Drawer Template previously to create the Main Activity. However I am having some massive problems trying to implement the Toolbar to the main Activity. I am continuously getting NullPointer Exceptions.
I am creating a toolbar xml file like this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/blue" >
</android.support.v7.widget.Toolbar>
After that I am trying to add it to my main layout using the include command:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.medinfo.main.MainActivity" >
<include layout="#layout/toolbar_database_edit" />
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<fragment
android:id="#+id/navigation_drawer"
android:name="com.medinfo.fragments.NavigationDrawerFragment"
android:layout_width="#dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
tools:layout="#layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
In my activity_main I am doing the following:
The NPE is occuring when I call setSupportActionBar or when the Setup NavDrawer is called.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.layout.toolbar_database_edit);
setSupportActionBar(toolbar);
mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout));
}
I tried wrapping the DrawerLayout in a linear-layout, what that did was create the toolbar behind the container that contains my fragments, when I started the activity I saw the toolbar rendered in the background then hidden once the Container and fragments were loaded. It did however remove the NPE. I also tried creating the toolbar within the layout instead of using a separate toolbar XML file. I still got the same NPE error.
While I am asking about the new Material Design Stuff, I would also like to know if there is a way to get my EditText Widgets and Spinner Widgets to use the old Holo Theme/Style.
I am really hoping there is a simple way to revert to those styles.
Thank you for the help everyone
1) First, your layout is incorrect. DrawerLayout accepts two children: layout container and drawer layout itself.
Simplified,
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<include layout="#layout/activity" />
<include layout="#layout/drawer" />
</android.support.v4.widget.DrawerLayout>
Second, you incorrectly findViewById your toolbar.
Toolbar toolbar = (Toolbar) findViewById(R.layout.toolbar_database_edit);
Here you're referencing to layout, but should reference to id.
Given the layout resource above, we have activity.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/blue"
android:foreground="?android:attr/windowContentOverlay"
app:theme="#style/Toolbar"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
. . . contents of activity layout
</FrameLayout>
</LinearLayout>
In code:
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
2) To use old Holo style, you should use Holo theme as parent of your app theme in styles.xml. But users would expect native theme on each Android version, so it's a bad practice.
Related
Trying to create items on a toolbar but they are not showing up. I have posted all my necessary code below. My toolbar shows correctly, however my items do not show and I do not know why. Any help would be appreciated
Main_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="#+id/left"
android:title="#string/app_name"
android:icon="#drawable/ic_left"
app:showAsAction="always"/>
<item
android:id="#+id/right"
android:title="#string/app_name"
android:icon="#drawable/ic_right"
app:showAsAction="ifRoom"/>
</menu>
App_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/readerBar"
android:background="#color/colorPrimaryDark"
app:title="#string/app_name"
android:theme="#style/ThemeOverlay.AppCompat.Dark">
</androidx.appcompat.widget.Toolbar>
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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<include
layout="#layout/app_bar"
android:id="#+id/include" android:layout_height="wrap_content" android:layout_width="match_parent"/>
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.readerBar);
setSupportActionBar(toolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
This is the result I get:
Your code + menu setup looks good, I think the menu items aren't showing up because this part: setSupportActionBar(toolbar); fails (toolbar == null); because it's inside a layout include with ID.
When you remove android:id="#+id/include" the toolbar should get setup correctly and show the items.
Appbar has limitations set by google that make it difficult to work.
So I have another suggestion for you,
You can replace your Appbar with a RelativeLayout or any parent layout you want.
It's better because you can customize it any way you want.
For example, you can add your Icon by imageView and then ser listener for them and control them.
And if you want your parent height is the same with Appbar set your layout height like this.
android:layout_height="?android:attr/actionBarSize"
I'm using the layout below, The CoordinatorLayout holds inside it AppBarLayout (With Toolbar) and the fragment layout.
I'm using app:layout_scrollFlags in my Toolbar and app:layout_behavior="#string/appbar_scrolling_view_behavior" in the fragment, so the Toolbar appear and disappear (hide/show) with scrolling my fragment content.
My problem: when I scroll in fragment A and therefore the toolbar disappear, then I use the BottomNavigationView to go to fragment B the toolbar remains hidden.
I want the toolbar to appear every time I open new fragment.
<?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/containerMain"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/AppBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_gravity="top"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="#+id/nav_host_fragment"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
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:navGraph="#navigation/mobile_navigation" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="0dp"
android:layout_height="#dimen/nav_bar"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:itemIconTint="#drawable/bottom_color_nav"
app:itemTextColor="#drawable/bottom_color_nav"
app:layout_constraintBottom_toBottomOf="#id/main_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
I would assume that the xml you posted is your layout for your MainActivity(), if so create a reference to your Toolbar in your MainActivty and create a function in your MainActivty() to access/change your Toolbar collapse states.
In your Fragments, create a reference to your MainActivity to then access the function to change the state of your Toolbar.
I cannot test as from work, but I have used same code flow to do the same stuff when using only MainActivity with Inner Fragments as the navigation flow of the app.
Below not exact working or tested code, but same idea/flow
//my fragment function to access MainActivity().changeToolbarState(boolean)
changeToolbar(state: boolean) {
if(state){
//true
//show toolbar
MainActivty().changeToolbarState(true)
}else{
//false
//collapse/hidetoolbar
MainActivty().changeToolbarState(false)
}
}
The best alternative could be enabling setExpanded property of app bar layout to true with the following code inside the fragment. Here, MainActivity.appBarLayout is the static variable defined in Main Activity referenced to App Bar Layout.
#Override
public void onPause() {
super.onPause();
MainActivity.appBarLayout.setExpanded(true);
}
I have been having trouble with my action bars, I got it set up on my xml front end like this:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:label="#string/dadosCadastrais"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme" />
And on the Java activity:
Toolbar toolbar = findViewById(R.id.toolbar4);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
I have already tried changing the theme the app uses, the theme the layout uses and even the activities theme to allow/forbid a toolbar to show up. Even though my java class extends AppCompatActivity it does not show!
PS: Got it working now! The problem was the setup on java code itself, there was an hidden method which was overwritting my setup, thx for the help!
Make sure your activity inflates the correct layout containing your ToolBar.
protected void setContentView() {
setContentView(R.layout.your_activity_layout);
}
Your activity layout should contain your ToolBar. Here is a code example:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar" />
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
</LinearLayout>
I have the following layout, activity_main.xml:
<merge
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">
<com.lorentzos.flingswipe.SwipeFlingAdapterView
android:id="#+id/frame"
android:background="#d1d1d1"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rotation_degrees="15.5"
tools:context=".MainActivity"
android:layout_gravity="top"/>
<TextView
android:id="#+id/tv_noJobsLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="#474747"
android:textAlignment="center"
tools:text="Nothing Left to Swipe!"
android:layout_gravity="center" />
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include layout="#layout/buttons" />
</merge>
In my main activity, I have the following code for injection using ButterKnife:
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
I want to remove the <include> part of the layout because I do not need those buttons anymore, however, when I remove the <include> line I get the following error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.lorentzos.swipecards.example/com.lorentzos.swipecards.MainActivity}: java.lang.RuntimeException: Unable to inject views for com.lorentzos.swipecards.MainActivity#f356341
What am I doing wrong?
Is there some reason why I cannot remove the <include>?
EDIT:
#InjectView(R.id.frame) SwipeFlingAdapterView flingContainer;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Remove title bar
//this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//color the notification bar with our company colors
Window window = this.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(this.getResources().getColor(R.color.laborswipe_notificationbar));
//remove title from action bar and add the logo to the top left of the action bar
setUpActionBar();
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
After removing your <include layout=.../> also remove the binded view from the layout in your activity.
Notes:
Binding views with ButterKnife means that you have views in a layout with the binding codes in your main activity. So there should be a code with:
#BindView(R.id.your_view_in_include_button) View yourViewName;
Remove this according with the view in your 'include layout.
Then rebuild your app.
Suggestion:
Upgrade your ButterKnife to current version.
I am trying to add a navigation drawer to an activity which will contain one or two fragments. I would like this activity to have a navigation drawer associated with it regardless of how many fragments are displayed. To do this i figured I'd need two xml files, one for the activity and one for the fragment. This seems to work except for the fact that the when the navigation drawer is opened, it is "under" the normal content view. Am I doing something wrong? or is there a way to increase the z index of the drawer?
Here is my onCreate() in the activity,
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm_list);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(android.R.id.content, new AlarmListFragment());
fragmentTransaction.commit();
}
and here are my xml layouts:
Activity:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/alarm_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
<ListView android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
Fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
I'd appricate any suggestions on how to go about this! Thanks!
I wonder how the code is working for you. The above code should not work. You put the fragment at android.R.id.content. But I don't see that inside the DrawerLayout your Activity XML. Furthermore, the Drawer Layout should only have a FrameLayout (with id 'content' in your case) and a ListView as mentioned here. So you need to have add a FrameLayout as below in your Activity XML for which you are implementing the navigation drawer.
<FrameLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Also you will have to move the xml into another fragment which you can load when the activity starts or when desired.