Changing view on Menu Item in Action Bar - android

I'm attempting to implement a refresh button in my app to allow a user to manually re-sync to a web server. The code works, but I'm having trouble figuring out the action views (at least, I think that's what I'm supposed to be using).
My menu item is here:
<item
android:id="#+id/main_menu_refresh"
android:enabled="true"
android:icon="#drawable/refresh"
android:orderInCategory="1"
android:showAsAction="ifRoom"
android:title="#string/refresh"
android:actionViewClass="android.widget.ProgressBar">
</item>
The problem is, it always shows the ProgressBar. I wondered if it worked like the search widget (the only example I really see online) and added the collapseActionView tag to the showAsAction and that prevented it from showing up immediately. However, when I click the refresh button, the icon disappears (good), but so does the Title in the action bar, and the ProgressBar appears on the left side of the window where the title used to be. Also not what I wanted.
As something of a last ditch effort, I attempted to add this to my code, and remove the actionViewClass from the XML:
MenuItem refresh = (MenuItem)findViewById(R.id.main_menu_refresh);
Log.w("MyApp", "Have Menu");
ProgressBar pb = new ProgressBar(ReadingList.this);
refresh.setActionView(pb);
That didn't work either, giving me a null pointer error on setActionView.
I need a solution that I can call from any function (there is an auto-sync period at the beginning I would like the ProgressBar to display during as well), and be able to return it to it's static icon after.
I tried reading through this question, but I am having trouble understanding what the answer means. I feel like I was trying to do just what it says, but I guess not. Any assistance is much appreciated.
Edit: For sastraxi's suggestion.
public class IconSwitcher extends LinearLayout{
public IconSwitcher(Context context) {
super(context);
ProgressBar pb = new ProgressBar(context);
ImageView iv = new ImageView(context);
addView(iv);
addView(pb);
}
}
This is my class thus far. However, when I try and reference it with:
MenuItem refresh = (MenuItem)findViewById(R.id.main_menu_refresh);
IconSwitcher ic = (IconSwitcher) refresh.getActionView();
I get a null pointer error. on creating the IconSwitcher. The button XML is as follows:
<item
android:id="#+id/main_menu_refresh"
android:enabled="true"
android:icon="#drawable/refresh"
android:orderInCategory="1"
android:showAsAction="ifRoom"
android:title="#string/refresh"
android:actionViewClass="IconSwitcher">
</item>
I'm just having a difficult time on referencing that IconSwitcher View.
Edit 2: I'm appearantly having trouble referencing the Menu Item at all.
MenuItem refresh = (MenuItem)findViewById(R.id.main_menu_refresh);
refresh.setVisible(false);
Also gives me a null pointer when I try and set the visibility. What is wrong with my references?

Instead of setting your action view class to a ProgressBar, set it to a custom LinearLayout class, as such:
class MyViewItem extends LinearLayout
Add a ProgressBar and an ImageView as children in its constructor with addView, and set these childrens' visibilities as either GONE or VISIBLE when your code requires it.

Try to use:
<item
android:id="#+id/main_menu_refresh"
android:enabled="true"
android:icon="#drawable/refresh"
android:orderInCategory="1"
android:title="#string/refresh"
app:showAsAction="ifRoom"
app:actionViewClass="android.widget.ProgressBar">
</item>
Note this two lines:
app:showAsAction="ifRoom"
app:actionViewClass="android.widget.ProgressBar"

Did you try to fetch your menu item like this?
MenuItem item = getToolbar().getMenu().findItem(Menu.FIRST);

Related

Ripple effect of TextView gets stuck on long click, when selection is used

