add a custom dropdown spinner to action item/overflow in Actionbar sherlock - android

I want get the effects like this picture. I am using Action bar Sherlock for backward compatibility.
I am use NAVIGATION_MODE_TABS mode in action bar. I follow this blog to achieve below screen. My code is here.
HomeActivity extends SherlockFragmentActivity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// actionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
setTitle(R.string.app_name);
mViewPager = (ViewPager) findViewById(R.id.pager);
// Add the tabs
mTabsAdapter = new TabsAdapter(this, actionBar, mViewPager);
mTabsAdapter.addTab(actionBar.newTab().setText("General"),
GeneralFragment.class, null);
mTabsAdapter.addTab(actionBar.newTab().setText("Memory"),
MemoryFragment.class, null);
// more tabs here; seems no need those
if (savedInstanceState != null) {
actionBar.setSelectedNavigationItem(savedInstanceState
.getInt("tab"));
}
int titleId = Resources.getSystem().getIdentifier("action_bar_title",
"id", "android");
// If you're using sherlock, in older versions of android you are not
// supposed to get a reference to android.R.id.action_bar_title, So
// here's little hack for that.
if (titleId == 0) {
titleId = com.actionbarsherlock.R.id.abs__action_bar_title;
}
View titleView = findViewById(titleId);
// attach listener to this spinnerView for handling spinner selection
// change
spinnerView = (Spinner) getLayoutInflater().inflate(
R.layout.spinner_layout, null);
//
// source of ViewGroupUtils class is given at the end of this post.
ViewGroupUtils.replaceView(titleView, spinnerView);
}
I manage to build this .
How i build my desired screen in ActionbarSherlock? Any link or suggestion will be greatly appreciated .
Edited: My ViewGroupUtils class
`public class ViewGroupUtils {
public static ViewGroup getParent(View view) {
return (ViewGroup) view.getParent();
}
public static void removeView(View view) {
ViewGroup parent = getParent(view);
if (parent != null) {
parent.removeView(view);
}
}
public static void replaceView(View currentView, View newView) {
ViewGroup parent = getParent(currentView);
if (parent == null) {
return;
}
final int index = parent.indexOfChild(currentView);
removeView(currentView);
removeView(newView);
parent.addView(newView, index);
}
}
`

Just change your menu XML with this
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_share"
android:icon="#android:drawable/ic_menu_share"
android:orderInCategory="100"
android:showAsAction="ifRoom"
android:title="Share"/>
<item
android:id="#+id/action_search"
android:icon="#android:drawable/ic_menu_search"
android:orderInCategory="100"
android:showAsAction="ifRoom"
android:title="Search"/>
<item
android:id="#+id/more"
android:orderInCategory="100"
android:icon="#android:drawable/ic_menu_more"
android:showAsAction="always"
android:title="">
<menu>
<item
android:id="#+id/action_call"
android:icon="#android:drawable/ic_menu_call"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Call"/>
<item
android:id="#+id/action_camera"
android:icon="#android:drawable/ic_menu_camera"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Camera"/>
<item
android:id="#+id/action_compass"
android:icon="#android:drawable/ic_menu_compass"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Compass"/>
<item
android:id="#+id/action_help"
android:icon="#android:drawable/ic_menu_help"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Help"/>
</menu>
</item>
No need to change in your Java file.
Output is....

Related

Hiding/Showing Navigation Elements From A Fragment

