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)
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'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)
I have an android.support.v4.app.Fragment in an AppCompatActivity.
I added a custom Menu in my fragment. Everything works as expected in Android 5 and 6. But if I try this on Android 4, although I can see the toolbar, when I tap the menu items nothing happens and it does not trigger onOptionsItemSelected
This is my fragment:
public class ProfileDetailFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.profile_detail_fragment, container, false);
Toolbar toolbar = (Toolbar) v.findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_profile, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case android.R.id.home:
getActivity().onBackPressed();
return true;
case R.id.tick:
save();
return true;
default:
return super.onOptionsItemSelected(menuItem);
}
}
public void save(){
Toast.makeText(getContext(), "test", Toast.LENGTH_LONG).show();
}
}
This is my fragment layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="#+id/fragment_master"
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="#android:color/white"
android:clickable="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>
</RelativeLayout>
And this is my menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/tick"
android:title="OK"
app:showAsAction="always"
tools:ignore="AppCompatResource" />
</menu>
Maybe your activity is interfering between the menu and fragment.
There are two solutions:
Inflate and handle menu within your activity and communicate with the fragment
Specify to the fragment for handle the menu: Android - How to access actionbar's menu items in fragment class
*Reviweing your code: make sure you return false inside your onOptionsItemSelected(MenuItem item) Activity's method
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.
I'm having issues getting my action bar to show icons. It shows the text/title I set in the overflow menu (three dots), but no action. Here is my code, what am I missing?
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vehicle_table);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.vehicle_table, new VehicleTable())
.commit();
}
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setCustomView(R.layout.custom_vehicle_action_bar_layout);
}
VehicleTable.java (my fragment)
public class VehicleTable extends Fragment {
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.menu_vehicle_table, menu);
}
menu_vehicle_table.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="com.roadstruck.mobile.VehicleTable">
<item android:id="#+id/add_vehicle"
android:icon="#drawable/ic_add_white_24dp"
android:orderInCategory="100"
android:title="Add"
android:showAsAction="always"
/>
</menu>
custom_vehicle_action_bar_layout (custom textview for centering menu text)
<?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="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="VEHICLES"
android:textColor="#ffffff"
android:id="#+id/mytext"
android:textSize="18sp" />
</LinearLayout>
Try change android:showAsAction="always" to app:showAsAction="always"