I recently refactored my App to use the jetpack navigation. On my MainActivity, I had a ViewPager containing 3 fragments with 1 recyclerview each. I therefore moved the ViewPager from the Activity to a new Fragment. Everything works when it comes to the functionality itself, but a new issue arose which really bugs me: When I select an item on the recyclerview with a long press, the ripple effect gets stuck and stays there, as if I'm still pressing the item, which I don't. Here is a picture of a selected item. As it can be seen, the ripple effect stays active on the TextView.
When I unselect the Item, the ripple effect also stays active:
The selection itself is handled with the android SelectionTracker. The TextView has the background set to background="?android:attr/selectableItemBackground". The whole ViewItem has the background set to android:background="#drawable/bg_multi_selection, whereas the bg_multi_selection file looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/secondaryLightColor" android:state_activated="true" />
<item android:drawable="#android:color/transparent" />
</selector>
What could be the issue of that? This is especially weird, as the problem did not exist, when the ViewPager with its fragments was contained inside the Activity, and not a Fragment. Any suggestions on how to fix this?
I found a solution which works for me. So for anyone interested, I did the following:
In the recyclerviewadapter in the onBindViewHolder() method I check if the element is selected and additionally set the background color and background resource of the TextView programmatically.
if (elementIsSelected) {
viewHolder.viewBinding.itemTextView.setBackgroundColor(context.resources.getColor(R.color.transparent, context.theme))
} else {
val outValue = TypedValue()
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, outValue, true)
viewHolder.viewBinding.itemTextView.setBackgroundResource(outValue.resourceId)
}
whereas I definied the color to be transparent, i.e. #00000000
It's odd that this problem occurs only on some devices, so I'm not sure if the "real" problem lies somewhere else, but at least that's how I fixed it. Hope that might be helpful for someone else.

the setting options in another activity

in my app on the top right of the action bar, I have the setting as three dots (as the usual setting). but when I click on it, it shows a white rectangle that has the word "setting" on it! But I don't want that!! I want just the three dots and when I click it I want it to take me to another activity right away(without showing the option setting on a rectangle).
this my code for the setting xml:
<item
android:id="#+id/action_settings"
android:orderInCategory="0"
android:title="#string/action_settings"
android:textColor="#color/colorBackground"
app:showAsAction="never" />
</menu>
The three dots you're talking about are usually there if you don't have enough room in your action bar and you want some of your menu items to show in a menu instead of directly displaying it to the action bar. The best thing for you is to create another item and set app:showAsAction to always and call a method using onOptionsItemSelected event:
<item
android:id="#+id/your_id"
android:title="your title"
app:showAsAction="always" />
Call it like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.your_id:
//code here...
}
return super.onOptionsItemSelected(item);
}
Currently your app has a default menu that has a settings item added. You can create your own menu options.
Create a new menu.xml file that contains 1 item whose image is the three dots.
In your class, inside the onOptionsItemSelected method, call the activity that you want to open.
Hope this helps :)

Solving the mystery of preserving selected states on views in ListView

Not surprising I found myself looking at a tablet-optimized design one day that showed a pane with search results on the left side and a pane to display corresponding details on the right. The results on the left pane had a selected state to indicate which details were currently shown. What seemed to be a walk in the park ended up being a tiresome journey of trial and error. But finally I managed to get it working and I removed all irrelevant test-code only to discover it had stopped working straight away. I reintroduced the "irrelevant" part and surprisingly it worked as planned.
Client happy, designer happy, but not me, because I still don't understand why it works as it does.
I have a fragment that has a ListView with choiceMode set to ListView.CHOICE_MODE_SINGLE.
The adapter inflates custom views for each result and sets a drawable as background (happens in code)
The drawable is a selector wrapped in a RippleDrawable and has checked and activated states with a drawable for the selected state that needs to be preserved.
The custom view overrides setSelected(boolean selected) and dependent on the boolean adds or removes a view that has the selected state.
Now my problem is 3 & 4. Having the checked and activated states (step 3) ensures that setSelected(true) gets called when the view is tapped, but not immediately gets called again with setSelected(false) once the touchDown ends and thus the view I set in step 4 stays.
I had however expected I didn't need this custom view from step 4 as I thought it would use the drawable for the activated state from step 3. Removing the custom (thus unrelated to Android states system) view from step 4 has the effect that the state drawable from step 3 does show up, but only during onPress (touchDown/Hold) and... on the previous selected item!
Item Background
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/light_gray">
<item android:drawable="#drawable/search_result_selector" />
</ripple>
Selector Drawable (search_result_selector)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/white_selected" android:state_selected="true"/>
<item android:drawable="#color/white_selected" android:state_pressed="true"/>
<item android:drawable="#drawable/search_result_highlighted_state" android:state_activated="true"/>
<item android:drawable="#drawable/search_result_highlighted_state" android:state_checked="true"/>
<item android:drawable="#color/white"/>
</selector>
setSelected(selected) on custom view used for items in ListView
#Override
public void setSelected(boolean selected) {
super.setSelected(selected);
if (selected && selectedView == null) {
selectedView = new View(getContext());
selectedView.setBackground(Utils.getDrawable(getContext(), R.drawable.action_bar_background));
RelativeLayout.LayoutParams lp = new LayoutParams(Utils.pxFromDp(getContext(), 3), getHeight());
lp.addRule(ALIGN_PARENT_RIGHT);
addView(selectedView, lp);
} else if (!selected && selectedView != null) {
removeView(selectedView);
selectedView = null;
}
}
selectedView is a field I defined in my custom view class. I understand why it works, but I wonder why I need it as I expected the state drawable to be used correctly and preserve selection. The strange thing is when I remove that part, the ListView decides to do use the drawable, but on the previous selected view and only during touchDown. Now why would the presence of a custom implementation, not tied to any Android API influence the working of Android's view states? Apparently it is tied somehow, somewhere, but I fail to see where. Any pointers to the why behind this all would put my mind at ease. Thank you in advance!
EDIT
Apparently one of my conclusions was wrong. setSelected(false) was called, even with the states in the selector. Which makes sense perhaps if activated is the state that matters. I moved the code to an overriden method on setActivated, which does in fact show my custom view. That said the weirdness remains... the state drawable don't work as expected.