I am looking to hide the "Profile" MenuItem from the apps navigation bar when the user is not loggedIn. When the user finally does log in i want to do two things:
Hide the "Login" button
Show the "Profile" button
This should be straightforward, although I'm not sure on how I can access these Menu Item's in which I wish to close and when I try to, I keep getting NullPointerExceptions.
I cant just select elements by id normally like I have tried MenuItem profileBtn= view.findViewById(R.id.nav_profile);
profileBtn.setVisible(true); as it throws a NullPointerException:
java.lang.NullPointerException: Attempt to invoke interface method 'android.view.MenuItem android.view.MenuItem.setVisible(boolean)' on a null object reference
Here is the loginScreen.java fragment from where I look to show the profile button and hide the login button in the "onClick" method at the bottom.
public class loginScreen extends Fragment implements View.OnClickListener{
private loginScreenText loginScreenText;
EditText email;
EditText password;
NavigationView navigationView;
Button button;
SimpleAccountManager accountManager;
Context mContext;
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
mContext = getActivity().getApplicationContext();
accountManager = new SimpleAccountManager(mContext);
button = (Button) inflater.inflate(R.layout.login_page, container, false).findViewById(R.id.loginBtn);
loginScreenText =
ViewModelProviders.of(this).get(loginScreenText.class);
View root = inflater.inflate(R.layout.login_page, container, false);
final TextView textView = root.findViewById(R.id.text_share);
button = root.findViewById(R.id.loginBtn);
email = root.findViewById(R.id.email);
navigationView = root.findViewById(R.id.nav_view);
password = root.findViewById(R.id.password);
button.setOnClickListener(this);
return root;
}
public void onClick(View view){
if(view == button){
User user;
if(accountManager.getUserByEmail(email.getText().toString()) != null){
user = accountManager.getUserByEmail(email.getText().toString());
/* Attempt to reference the profile button which results in NullPointerException as shown
above*/
MenuItem profileBtn= view.findViewById(R.id.nav_profile);
profileBtn.setVisible(true);
Fragment profile = new profileScreen(mContext);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(((ViewGroup)(getView().getParent())).getId(), profile);
fragmentTransaction.commit();
//kill current fragment
getFragmentManager().beginTransaction()
.remove(loginScreen.this).commit();
accountManager.login(user, password.getText().toString());
} else{
loginScreenText.setmText("No user found with email: " + email.getText().toString());
}
}
}
}
Here are the Menu Items in activity_main_drawer.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view"
android:id="#+id/navMenu">
<group android:checkableBehavior="single" >
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_menu_camera"
android:title="#string/menu_home" />
<item
android:id="#+id/nav_profile"
android:icon="#drawable/ic_menu_gallery"
android:title="Profile"
android:visible="false"/>
<item
android:id="#+id/nav_polls"
android:icon="#drawable/ic_menu_slideshow"
android:title="View Polls" />
<item
android:id="#+id/nav_patients"
android:icon="#drawable/ic_menu_manage"
android:title="View Patients" />
</group>
<item android:title="Log In!">
<menu>
<item
android:id="#+id/nav_login"
android:icon="#drawable/ic_menu_share"
android:title="Login" />
<item
android:id="#+id/nav_login_sp"
android:icon="#drawable/ic_menu_share"
android:title="Login as SP" />
</menu>
</item>
</menu>
Thanks in advance to anyone with advice on how to tackle this problem!
Instead of getting the menu item directly with findViewById you need to get the navigation view first, then get its menu and then get the item from there.
In other words:
NavigationView navigationView = findViewById(R.id.navigation_view); //use the proper id
Menu menu = navigationView.getMenu();
MenuItem menuItem = menu.findItem(R.id.nav_profile);

How to add dividers between specific menu items?

