I use ActionBarSherlock, in which I set the navigation mode to 'list'
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getSupportActionBar().setListNavigationCallbacks(adapter, this);
Is it possible to dynamically show a second spinner, depending on which item is selected?
Use a custom action bar layout.
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setCustomView(R.layout.action_bar_custom);
action_bar_custom.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Spinner
android:id="#+id/action_bar_spinner_collection"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</Spinner>
<Spinner
android:id="#+id/action_bar_spinner_collection_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</Spinner>
</LinearLayout>
Use this one..This may works...
Code:
getMenuInflater().inflate( R.menu.main, menu );
mSpinnerItem = menu.findItem( R.id.menu_spinner );
setupSpinner( mSpinnerItem );
Menu XML:
<item
android:id="#+id/menu_spinner"
android:actionViewClass="android.widget.Spinner"
android:visible="false"
android:showAsAction="always"/>
NEVER use NAVIGATION_MODE_LIST and onNavigationItemSelected it is not worth it !
#Override
public boolean onNavigationItemSelected(int position, long itemId)
You also cannot use menu's to do this:
#Override public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
due to inflation ordering.
Reasons:
(1) it generates a "hidden" spinner, for which you can not get the id.
(2) you cannot customize this spinner
(3) you save 30 lines of code, but are permanently limited if you want to add a second bi-directional spinner
(4) not even in the special case of "simple code" (one spinner), you lose to much.
(5) you cannot use tabs.
the key is actionBar.setCustomView(R.layout.action_bar_custom);
and spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()...
for each spinner.
Trust me I lost hours trying each solution.
Related
I want to provide a numbered month's list dropdown with calendar icon click on the app toolbar. I am having two issues/questions to implement this.
Unable to place calendar, icon with out disturbing the title (NavHost traversed fragment names).
Don't know how to show a clickable drop down list with some options on that icon
With the help of internet, I have implemented single activity and multi fragment (Jetpack navigation) architecture app as shown in below image.
Below is the code I have tried to implement this:
And here is App screenshots with different behaviors
When I uncomment above code (21 to 35), I see 1 and 3 of below images and If I comment that ou, I see 2 and 4.
For the first issue, is it just a UI trick to update the RelativeLayout width to warp_content of child ? or any other way to achieve this properly.
For the second issue, I didn't find a one step or atleast two step solution. Every where it shows Navigation menu option, when I try for "Android toolbar clickable dropdown list".
My Final goal: Show a calendar icon with months list click able dropdown (1 month, 3 months, 6 months, 9months ... e.t.c) on the right side of the toolbar when user lands on Invoices page for filtering
Make this in xml layout file:
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/app_bar"
style="#style/MyTheme.ToolbarStyle"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:paddingStart="12dp"
android:paddingLeft="12dp"
android:paddingEnd="12dp"
android:paddingRight="12dp"
app:title="#string/app_name"/>
<ImageView
android:id="#+id/yourImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_your_icon" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
You need use popup menu. Make xml file for menu. For example:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/month1"
android:title="1month" />
<item
android:id="#+id/months3"
android:title="3months" />
<item
android:id="#+id/months6"
android:title="6months" />
<item
android:id="#+id/months9"
android:title="9months" />
</menu>
And than use menu in activity. Create instance of popup menu, set listener for it and set listener for youe image. Write this in onCreate function:
ImageView image = findViewById(R.id.yourImageView);
PopupMenu popupMenu = new PopupMenu(this, image);
popupMenu.getMenuInflater().inflate(R.menu.menu_your_name, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
//Do what you want
return true;
}
});
image.setOnClickListener(view->{
popupMenu.show();
});
May be this is not the most optimal way, but it must be work as you want.
I found the answer, for my multiple fragment and single activity architecture ("Jetpack navigation") related menu/custom action icons in toolbar
Note: Below 1,2,3 helps to solve above problem statement 1 and the remaining helps 2
Create another menu file with required content.
Populate it with `onCreateMenuOptions in the desired fragment
(Note: Include setHasOptionsMenu(true) in the onCreate)
If you inflate a menu in this onCreateMenuOptions, you new menu will be appended to the already existing one of parent/main activity inflated.
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.invoice_list_menu, menu)
super.onCreateOptionsMenu(menu, inflater)
}
Create a sub menu. in the menu item with radio checkable group. See the last screenshot for example
override onOptionsItemSelected(item: MenuItem) to capture the menu clicks. Make sure you are updating the checkable status of the radio item.
Note: Make sure you are using the style="#style/Widget.MaterialComponents.Toolbar.Primary" from above 2nd link, to get the proper white overlayed nice action bar. Otherwise you will end up having some dark text colored action bar with out known why
Below links are helpful to understand more:
Android developers docs Menu (To understand things inside menu)
Android material menu action bar implementation (To create a proper action bar with material design compatible)
Extended ActionBar guide (To add search to toolbar and create collapsable toolbar )
Android Jetpack Navigation example contained menu usage
Below screenshot is the final output and code reference
Material design has an Exposed Dropdown Menu implemented with a AutoCompleteTextView like this:
<com.google.android.material.textfield.TextInputLayout
style="#style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/hint_text">
<AutoCompleteTextView
android:id="#+id/filled_exposed_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
But I need to have the same look an feel but with the spinner behavior (Without autocomplete, just display popup and select an item).
I disabled editing on AutoCompleteTextView to avoid to use the auto complete, but after selecting one of the item then the autocomplete just list the items that matches the item text selected given a filter that is used in this view. This is the code:
<AutoCompleteTextView
android:id="#+id/filled_exposed_dropdown"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
**android:editable="false"**/>
Also I put a listener to open items list when click on it
val editTextFilledExposedDropdown = findViewById<AutoCompleteTextView>(R.id.filled_exposed_dropdown)
editTextFilledExposedDropdown.setAdapter(adapter)
editTextFilledExposedDropdown.setOnClickListener {
(it as AutoCompleteTextView).showDropDown()
}
So, I would want to know if it is possible to implement this but with a spinner
This was my attempt using a spinner, but it not display the style correctly OutlinedBox.Dense.ExposedDropdownMenu and also display two arrow bottom icon, I think one for the style and another for the spinner.
this was the code with the spinner:
<com.google.android.material.textfield.TextInputLayout
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Hint">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/layout_id"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Currency">
<androidx.appcompat.widget.AppCompatSpinner
android:id="#+id/my_spinner"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.google.android.material.textfield.TextInputLayout>
This is what i was looking for, just disable autocomplete functionality of AutoCompleteTextView by overriding getFilter method.
the answer is posted here (AutoCompleteTextView - disable filtering)
Update:
Can be achieved with 1 line of code:
android:editable="false"
On the AutoCompleteTextView
From the material.io docs:
Note: In order to have a non editable variation of the menu, you
should disable user input in the AutoCompleteTextView. That can be
achieved by setting android:editable="false" on the
AutoCompleteTextView.
No idea why Google chose to use a deprecated attribute for this though...
tools:ignore="Deprecated" can be used though to remove the warning
You can use android:inputType="none" on the AutoCompleteTextView.
How about creating PopupMenu instead of AutoCompleteTextView
Here is an example of how creating menu in android :
Context wrapper = new ContextThemeWrapper(getContext(), R.style.popupMenuStyle);
//yourView is the view that you want to display the menu above it.
PopupMenu popupMenu = new PopupMenu(wrapper, yourView);
popupMenu.getMenuInflater().inflate(R.menu.menu, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(item -> {
switch (item.getItemId()) {
case R.id.delete:
//delete
break;
case R.id.edit:
//edit
break;
}
popupMenu.dismiss();
return true;
});
popupMenu.show();
menu.xml file inside menu folder:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/edit"
android:title="#string/edit">
</item>
<item
android:id="#+id/delete"
android:title="#string/delete">
</item>
</menu>
I am new on android.
What I want to do is, when I press the icon on Actionbar the LinearLayout is showing.
Here's the picture
As you can see, there's a magnifier icon.
when I press that icon, the search bar below it will gone.
And when i press the icon again, it'll show again.
I already trying use setVisibility, but its show error.
Here's my Java code
MenuItem searchBar;
searchBar = (MenuItem) findViewById(R.id.search);
searchBar.setVisibility(View.GONE);
}
public void toggle_contents(View v){
if(searchBar.isShown()){
Fx.slide_up(this, searchBar);
searchBar.setVisibility(View.GONE);
}
else{
searchBar.setVisibility(View.VISIBLE);
Fx.slide_down(this, searchBar);
}
}
And Here's my XML code
<LinearLayout
android:id="#+id/search"
android:background="#color/gray74"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="7dip"
android:paddingBottom="7dip" >
<EditText
android:id="#+id/search_global"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="#drawable/searchbackground"
android:text="Search"
android:textColor="#color/gray74" />
</LinearLayout>
Thanks before
First: A MenuItem is not a View and consequently it's not part of your layout. Therefore you shouldn't be using:
MenuItem searchBar = (MenuItem) findViewById(R.id.search);
But instead:
MenuItem searchBar = menu.findItem(R.id.search);
Second: When you make changes to your menu, you should call invalidateOptionsMenu().
By doing this you basically tell the menu that some changes have been made to it. This will make the menu recreate itself and request that the system call onPrepareOptionsMenu().
This question already has answers here:
Actionbar not shown with AppCompat
(3 answers)
Closed 9 years ago.
I am using appcompat in my app. I want the menu items to show on actionbar or at least the overflow(3 dots) to show them when there is no room. There is lot of space on the actionbar, but still they don't show up. The menu flow raises from the bottom and that too only when menu button is pressed.
menu_activity.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="#+id/menu_lang"
android:showAsAction="always"
android:title="#string/menu_lang"
android:icon="#android:drawable/ic_input_lang"/>
</menu>
activity:
#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, menu);
return true;
}
This post says that it not works when hardware menu button is present. But other apps are able to show items on the same device. So, that answer seems to be incorrect. Can someone please help on this?
You seem to be using the wrong menu:
Your file is named "menu_activity.xml" and you inflate the menu with the Resource-Id: R.menu.reminder_menu
The Resource name of the menu should be the same as the file name, i.e.: R.menu.manu_activity
Try it with this again - I ran into this too once and it drove me nuts...
Update
After clarification that the above part was for obfuscation, please make sure that:
You extend ActionBarActivity.
You use (or extend) one of the Theme.AppCompat themes for the activity (or whole app)
Because on older devices, the Actionbar related attributes are not present, make sure that all these attributes in the XML are used with a custom namespace. Here that would be the showAsAction attribute, so that the compatibility library can pick them up.
You already had the custom namespace defined ("app", in the menu tag). You need to change the android:showAsAction tag to app:showAsAction according to the Android guide.
Your corrected menu_activity.xml would then look like this:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="#+id/menu_lang"
app:showAsAction="always"
android:title="#string/menu_lang"
android:icon="#android:drawable/ic_input_lang"/>
</menu>
The extended Android guide for actionbar covers these new and nasty traps...
Okay I think I found a solution for you. It is called Overflow Menu and you need to call the below method in your onCreate method.
private void getOverflowMenu() {
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if(menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Try this and let me know if it works for you.
EDIT:
I think I understood your problem finally. I can give you one idea. If you do not want to use overflow menu and just display menu items as displayed in the screen-shot you have posted, you can create a layout on top of your activity.
You can take a linear layout, give a background that looks the same as action bar and place whatever icons you want to put there, and give functionality to them with onClickListener. Hope this will give you some idea. This way you can create your own custom menu. Try the layout below and replace ic_launcher drawable with menu icons. Then just set onClickListeners to them and perform whatever functions you want to perform inside onClick method.
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#66000000" >
<ImageView
android:id="#+id/xMenuBtn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:background="#drawable/ic_launcher" />
<TextView
android:id="#+id/xMenuTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Chats"
android:textSize="18sp"
android:layout_toRightOf="#+id/xMenuBtn1"
android:layout_centerVertical="true" />
<ImageView
android:id="#+id/xMenuBtn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/xMenuBtn3"
android:background="#drawable/ic_launcher" />
<ImageView
android:id="#+id/xMenuBtn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="#drawable/ic_launcher" />
</RelativeLayout>
Try in your activity onCreate() :
ActionBar bar = getSupportActionBar();
bar.setTitle(R.string.app_name);
and then :
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
getSupportMenuInflater().inflate(R.menu.menu_activity, menu);
return super.onPrepareOptionsMenu(menu);
}
I have a fragment layout like below.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:baselineAligned="false">
<fragment
android:id="#+id/callsListFragment"
android:layout_width="0dp"
android:layout_weight="1.5"
android:layout_height="match_parent"
class="com.example.MyCallsListFragment" />
<fragment
android:id="#+id/callDetailFragment"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent"
class="com.example.MyCallsDetailsFragment" />
</LinearLayout>
The first fragment shows a list of all calls made and the second one its details. Each of them has a separate menu option.
Say callsListFragment has two menu items such as
View outstanding calls
Calls for today
callDetailFragment has three menu items such as
Edit call
Add new call
Archive call
I inflate those menus from respective fragments.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_mycalls, menu);
}
However, in the dual pane, I see all the five menu items which is rather conflicting as it is hard to find which one for which.
Is this the approach to show menu items? Could you guide me through the correct way of doing it?
The app is to support both tablets and handsets.
Check is two pane mode when create option menu.
boolean mTwoPane = // isTwoPane ?
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (mTwoPane) return; // if (!mTwoPane) return;
inflater.inflate(R.menu.menu_mycalls, menu);
}
Or, Make new menu for two pane mode. (make resource folder like "menu-land")