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>
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
if you open the drop-down list and without selecting any item close the drop-down list, the hint will remain in the top position. TextInputLayout will return to its original state (the hint is centered vertically) only after the focus moves to another element.
XML:
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/hint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:hint="#string/register_children_child_name_hint"
style="#style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
app:endIconDrawable="#drawable/ic_dropdown"
app:boxStrokeWidth="0dp"
app:boxStrokeWidthFocused="0dp"
app:boxStrokeColor="#color/transparent"
app:boxBackgroundColor="#color/black_5_new"
app:boxCornerRadiusTopStart="5dp"
app:boxCornerRadiusTopEnd="5dp"
app:boxCornerRadiusBottomStart="5dp"
app:boxCornerRadiusBottomEnd="5dp"
app:hintTextColor="#color/gray_new">
<AutoCompleteTextView
android:id="#+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:textAppearance="#style/NormalText"
android:textSize="17sp"
tools:ignore="LabelFor" />
</com.google.android.material.textfield.TextInputLayout>
how can I make it return to its original state if the drop-down list is closed and no items are selected?
I tried clearFocus() but it didn’t help.
You can use something like:
AutoCompleteTextView autoCompleteTextView = ((AutoCompleteTextView)textinputlayout.getEditText());
autoCompleteTextView.setAdapter(adapter);
autoCompleteTextView.setOnDismissListener(new AutoCompleteTextView.OnDismissListener() {
#Override
public void onDismiss() {
autoCompleteTextView.clearFocus();
}
});
I found out why when opening the drop-down list, TextInputLayout immediately went into an active state and did not return to its original state when drop-down list closed. I call setFocusableInTouchMode(true) in my code. When I removed this line, everything worked as it should.
I need to implement two single choice list on an alert dialog. The two single choice items can be seen in the first picture. Once you clicked on the button , it will show a list of item(second picture). My question is how do I implement two single choice list item on an alert dialog? Thanks!
picture is adopted and a screenshots from VirtualGuitar+
You can create a layout with two spinners in horizontal linear layout.
Then make alert dialog with your layout xml like this
AlertDialog.Builder builderVal=new AlertDialog.Builder(mContext);
builderVal.setTitle("Title here") ;
View holder=View.inflate(mContext, R.layout.spinners, null);
builderVal.setView(holder);
Spinner spinner1 = (Spinner) holder.findViewById(R.id.spinner1);
//implement spinner logic
builderVal.setPositiveButton("Okay",null);
builderVal.show();
spinners.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/spinner1"></Spinner>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/spinner2"></Spinner>
</LinearLayout>
I've been looking for something like Pinterest menu whenever item in GridView is pressed. I know it's too broad question. But little strike on question will provide a correct way to achieve these.
Que:
How one can implement customise context menu like Contacts+ or Pinterest Context menu on GridView item?
Tried:
ArcMenu : But they are replacement of Slider Menu or Pop up Menu for overall Application. I want menu which can be created onFly for GridView Item.
Satellite Menu : Same as ArcMenu, replacement of Slider Menu or Pop up Menu for overall Application.
Please enlighten me to achieve behaviour like these.
I think instead of Context Menu you can use PopupWindow for your requirement.
//Custom popup view
View view= layoutInflater.inflate(R.layout.popupview, null);
PopupWindow popupWindow = new PopupWindow(
view,
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
//Display popup window on clicking anything
//Displays pop up window near button with offsets 10 and -10
popupWindow.showAsDropDown(button, 10, -10);
For more info
http://developer.android.com/reference/android/widget/PopupWindow.html
http://android-er.blogspot.in/2012/03/example-of-using-popupwindow.html
Use quick action 3D view. It is the menu which is used in twitter application.
For source: https://github.com/lorensiuswlt/NewQuickAction3D
I'm using a modified version of ArcMenu (just small and mainly visual modifications) for something similar. And it's perfectly adaptable to gridview (i'm using it with StaggeredGridView onitemclick).
You only have to define it in the xml inside the gridview item with Visibility:gone and then in your gridview adapter or in the activity set it to visible when the item is touched or clicked...
don't know why you say it's for overall app, it can be used as an item element also.
You can check out this library which I created:
https://github.com/reyanshmishra/PinMenu
You can clone it and import it as a module to your app and do something like this:
In your XML layout:
<?xml version="1.0" encoding="utf-8"?>
<com.reyanshmishra.pinmenu.PinMenuHolder 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"
app:pin_holder_draw_over_view="true"
app:pin_holder_overlay_color="#90ffffff">
<com.reyanshmishra.pinmenu.PinMenu
android:id="#+id/one"
android:layout_width="48dp"
android:layout_height="48dp"
android:elevation="5dp"
android:padding="5dp"
android:scaleType="centerInside"
android:src="#drawable/ic_close_black_24dp"
app:pin_background_color="#color/white"
app:pin_name="Cancel"
app:pin_selected_color="#BD081C" />
<com.reyanshmishra.pinmenu.PinMenu
android:id="#+id/three"
android:layout_width="48dp"
android:layout_height="48dp"
android:elevation="5dp"
android:padding="5dp"
android:scaleType="centerInside"
android:src="#drawable/share_variant"
app:pin_background_color="#color/white"
app:pin_name="Share"
app:pin_selected_color="#BD081C" />
<com.reyanshmishra.pinmenu.PinMenu
android:id="#+id/four"
android:layout_width="48dp"
android:layout_height="48dp"
android:elevation="5dp"
android:padding="5dp"
android:scaleType="centerInside"
android:src="#drawable/dots_horizontal"
app:pin_background_color="#color/white"
app:pin_name="More"
app:pin_selected_color="#BD081C" />
</com.reyanshmishra.pinmenu.PinMenuHolder>
Now in Java:
PinDialog mPinDialog = new PinDialog(this);
mPinDialog.setContentView(R.layout.layout_pin_menu);
mPinDialog.setPinSelectListener(new PinSelectListener() {
#Override
public void pinSelected(PinMenu pinMenu) {
Toast.makeText(mContext, "" + pinMenu.getPinName(), Toast.LENGTH_SHORT).show();
}
});
mPinDialog.addToRecyclerView(mRecyclerView);
It's still under development so it just supports recyclerview. For depth of the implementation, you can just skim through the classes of the library. I don't think I can put all the code here.
The result it something like this:
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.