Background
I have a menu item in the action bar (toolbar actually) that when clicked, shows a list of items to choose from, similar to radio-buttons:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:icon="#drawable/..."
android:title="#string/..."
app:showAsAction="always">
<menu>
<group
android:id="#+id/..."
android:checkableBehavior="single">
<item .../>
<item .../>
<item .../>
</group>
</menu>
</item>
</menu>
I need to put an item below this list of items, that will have a divider between it and the list. Similar to what the material design guidelines show (taken from here) :
EDIT: here's a sketch of what I want to do:
The problem
I can't find a way to do it.
What I've tried
The only possible solutions I've found are:
change the theme of the activity (here), but this will also affect other menu items of the activity
methods to put a divider between menu items when they appear on the action bar, but here they do not appear on the toolbar itself. They appear on a popup menu of a selected item.
I tried to put fake items between the list and the extra item, and I also tried to put a group, an empty group and even tried various attributes.
Sadly nothing worked.
The question
How can I add a divider between specific items of an action-item's popup menu ?
Perhaps I need to create a custom popup menu when clicking on the action item (like here) ? If so, how do I put a divider between specific items there ?
Maybe use a Spinner as an action item?
You should use action layout
<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=".LandingActivity">
<item
android:id="#+id/action_cart"
android:title="cart"
android:actionLayout="#layout/cart_update_count"
android:icon="#drawable/shape_notification"
app:showAsAction="always"/>
</menu>
and then the action layout can have the textview with divider.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/divider"/>
<TextView
android:id="#android:id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:textAppearance="?attr/textAppearanceListItemSmall"/>
</LinearLayout>
then you can add the click listener in code
As of SDK version 28, you can use menu.setGroupDividerEnabled(boolean). If you're using ContextMenu this is only supported on SDK 28+, but MenuCompat offers backwards compatibility when used in onCreateOptionsMenu().
This will add a divider between the actions for each different groupId, shown as 0 and 1 below:
menu.add(0, getAdapterPosition(), action1, R.string.action1);
menu.add(1, getAdapterPosition(), action2, R.string.action2);
menu.setGroupDividerEnabled(true);
// Or for MenuCompat < SDK 28:
MenuCompat.setGroupDividerEnabled(menu, true);
Documentation here: https://developer.android.com/reference/android/view/Menu#setGroupDividerEnabled(boolean)
EDIT: Sample code as requested by asker:
Here's the code I am currently using in my app, located in a RecyclerView Adapter. It should work with your menu implementation as well. Since you're defining the menu by XML, the below will also work for you as long as you reference the menu resource. Here's what the result looks like:
Override onCreateContextMenu or your menu's relevant onCreate.. method like so within the:
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.setHeaderTitle(getStr(R.string.actions_title));
// Groups 0 and 1, first parameter for menu.add()
menu.add(0, getAdapterPosition(), 0, R.string.homescreen);
menu.add(0, getAdapterPosition(), 1, R.string.lockscreen);
menu.add(0, getAdapterPosition(), 2, R.string.wpLocation_both);
menu.add(1, getAdapterPosition(), 3, R.string.action_download);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
menu.setGroupDividerEnabled(true); // This adds the divider between groups 0 and 1, but only supported on Android 9.0 and up.
}
}
OK, I've found a nice workaround, but I'm not sure the styling should be this way. That's what I'm missing:
background of items is on top of the background of the popup of the spinner, and I'm not sure if that's the correct way to put it.
I used the white background of the support library for the popup of the spinner. I think there should be a better way to make it white.
I need to know what is the correct style of the divider. for now I used a simple one
Action bar item style is missing. I just used a simple ImageView, and I think it should be different.
For some reason, on some Android versions (maybe Lollipop and below) the background of the items look black instead of white.
The spinner might sometimes have issues with setOnItemSelectedListener , not sure when.
MainActivity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
final MenuItem item = menu.findItem(R.id.action_settings);
final Spinner spinner = ((Spinner) MenuItemCompat.getActionView(item));
SimpleImageArrayAdapter adapter = new SimpleImageArrayAdapter(this);
spinner.setAdapter(adapter);
return true;
}
public class SimpleImageArrayAdapter extends ArrayAdapter<String> {
private final String[] items = {"item 1", "item 2", "item 3", "extra item"};
public SimpleImageArrayAdapter(Context context) {
super(context, 0);
}
#Override
public int getCount() {
return items.length;
}
#Override
public String getItem(final int position) {
return items[position];
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View rootView = convertView == null ? LayoutInflater.from(getContext()).inflate(R.layout.spinner_item, parent, false) : convertView;
TextView tv = (TextView) rootView.findViewById(android.R.id.text1);
tv.setTextColor(0xff000000);
tv.setText(items[position]);
boolean isLastItem = position == getCount() - 1;
rootView.findViewById(R.id.action_divider).setVisibility(isLastItem ? View.VISIBLE : View.GONE);
rootView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
return rootView;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//this is the view that's shown for the spinner when it's closed
ImageView iv = new ImageView(getContext());
iv.setImageResource(android.R.drawable.ic_menu_add);
int viewSize = getDimensionFromAttribute(MainActivity.this, android.support.v7.appcompat.R.attr.actionBarSize);
iv.setLayoutParams(new ViewGroup.LayoutParams(viewSize, viewSize));
iv.setScaleType(ScaleType.CENTER_INSIDE);
iv.setBackgroundResource(getResIdFromAttribute(MainActivity.this, R.attr.selectableItemBackground));
return iv;
}
}
public static int getResIdFromAttribute(final Activity activity, final int attr) {
if (attr == 0)
return 0;
final TypedValue typedValue = new TypedValue();
activity.getTheme().resolveAttribute(attr, typedValue, true);
return typedValue.resourceId;
}
public static int getDimensionFromAttribute(final Context context, final int attr) {
final TypedValue typedValue = new TypedValue();
if (context.getTheme().resolveAttribute(attr, typedValue, true))
return TypedValue.complexToDimensionPixelSize(typedValue.data, context.getResources().getDisplayMetrics());
return 0;
}
res/menu/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="com.example.user.myapplication.MainActivity">
<item
android:id="#+id/action_settings"
android:actionLayout="#layout/spinner"
android:title=""
app:actionLayout="#layout/spinner"
app:showAsAction="always"
/>
</menu>
res/layout/spinner_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/action_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/divider"/>
<TextView
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="?attr/listPreferredItemHeightSmall"
android:paddingEnd="?attr/listPreferredItemPaddingRight"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
android:paddingRight="?attr/listPreferredItemPaddingRight"
android:paddingStart="?attr/listPreferredItemPaddingLeft"
android:textAppearance="?attr/textAppearanceListItemSmall"/>
</LinearLayout>
res/layout/spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<Spinner
android:id="#+id/spinner"
style="#style/SpinnerWithoutArrow"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
res/values/styles.xml
<style name="SpinnerWithoutArrow" parent="#style/Widget.AppCompat.Spinner">
<item name="android:background">#null</item>
<item name="android:popupBackground">#drawable/abc_popup_background_mtrl_mult</item>
</style>
res/drawable/divider.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:height="1dp"/>
<solid android:color="#FFff0000" />
</shape>
This can be done by using popup window and list view. In your list view, you can have different view types, such as menu item and divider.
I list the code for popup window part:
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.option_menu, null);
ListView listView = (ListView) view.findViewById(R.id.listView);
listView.setDivider(null);
mAdapter = new OptionListAdapter(context, options);
listView.setAdapter(mAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//TODO: The code when item is clicked.
}
});
mPopupWindow = new PopupWindow(context, null, R.attr.popupMenuStyle);
mPopupWindow.setFocusable(true); // otherwise on android 4.1.x the onItemClickListener won't work.
mPopupWindow.setContentView(view);
mPopupWindow.setOutsideTouchable(true);
int height = 0;
int width = 0;
float density = context.getResources().getDisplayMetrics().density;
int minWidth = Math.round(196 * density); // min width 196dip, from abc_popup_menu_item_layout.xml
int cellHeight = context.getResources().getDimensionPixelOffset(R.dimen.option_height);
int dividerHeight = context.getResources().getDimensionPixelOffset(R.dimen.divider_height);
final int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
for (int i = 0; i < mAdapter.getCount(); i++) {
Object item = mAdapter.getItem(i);
if (item != null) {
View childView = mAdapter.getView(i, null, listView);
childView.measure(widthMeasureSpec, heightMeasureSpec);
height += cellHeight;
width = Math.max(width, childView.getMeasuredWidth());
} else {
height += dividerHeight; // divider
}
}
width = Math.max(minWidth, width);
Drawable background = mPopupWindow.getBackground(); // 9-pitch images
if (background != null) {
Rect padding = new Rect();
background.getPadding(padding);
height += padding.top + padding.bottom;
width += padding.left + padding.right;
}
mPopupWindow.setWidth(width);
mPopupWindow.setHeight(height);
mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
Then you can use following method to show the popup window:
PopupWindowCompat.showAsDropDown(mPopupWindow, parent, x, y, gravity);
In the adapter for list view, you can override getViewTypeCount() and getItemViewType() to support both menu item layout and divider layout, also you can add any view type that you need.
Here is a snapshot in my app:
In Material3 Design, MDC-Android, make menu items in each group, and call setGroupDividerEnabled(Boolean).
Dividers will inserted between group or menu item(s).
MyActivity.kt
private val binding by lazy { ActivityMyBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
// other initializations..
// ...
binding.toolbar.menu.setGroupDividerEnabled(true)
}
activity_my.xml
<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">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
<!-- Other properties -->
android:id="#+id/toolbar"
app:menu="#menu/main" />
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/item0"
android:title="item0"
app:showAsAction="never" />
<item
android:id="#+id/item1"
android:title="item1"
app:showAsAction="never" />
<group android:id="#+id/group0">
<item
android:id="#+id/item2"
android:title="group0 item2"
app:showAsAction="never" />
</group>
<group android:id="#+id/group1">
<item
android:id="#+id/item3"
android:title="group1 item3"
app:showAsAction="never" />
<item
android:id="#+id/item4"
android:title="group1 item4"
app:showAsAction="never" />
</group>
</menu>
I did it this way:
Reference screenshot:
style.xml:
<style name="popup" parent="Widget.AppCompat.ListView.DropDown">
<item name="android:divider">#color/colorPrimary</item>
<item name="android:dividerHeight">1dp</item>
<item name="android:textColor">#color/colorPrimary</item>
<item name="android:itemBackground">#android:color/white</item>
</style>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!--- Customize popmenu -->
<item name="android:dropDownListViewStyle">#style/popup</item>
</style>
Java code:
private void showPopup(View v) {
Context wrapper = new ContextThemeWrapper(this, R.style.popup);
PopupMenu mypopupmenu = new PopupMenu(wrapper, v);
MenuInflater inflater = mypopupmenu.getMenuInflater();
inflater.inflate(R.menu.menu_patient_language, mypopupmenu.getMenu());
mypopupmenu.show();
mypopupmenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
txtPreferredLanguage.setText(item.getTitle().toString());
switch (item.getItemId()) {
case R.id.menuEnglish:
// Your code goes here
break;
case R.id.menuFrench:
// Your code goes here
break;
}
return false;
}
});
}
Hope this will help you.
Super simple solution that worked out for me:
Define a drawable for the background:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#android:color/white"/>
<stroke
android:width="3dp"
android:color="#color/colorPrimary"/>
</shape>
then in Styles use the background:
<style name="bluetooth_popup" parent="#android:style/Widget.DeviceDefault.Light.PopupMenu">
<item name="android:textColor">#color/colorPrimary</item>
<item name="android:textStyle">bold</item>
<item name="android:textAllCaps">true</item>
<item name="android:background">#android:color/transparent</item>
<item name="android:itemBackground">#drawable/bluetooth_popup_buttons</item>
now :
group1[ item0 item1 item2 ] group1[item3];
change to :
group1[ item0 item1] group1[item2 item3]
group has a divider;
it likes that group can add a divder between item;
if divider is unavailable,try background;
i never user menu;
its my guess;

