I have read a lot of similar topics but none of the solutions works to me. I'm getting the MenuItem normaly, but when i try to get its view, I get a null view. I already tried put the code in the onPrepareOptionsMenu, get the view with MenuItemCompat, and other sutff.
activity_main.xml, where is the toolbar
<?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"
...
tools:context=".activities.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:elevation="4dp"/>
</android.support.design.widget.AppBarLayout>
...
</android.support.design.widget.CoordinatorLayout>
menu_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".activities.MainActivity">
<item
android:id="#+id/action_location"
android:orderInCategory="0"
android:icon="#android:drawable/ic_dialog_map"
android:title="Localização"
app:showAsAction="ifRoom" />
...
</menu>
onCreate method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
...
}
onCreateOptionsMenu method
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem menuItem = menu.findItem(R.id.action_location); // here is fine, found the item
View view = menuItem.getActionView(); // here is null
return super.onCreateOptionsMenu(menu);
}
Familiarize yourself with what a ActionView really is.
Just by assigning menuItem, you receive all the attributes about it, including the title, "Localização."
If you're trying to get the result of click "action_location," then onOptionsItemSelected may be the method call you need.
Related
I don't understand why in this case is not recongnizing my menu item.
I have another activities with similar code and it's working fine, but in this case i'm having NPE.
Layouts
General (activity_completas)
<?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=".activities.CompletasActivity">
<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_breviario_general" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
content_breviario_general
<?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"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<include
android:id="#+id/include"
layout="#layout/tv_zoomable" />
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintBottom_toTopOf="#+id/include"
app:layout_constraintEnd_toStartOf="#+id/include"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
Menu
<?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=".activities.BreviarioActivity">
<item
android:id="#+id/item_voz"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="#drawable/ic_play"
android:visible="false"
android:title="#string/leer"
app:showAsAction="ifRoom" />
<item
android:id="#+id/item_calendario"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="#drawable/ic_calendar_toolbar"
android:title="#string/all_calendar"
app:showAsAction="ifRoom" />
</menu>
Java code
Relevant parts only for this case:
public class CompletasActivity extends AppCompatActivity {
//...
private Menu menu;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_completas);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
showData();
}
private void showData() {
sbReader = new StringBuilder();
//I fill sbReader correctly
if (sbReader.length()>0) {
menu.findItem(R.id.item_voz).setVisible(true); //******NPE here*******
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
getMenuInflater().inflate(R.menu.toolbar_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (tts != null) {
tts.cerrar();
}
NavUtils.navigateUpFromSameTask(this);
return true;
case R.id.item_voz:
String html = String.valueOf(Utils.fromHtml(sbReader.toString()));
String[] textParts = html.split(SEPARADOR);
tts = new TTS(getApplicationContext(), textParts);
return true;
case R.id.item_calendario:
Intent i = new Intent(this, CalendarioActivity.class);
startActivity(i);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
super.onBackPressed();
if (tts != null) {
tts.cerrar();
}
}
}
Error
java.lang.NullPointerException: Attempt to invoke interface method
'android.view.MenuItem android.view.Menu.findItem(int)' on a null
object reference
I do the same thing in another activities and i don't have NEP. What's happening here?
You are getting null point exception because your menu isn't instantiated. As i can see, your are calling showData before creating the menu. Call showData in the onCreateMenu. This should solve your problem.
I must have read almost all the question and answers related to this, but still cannot get it to work. Below is the rough sketch of how the app looks.
Adding code below to give structure of the layout and where I might be doing wrong.
activity_main.xml
<android.support.constraint.ConstraintLayout >
<android.support.design.widget.BottomNavigationView>
</android.support.design.widget.BottomNavigationView>
<FrameLayout>
</FrameLayout>
bottom_nav_fragment.xml
<android.support.design.widget.CoordinatorLayout >
<android.support.design.widget.AppBarLayout
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar>
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/liquor_type_tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:tabMode="scrollable">
<android.support.design.widget.TabItem
/>
<android.support.design.widget.TabItem
/>
<android.support.design.widget.TabItem
/>
<android.support.design.widget.TabItem
/>
<android.support.design.widget.TabItem
/>
</android.support.design.widget.TabLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/price_list_viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
For each of tab item, I have used a common fragment which will have different data in recyclerView.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.nandu.oru10ml.price_list.CommonPriceFragment">
<android.support.v7.widget.RecyclerView >
</android.support.v7.widget.RecyclerView>
MainActivity.java
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// MenuInflater inflater = getS
Log.d("Activity Options", "inside onCreateOptionsMenu ");
getMenuInflater().inflate(R.menu.search_item, menu);
return true;
}
BottomNavFragment.java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("Fragment onCreate", "inside onCreate ");
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Log.d("Fragment Options", "inside onCreateOptionsMenu ");
inflater.inflate(R.menu.search_item, menu);
super.onCreateOptionsMenu(menu,inflater);
}
CommonFragment.java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("Fragment onCreate", "inside onCreate ");
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Log.d("Fragment Options", "inside onCreateOptionsMenu ");
inflater.inflate(R.menu.search_item, menu);
super.onCreateOptionsMenu(menu,inflater);
}
and finally, search_item.xml
<?xml version="1.0" encoding="utf-8"?>
<item
android:id="#+id/action_search"
android:title="Search for Brand"
android:icon="#drawable/ic_search_black_24dp"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView">
</item>
</menu>
The reason why it is not working would also help me understand the root cause.
This SearhView is applicable to 2 of the bottom nav Fragment and all of the nested Fragments inside, to search Recyclerview present in each of it.
setSupportActionBar should take the argument as a toolbar. So what you should do is, inside your fragment call
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar)
I have an activity which contains a custom toolbar and a simple listview. I want the toolbar respond when the listview is scrolled. However, it is not working.
Here is the .xml file
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.abdralabs.talksee.HistoryActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/history_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/history_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/title"
app:layout_scrollFlags="scroll|enterAlways">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/lv_history"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</ListView>
Here is the .java file
public class HistoryActivity extends AppCompatActivity {
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
toolbar = (Toolbar)findViewById(R.id.history_toolbar);
/*
setSupportActionBar(toolbar);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
*/
toolbar.setTitle("History");
String[] rcArray = {"A","B","C","D","A","B","C","D","A","B","C","D","A","B","C","D","A","B","C","D","A","B","C","D","A","B","C","D"};
ArrayAdapter adapter = new ArrayAdapter<String>(this,
R.layout.list_history, rcArray);
ListView listView = (ListView) findViewById(R.id.lv_history);
listView.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
/*
switch (item.getItemId()){
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
break;
}
*/
return super.onOptionsItemSelected(item);
}
}
What have I done wrong?
EDIT:
In response to rafsanahmad007's answer
I have applied the changes as per your suggestion but still there is no change.
When I scroll through the ListView there is no change to the size of the ToolBar. However, when I click on the ToolBar itself and make an up & down motion the ToolBar moves up & down too. What I want to achieve is, when I scroll the ListView downwards the ToolBar should collapse and when I scroll the ListView upwards the ToolBar should get to its normal size/position.
The following pictures depict how the ToolBar is responding currently.
As you can see in the above pics, the ListView is not being scrolled, but the ToolBar itself is being scrolled. What I want is, when I scroll the ListView the ToolBar should scroll only during that time. I hope I have clarified myself.
try this:
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:minHeight="80dp"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed" />
</android.support.design.widget.AppBarLayout>
you can also get Help from Here
I'm using PreferenceFragment that I launch from the NavigationDrawer. In the preferenceFragment I show the toolbar. All looks good, but when I press the arrow in the toolbar to come back it doesn't work. I can see in the log this:
D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
But don't do nothing. The only way to come back is press button back in the device
Some help will be appreciated.
This is my code:
PreferenceFragment:
public class AnPreferenceActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pref_with_actionbar);
getFragmentManager().beginTransaction()
.replace(R.id.content_frame, new SettingsPreference())
.commit();
}
public static class SettingsPreference extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
}
}
}
Layout xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:navigationContentDescription="#string/abc_action_bar_up_description"
app:navigationIcon="?attr/homeAsUpIndicator"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:title="#string/action_settings" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/appbar" />
</RelativeLayout>
In onCreate() of your fragment first you should declare it has option Menu:
setHasOptionsMenu(true);
Then you should handle your own menu:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// close fragment here
getActivity().getFragmentManager().popBackStack();
return true;
default:
break;
}
return false;
}
If you need more Menu create new menu item:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.fragment_menu, menu);
return true;
}
Accessing to toolbar from fragment is not good approach you should handle it in better way. There are lots of thread about this issue out there. (in fact Activity should handle Toolbar behaviour)
Since I use an action bar instead of menus for my application, no action bar nor/ menus are shown in my implementation of AccountAuthenticatorActivity. Other activities show action bar without problem.
I'm not sure if it's a bug or a missing adaptation of the code on my side. Has someone experienced the same problem? I didn't find any other question related to this problem.
public class MyAuthenticatorActivity extends AccountAuthenticatorActivity {
...
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
final MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
XML menu that should be right as it is used in many other activities:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/menuHome"
android:icon="#drawable/ic_menu_home"
android:orderInCategory="110"
android:showAsAction="ifRoom"
android:title="#string/menu_home"/>
<item
android:id="#+id/menuSettings"
android:icon="#drawable/ic_menu_settings"
android:orderInCategory="111"
android:showAsAction="ifRoom"
android:title="#string/menu_settings"/>
<item
android:id="#+id/menuInfo"
android:icon="#drawable/ic_menu_info"
android:orderInCategory="113"
android:showAsAction="ifRoom"
android:title="#string/menu_info"/>
</menu>
I know my answer is late. But I was able to get around this base on this one. It seems the AccountAuthenticatorActivity doesn't really have an ActionBar for some reason. Esp. it is really hard to work on when you want to use the support-library.
Here is how I did it:
You have to enclose your activity layout using a CoordinatorLayout:
<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/coordinatorlayout_homescreen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background_login"
tools:context="com....LoginActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsingtoolbarlayout_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/actionBarSize"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="64dp"
app:expandedTitleMarginEnd="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
...
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
As you can see, I placed an AppBarLayout as per the docs and have the appcompat version of the Toolbar here. We will assign this Toolbar later.
If you prefer to make the CoordinatorLayout just like any ordinary activity without animated-coordinated scroll, you can just set the attribute of CollapsingToolbarLayout like the following:
android:minHeight="?android:attr/actionBarSize"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
This will make sure your Toolbar will not disappear/collapse when you scroll up as the minHeight has been set to ?android:attr/actionBarSize. You can checkout its behavior here.
Next on your LoginActivity which extends AccountAuthenticatorActivity, you have to use AppCompatDelegate but before that make sure you LoginActivity implements the AppCompatCallback:
public class LoginActivity extends AccountAuthenticatorActivity
implements AppCompatCallback
{
...
private AppCompatDelegate mAppCompatDelegate;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
...
mAppCompatDelegate = AppCompatDelegate.create(this, this);
mAppCompatDelegate.setSupportActionBar(mToolbarLogin);
ActionBar actionBar = mAppCompatDelegate.getSupportActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(getString(R.string.activity_login));
mCollapsingToolbarLayoutLogin.setTitleEnabled(false);
}
There are three methods you have to implement, but on my research they seem to do nothing fancy esp if you only want to show an ActionBar, so on this use-case you can leave them blank:
#Override
public void onSupportActionModeStarted(ActionMode mode)
{
}
#Override
public void onSupportActionModeFinished(ActionMode mode)
{
}
#Nullable
#Override
public ActionMode onWindowStartingSupportActionMode(ActionMode.Callback callback)
{
return null;
}
The line mAppCompatDelegate = AppCompatDelegate.create(this, this); ask for the Activity instance on the first param, the second param is asking for the callback.
Also, another thing. If you want the back button to be present as shown on this code, it doesn't respond to click. You may have to override it:
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case android.R.id.home:
onBackPressed();
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
One small quirk I found going using this is that the status bar appeared white on some devices. I am still looking how to fix it but at least the AccountAuthenticatorActivity now has an ActionBar. I don't like this solution as it is a little bit hacky to may taste. So much hassle to implement a seemingly basic behavior for Activity.
HTH