Actionbar progress indicator and refresh button - android

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.

Related

Android toolbar custom image view icon with drop down list

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

Spinner items are cut off at top if spinner is placed on a dialog

I placed a spinner on a dialog. When I want to select an item and the item list is shown below the spinner, everything is fine and I can scroll through the items. But if the item list is shown above the spinner, the item list is cut off and I cannot scroll:
It looks like the system does not identify, that the item list above the dialog is not visible and therefore does not show the scrollbars.
My spinner definition looks like this:
<Spinner
android:id="#+id/spnnrValue"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="2dp"
android:layout_marginLeft="-20dp"
android:layout_weight="1" />
This is how I define the dialog:
dialogColorPickerExtended = new Dialog(Base.getMainActivity(), R.style.full_screen_dialog);
dialogColorPickerExtended.setCancelable(true);
dialogColorPickerExtended.setContentView(R.layout.template_color_picker_extended);
if (dialogColorPickerExtended.getWindow() != null)
dialogColorPickerExtended.getWindow().getAttributes().width = (int) (GUIManager.getScreenWidth() * 0.9f);
Do you have any idea, how I can show the complete item list?
You might not be able to show it all at once, but adding a scrollbar to the spinner itself may be a solution. Visit this page, you might be able to solve this problem with an overall functionality improvement by adding a scrollbar to your spinner.
Spinner's scrollbar style

How to make recyclerView_items unclickable, while one of them is clicked and working?

Premise
Each of my RecyclerView_items displays an image, and changes its image_resource when tapped.
One of them is the right answer which has additional function: navigation to another fragment 5-second after changing its image.
Basically, the function of clickListener of RecyclerView_items is
wrong item
click -> change image_resource
right item
click -> change image_resource -> delay(5000) -> navigate to another fragment
Problem
Then, my problem is that after the right_item is tapped, other items are clickable during delay(5000).
I don't want them to change their images during delay(5000).
How to do it?! Thanks in advance.
You can achieve this by adding a flag at time when user click right image then make that variable false. As such after the delay before moving to the next fragment make it true again.
boolean flag = true;
then in your item click method
view.setOnClickListner {
if (flag) {
if (rightimageclicked) {
flag = false;
delay {
flag = true;
// Move to other fragment
}
} else {
// change the image for wrong click
}
}
}
The simple trick you can use is make a FrameLayout or View that overlaps on the RecyclerView. Set ists visibility to GONE. Then inside activity or fragment where you can access this FrameLayout or View which is overlapping, add an empty OnClickListener on this view.
*viewId*.setOnClickListener { }
Now set its visibility to VISIBLE when you call delay. When delay finished again set its visibility to GONE
This is what I understood, you want to lock the entire screen (make all items or buttons unclickable) when you are in delay(5000).
This is what I would do, give a CLICKABLE overlay view on top of recycler view and toggle its visibility. I used the same for locking the entire screen while making an API call.
view_overlay.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rl_progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:clickable="true"
android:focusable="true"
android:elevation="5dp"
android:visibility="invisible">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#android:color/transparent"
android:indeterminateTint="#android:color/transparent" />
</RelativeLayout>
Obviously you can replace ProgressBar with just View to get a transaprent view.
To include it in your main view, give this at the bottom of your parent layout or below recycler view. Whichever you choose make sure you have the overlay view on top of recycler view.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
...
...
<include layout="#layout/view_overlay" />
</RelativeLayout>

Disabling all touches when loading indicator is shown

I have a simple main layout, and then I add a fragment layout that only shows an indicator loading on top of that main layout. Problem is that I can still press the buttons behind the loading indicator.
Is there anyway to disable touches so it doesn't pass through to the back? I don't want to have to disable each button on the main screen one by one.
You could set the "clickable" attribute to "true" in the layout that contains your ProgressBar:
<FrameLayout
android:id="#+id/progressBarContainer"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:clickable="true" >
<ProgressBar
android:id="#+id/progressBar"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
Then while the ProgressBar is visible, its container (which fills the entire screen although it's invisible) will intercept any click events so they won't fall through to the underlying layout while your ProgressBar is showing.
To use this, do this when you want to show the ProgressBar:
findViewById(R.id.progressBarContainer).setVisibility(View.VISIBLE);
and then do this when you're done with it:
findViewById(R.id.progressBarContainer).setVisibility(View.INVISIBLE);
For instance, if you're using this in an AsyncTask, you could make it visible in onPreExecute(), then make it invisible in onPostExecute().
Return true while you wanna block user touches. Override this method in your Activity.
#Override
public boolean onTouchEvent( MotionEvent event ) {
return true;
}

ProgressBar at the bottom of gridview

I have a GridView which shows a grid of 15 Views for the first time. Then, on click of a button, I add 5 more grid views. So, my question is: How to add a ProgressBar at the bottom of a page, when those 5 Views are loading ? Like a spinner loading and the 5 Views get updated.
Hi i have a tab host tabwidget for tabs and gridview inside framlayout..now if i want the progressbar then should i need to inclue this linearlayout after frame layout or inside frame laoyout?
Add this below your GridView in the XML.
<LinearLayout
android:id="#+id/linlaProgressBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<ProgressBar
style="#style/Spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp" />
</LinearLayout>
And in your Activity, where you are loading the data (assuming, it is an AsyncTask), in your onPreExecute() show it:
#Override
protected void onPreExecute() {
// SHOW THE BOTTOM PROGRESS BAR (SPINNER) WHILE LOADING MORE PHOTOS
linlaProgressBar.setVisibility(View.VISIBLE);
}
And in the onPostExecute(), hide it:
#Override
protected void onPostExecute() {
// SHOW THE BOTTOM PROGRESS BAR (SPINNER) WHILE LOADING MORE PHOTOS
linlaProgressBar.setVisibility(View.GONE);
}
If you are not using an AsyncTask, then set the visibility to View.VISIBLE at the start of the method where you start downloading the data and set it to View.GONE either after or just before you set the Adapter.
EDIT: Adding additional info.
Couple of things.
You are downloading data off the Internet for which, I would recommend switching to AsycnTask instead of using a conventional () Method.
Check out my answer a few days ago on a similar question here: https://stackoverflow.com/a/13265776/450534
In that answer, you will find a complete solution that will suit your exact needs. Well, almost entirely anyway. You may have to make a few modifications and adapt to a few things yourself. But by and large, it will answer all your questions. I use it in my apps and they function as you say, the Google Play loading text at the bottom. And it really is complete. :-)
You need to create custom view for that and inflate it and add as bottom view in gridview
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button android:text="Load"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
<ProgressBar
android:layout_width="25.0dip"
android:layout_height="25.0dip"
android:layout_centerInParent="true"
android:visibility="gone"
/>
</RelativeLayout>
now inflate this view and show the progressbar at bottom of gridview
You can set button as bottom with this when you click just visible the progressbar
Just add a ProgressBar in your layout, set its visibility to VISIBLE or GONE whenever you want to show/hide it.
Add a in the xml of GridView and set its property "alignParentRight = true" and "visibility = invisible" . In your activity , use Async task class and on its preExectue method set set its visibility to visible
pb.setVisibility(View.VISIBLE);
In doInBackground method load your images and finally in onPostExecute method make this progress bar invisible.
pb.setVisibility(View.INVISIBLE);
execute this async task class on click of load button.
This is an easy tutorial for understanding asyncTask
http://androidresearch.wordpress.com/2012/03/17/understanding-asynctask-once-and-forever/
Or threads can be used instead of async task.

Categories

Resources