How to add an customized button on the actionbar?

I want to make an action bar with a button on the right with a margin_right. like this
And I use the action button to do it. But the button was on the right without margin_right.
android:layout_marginRight doesn't work here.
here is my styles.xml:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<item name="android:actionBarSize">50dp</item>
<item name="android:actionBarStyle">#style/my_actionbar_style</item>
<item name="android:actionButtonStyle">#style/my_action_button</item>
</style>
<style name="my_actionbar_style" parent="android:Widget.ActionBar">
<item name="android:background">#color/actionbar_backgroud</item>
<item name="android:titleTextStyle">#style/myTitleStyle</item>
<item name="android:displayOptions">showTitle</item>
</style>
<style name="myTitleStyle">
<item name="android:textColor">#ffffff</item>
<item name="android:textSize">20sp</item>
</style>
<style name="my_action_button">
<item name="android:background">#drawable/button_selector</item>
<item name="android:width">70dp</item>
<item name="android:textSize">13sp</item>
<item name="android:layout_marginTop">10dp</item>
<item name="android:layout_marginBottom">10dp</item>
<item name="android:layout_marginRight">10dp</item>
</style>
and this is my menu.xml:
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="AppCompatResource">
<item
android:id="#+id/action_search"
android:title="submit"
android:showAsAction="always" /></menu>
Another quick and clean way to go about this is specifying your own layout for that menu button. something like this
<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.example.MainActivity">
<item
android:id="#+id/action_custom_button"
android:title="Custom Button"
android:icon="#drawable/ic_custom_button"
app:actionLayout="#layout/layout_to_custom_button"
app:showAsAction="always" />
</menu>
there should be
layout_to_custom_button.xml
layout file which contains the padding and style you wanted.
and also do this in your activity for the click event
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_product_detail, menu);
final Menu mMenu = menu;
final MenuItem item = menu.findItem(R.id.action_custom_button);
item.getActionView().setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
mMenu.performIdentifierAction(item.getItemId(), 0);
}
});
return true;
}
I found the easiest way to do this was to just create your own action bar in a layout file. You can then use it by having your activities inherit from a common activity that overrides setContentView, where you just stick the view you're given into a parent view containing that and your action bar. You can mimick the overflowing menu behavior by using ActionMenuView (5.0+).
For example, assume you have an action_bar.xml with an ActionMenuView in it named menuView:
class BaseActivity extends Activity {
...
ActionMenuView mMenuView;
...
#Override
protected void setContentView(int resId) {
LayoutInflater inflater = getLayoutInflater();
View actionBar = inflater.inflate(R.layout.action_bar, null);
View contentView = inflater.inflate(resId);
mMenuView = (ActionMenuView)actionBar.findViewById(R.id.menuView);
RelativeLayout parentLayout = new RelativeLayout(this);
LayoutParams actionBarLayout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
actionBar.setLayoutParams(actionBarLayout);
parentLayout.addView(actionBar);
actionBar.setId(R.id.actionBar);
LayoutParams contentLayout = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
contentLayout.addRule(RelativeLayout.BELOW, actionBar.getId());
contentLayout.addRule(RelativeLayout.ALIGN_WITH_PARENT_BOTTOM);
contentView.setLayoutParams(contentLayout);
parentLayout.addView(contentView);
setContentView(parentLayout);
}
}