Android: Change icon of action share item on Action Bar

I understand that this question has been asked here many times but after of spending hours searching for the solution I am unable to find one.
My requirement simple, I just want to change share icon on Action Bar to white color. I've the white drawables and using built-in Action Bar.
have tried setting icon in menu xml but didn't work. Any help would be appreciated.
<item
android:id="#+id/action_share"
android:actionProviderClass="android.widget.ShareActionProvider"
android:showAsAction="ifRoom"
android:icon="#drawable/ic_action_share_white"
android:title="#string/action_share"/>
Take a look at the ShareActionProvider's onCreateActionView() method:
public View onCreateActionView() {
// Create the view and set its data model.
...
// Lookup and set the expand action icon.
TypedValue outTypedValue = new TypedValue();
mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId);
...
So, to change this image, it looks like you should change the value of actionModeShareDrawable for your app's theme. Unfortunately this attribute seems not to be public in the framework (though it is if using AppCompat or ActionBarSherlock).
If you are using neither of these libraries, a possible solution is to create a subclass of ShareActionProvider and reimplement the onCreateActionView() method (though you'll have to duplicate its code and, possibly, the resources it uses).

How to use my own custom EditText layout as a searchView

I have just starting using an ActionBar, everything is well apart from the search box. I am now wanting to use a SearchView but have found it to be hard to customize, is there a way to use my existing EditText based layout in place of the expandable SearchView?
The top one is the new SearchView and the bottom is my old one which I would like to use, I am not worried about any extras like autocomplete.
I have looked on google for some time but cannot find any solution, my XML for the menu looks like so :
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/btnSearch"
android:title="Search"
android:icon="#drawable/ic_action_search"
android:showAsAction="always|collapseActionView"
android:actionViewClass="android.widget.SearchView"
android:queryHint="blah blah"/>
...
</menu>
I have found that I can get the bottom line to look similar to my old search box by using some ugly looking reflection code, however it still does not look right, the padding etc is all wrong. I don't want any reflection, I just want to use my old layout.
I found something that could solve your problem:
http://www.techrepublic.com/blog/software-engineer/pro-tip-customize-the-android-search-view-widget/#.
I wrote this class to help with SearchView customization:
https://gist.github.com/jaredrummler/c408c9d897fd92d5d116
You could do something like this after inflating the menu in onCreateOptionsMenu:
SearchViewStyle.on(menu, R.id.your_search_id)
.setSearchPlateDrawableId(R.drawable.your_edit_text);

Categories

Resources