Let me give you a brief scenario what is happening.
I want to have a refresh button on my action bar which switches to the indeterminateProgressStyle (a rotating circle) while somethings are loading.
In my project i have the following layouts. (e.g. res/layout/actionbar_indeterminate_progress.xml)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center">
<ProgressBar android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_gravity="center"
style="?android:attr/indeterminateProgressStyle" />
</FrameLayout>
and when the user clicks on the refresh button I do the following.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
refreshMenuItem = menu.findItem(R.id.menu_refresh);
if (refreshMenuItem != null) {
// Show refresh button if we are in action bar mode, but only if
// there's something to be refreshed
boolean selectedItemExists = (getCurrentBrowsingContainer() != null);
refreshMenuItem.setVisible(selectedItemExists);
if (is_spinner_running) {
refreshMenuItem.setActionView(R.layout.actionbar_indeterminate_progress);
} else {
refreshMenuItem.setActionView(null);
}
}
return super.onCreateOptionsMenu(menu);
}
also my res/menu/main.xml looks like below.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
...
<item android:id="#+id/menu_refresh" android:icon="#drawable/ic_menu_refresh" android:showAsAction="always" android:title="#string/refresh" />
<item android:id="#+id/menu_search" android:title="#string/menu_search" android:icon="#android:drawable/ic_menu_search" android:showAsAction="never" />
<item android:id="#+id/settings" android:title="#string/settings" android:icon="#android:drawable/ic_menu_preferences"></item>
<item android:id="#+id/exit" android:title="#string/exit" android:icon="#android:drawable/ic_menu_close_clear_cancel"></item>
...
</menu>
The problem is that, I start my activity in portrait for example and hit on the refresh button, it stops nicely. Now i rotate it and hit the refresh button again but now it keeps on showing the indeterminate progress for some reason. I checked, the refreshMenuItem.setActionView(null) is getting called but it still keeps on showing the indeterminate thingy. Also now the refreshMenuItem seems to be invisible for some reason, cause the onOptionsItemSelected is not getting called when i click on the indetermintate progress.
so I tried with a different sample app and it works perfectly without any issues. So i am wondering where could i go wrong. any pointers will help.
Actually I figured out the problem. my project was supposed to handle configuration changes before (so we had configchanges in the manifest). with the actionbarsherlock, it becomes unresponsive with the configchanges.
Now since we were not recreating the activity before on config changes, we were passing the activity in some of our code, which was fine since it was never recreated and we took care of cleaning it. but now to get actionbarsherlock working we have to recreate the activity on configchanges. The earlier instance of the activity was still present in some parts of the code and was not getting overridden with the new instance of the activity. so the menuitem which i was trying to stop spinning was actually belonging to the older instance and not the new one.
so refactored the code to use the current instance of the activity and everything worked great!
Regarding onOptionsItemSelected not getting called when clicking on the intermediate progress: when action view is set, it disables the default behavior of the action item. It also overrides previously set action provider. The only way to handle action view click is by setting OnClickListener.
Regarding intermediate progress not stopping after rotation: I did not have exact this problem. In my case the intermediate progress would not show up at all when I click on the refresh action item, but it would show up nicely if it was triggered from the code. The way I made it work is by moving the code that calls setActionView(...) to Handler.post(Runnable).
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
I have searched a lot for this on stackoverflow and on some other professional websites but not found any solution.
I have tried different methods but result was about 0. Some methods work for me but only in that condition when I clicked in top menu navigation bar. But I don't want to show action/top navigation bar.
I only want to show these items in bottomnavigation bar like Recent News, Hot Stories, Most Visited. There are three activities which I want to start by clicking on these items, because my app is a webview app.
For this purpose I am using onOptionItemSelected I think that's wrong. So question goes here >>
I have three buttons in bottom navigation.
(action_item1) = on click it should start second_activity
(action_item2) = on click it should start third_activity
(action_item3) = on click it should start fourth_activity
Please help me I am new in android studio.
Navigation XML is here!
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/action_item1"
android:icon="#drawable/ic_recent"
android:title="Recent News" />
<item
android:id="#+id/action_item2"
android:icon="#drawable/ic_hot"
android:title="Hot Stories" />
<item
android:id="#+id/action_item3"
android:icon="#drawable/ic_most"
android:title="Most Visited" />
</menu>
Mainactivity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.pkg.webview.webview">
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/navigation" />
</android.support.constraint.ConstraintLayout>
Mainactivity.java
package com.pkg.webview.webview;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
public class MainActivity extends AppCompatActivity{
private ProgressBar pb;
private WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
getSupportActionBar ().hide ();
setContentView (R.layout.activity_main);}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater ().inflate (R.menu.navigation, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId ()) {
case R.id.action_item1:
startActivity (new Intent (this, secondactivity.class));
break;
}
return super.onOptionsItemSelected (item);
}
}
From what I have understood, you want to implement Bottom Navigation and open different activities/screens for different items.
I have searched a lot for this on stackoverflow and on some other professional websites but not found any solution.
Everything is not available for copy paste as per your requirement.
I only want to show these items in bottomnavigation bar like Recent News, Hot Stories, Most Visited. There are three activities which I want to start by clicking on these items because my app is a webview app.
To dive into more details refer this tutorial. For your simplicity in this tutiorial Bottom Navigation is implemented through BottomNavigationView provided in android.support.design.widget.BottomNavigationView and fragments are used for different screens as per our requirement.
I want to start by clicking on these items because my app is a webview app.
You can open webview inside these fragments. eg in OnCreate of your fragment you can load webview.
Please help me I am new in android studio.
As a community, we always Welcome New People. Follow the community guidelines and feel free to ask anything after you have done your thorough research.
It's a good thing that you started, now Instead of diving directly into it, take a step back and understand it's working.
May the force be with you..
Hope this helps.
Happy Coding...
Hello I am having action bar which I made using appcompat library in android. It looks like
When I click on the refresh menu item then I here show the progress bar and it is displaying perfectly
menuItem.setActionView(R.layout.progressbar);
menuItem.expandActionView();
progressbar.xml
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ProgressBar>
but after my task done in async task I am doing to stop it in onPostExecute like below which is not working, means progress bar still executing after that also. I want to hide it and show refresh button after this process complete but it is not working currently
menuItem.collapseActionView();
menuItem.setActionView(null);
Any idea what it is wrong ?
I can guess, you've forgot to invalidate action bar. If you, then just call invalidateOptionsMenu() . And see the magic ;)
menuItem.collapseActionView();
menuItem.setActionView(null);
YourActivity.this.invalidateOptionsMenu();
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);
}
Is it possible to show the progress indicator (the one that is show using requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS) in place of a refresh button?
The idea is to work as Gmail client does: When not loading show refresh button and when loading show the indeterminate spinner in the place of refresh button
Yes you can do it easily this way.
private MenuItem refresh;
.
.
.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.options_menu, menu);
// refresh menu item
refresh = menu.findItem(R.id.refresh_option_item);
return super.onCreateOptionsMenu(menu);
}
You have to get your refresh menu item like above and then, you can enable spinning item like below:
refresh.setActionView(R.layout.actionbar_indeterminate_progress);
and when you task is completed, you can disable spinning like below:
refresh.setActionView(null);
And lastly, the actionbar_indeterminate_progress.xml can be like this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="64dp"
android:layout_height="wrap_content"
android:gravity="center">
<ProgressBar android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
style="?android:attr/indeterminateProgressStyle" />
</FrameLayout>
You may try the follow: put both the refresh button and the indeterminate spinner inside a FrameLayout, so the two are stacked in the z-plane, show in the same position on the screen. Then you just have to play with the Visibility. When you want to show the refresh button, you set the spinner to invisible and the button to visible. When you want to show the spinner, set it to visible and the button to invisible.