NullPointerException after replaceing actionbar with toolbar

I'm using badge layout in one menu item
here is some menuItems
<item
android:id="#+id/action_rdvmed"
android:title="#string/rdv"
android:icon="#drawable/ic_action_action_event"
android:showAsAction="always" />
<item
android:id="#+id/action_msg"
android:title="#string/msg"
android:actionLayout="#layout/badge_layout" <!--this one causes the problem-->
android:showAsAction="always" />
<item
android:id="#+id/action_actualiser"
android:title="#string/actualiser"
android:icon="#drawable/ic_action_refresh"
android:showAsAction="always" />
i'm getting a null pointer exception in my onCreateOptionMenu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_activity_med, menu);
this.MenuMed = menu;
RelativeLayout badgeLayout = (RelativeLayout) menu.findItem(R.id.action_msg).getActionView();
mCounter = (TextView) badgeLayout.findViewById(R.id.hotlist_hot); //the error in this line
imgMessage = (ImageView) badgeLayout.findViewById(R.id.hotlist_bell);
badgeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listMessages.clear();
msg();
}
});
return true;
}
and here is the part of muy onCreate methode whare i'm using toolbar
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity_med);
Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
thanks in advance.
I believe you're facing the same problem as one user faced here.
The trick is you need to change your android:actionLayout to app:actionLayout.
So, change your
<item
android:id="#+id/action_msg"
android:title="#string/msg"
android:actionLayout="#layout/badge_layout"
android:showAsAction="always" />
to,
<item
android:id="#+id/action_msg"
android:title="#string/msg"
app:actionLayout="#layout/badge_layout"
android:showAsAction="always" />

Showing Custom Layout on Overflow Drop Down Menu Item? Android

I am trying to figure out how to show a custom view for items inside the overflow menu (on right of actionbar) but I can't seem to figure it out. It still shows the title only :S. I want to do something like how twitter has it to show an icon, title, and subtitle in the first item in drop down menu. Can anyone help me out
Item in Menu.xml
<item
android:id="#+id/action_dropdown"
android:icon="#drawable/ic_action_overflow"
android:actionProviderClass="efwefwef.com.actionbar.ABDropDown"
android:title=""
android:showAsAction="always">
</item>
actionProvider Class #1
public class ABDropDown extends ActionProvider {
private static final String TAG = "MActionProvider";
private Context context;
public ABDropDown(Context context) {
super(context);
this.context = context;
}
#Override
public View onCreateActionView() {
return null;
}
#Override
public boolean hasSubMenu() {
Log.d(TAG, "hasSubMenu");
return true;
}
#Override
public boolean onPerformDefaultAction() {
Log.d(TAG, "onPerformDefaultAction");
return super.onPerformDefaultAction();
}
#Override
public void onPrepareSubMenu(SubMenu subMenu) {
subMenu.clear();
subMenu.add("Profile").setActionProvider(new ABDropDownProfile(context));
subMenu.add(Menu.NONE, Menu.NONE, 2, "Mezz 2");
}
}
Second ActionProvider class for the item I want to show a custom view
public class ABDropDownProfile extends ActionProvider {
private static final String TAG = "MActionProvider";
private Context context;
public ABDropDownProfile(Context context) {
super(context);
this.context = context;
}
#Override
public View onCreateActionView() {
View view = View.inflate(context, R.layout.actionbar_viewprofile, null);
return view;
}
#Override
public boolean hasSubMenu() {
return false;
}
#Override
public boolean onPerformDefaultAction() {
Log.d(TAG, "onPerformDefaultAction");
return super.onPerformDefaultAction();
}
}
I was just facing the same problem on how to list custom rows in overflow menu. Unfortunately there isn't much on web about customising action bars. If you want to list items with just icon and title in over flow menu, you need to do nesting of items within items. I did it like this:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_settings"
android:icon="#drawable/ic_action_overflow"
android:orderInCategory="100"
android:showAsAction="always">
<menu>
<item
android:id="#+id/add_source"
android:icon="#drawable/add_on"
android:orderInCategory="100"
android:showAsAction="never"
android:title="#string/add_source"/>
<item
android:id="#+id/channel_setup"
android:icon="#drawable/channelsetup_on"
android:orderInCategory="100"
android:showAsAction="never"
android:title="#string/channel_setup"/>
</menu>
</item>
<item
android:id="#+id/time"
android:orderInCategory="99"
android:showAsAction="always"
android:title="#string/time_title"/>
<item
android:id="#+id/weather"
android:icon="#drawable/ic_action_cloud"
android:orderInCategory="98"
android:showAsAction="always"
android:title="#string/weather_title"/>
<item
android:id="#+id/search"
android:actionViewClass="android.widget.SearchView"
android:icon="#drawable/ic_action_search"
android:orderInCategory="97"
android:showAsAction="collapseActionView|always"
android:title="#string/search_title"/>
</menu>
to achieve this thing:
And here is the reference to my question:
link
I hope it might help you.
If you just want add a drawable (red dot) after text, you can use imageSpan to add drawable after main text like below:
private MenuItem settingsItem;
....
SpannableStringBuilder builder = new SpannableStringBuilder(getString(R.string.settings_menu_name) + " .");
Drawable drawable = getResources().getDrawable(R.drawable.red_dot);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
builder.setSpan(new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE), builder.length()-1, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
settingsItem.setTitle(builder);

Categories

Resources