I have an item in my actionbar that shows a progressbar when clicked. However, when the user clicks the progressbar, I want the progress bar to stop, and show the normal "refresh" button again. Currently the progressbar become unclickable. Here's my code:
case R.id.id_Refresh:;
menuItem = item;
if(btnRefreshPressed == true){
menuItem.setActionView(R.layout.progressbar);
menuItem.expandActionView();
btnRefreshPressed = false;
mUpdateMap.run();
return true;
}else if(btnRefreshPressed == false){
menuItem.collapseActionView();
menuItem.setActionView(null);
mHandler.removeCallbacks(mUpdateMap);
btnRefreshPressed = true;
return true;
}
progressbar.xml:
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/progressbar2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true" >
</ProgressBar>
when you use your own actionView, you need to handle the clicking on the view itself:
menuItem.getActionView().setOnClickListener(...);
also, instead of having 2 modes , one with actionView and another without, you can use viewSwitcher as the actionView , and just toggle it when you want , by using showNext().
EDIT: for easiest way to support clicking on action bar items, no matter if they contain an actionView or not, you can use this code:
public static void setOnMenuItemSelected(final MenuItem menuItem, final Runnable runnable) {
final View view = menuItem.getActionView();
if (view != null)
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(final View v) {
runnable.run();
}
});
else
menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(final MenuItem item) {
runnable.run();
return true;
}
});
}
You are not passing in the ID:
findViewById(com.example.androidbasic12.R.layout.progressbar);
it should be R.id.YourID not R.layout.progressbar
That's why you get a NullPointerException
Related
I have an interesting problem - though maybe it is the expected behavior? I have a SearchView in my tool bar, which functions just fine till I enter a search then close it, at which time the search icon disappears and the ability to do another search is lost.
This behavior only happens when the search query is initiated - so if I enter search text, clear the search, then close it, the icon is there. But if I close it with data in it, then the Icon disappears. It is not the text color - I have clicked away and nothing seems to be there.
Here are some pictures of what I am talking about:
Search is there:
Enter search, query:
Close SearchView, icon gone
Menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/library_forms_refresh"
android:orderInCategory="100"
android:showAsAction="always|withText"
android:icon="#drawable/ic_action_refresh"
android:title="refresh"/>
</menu>
The code looks like this:
import android.widget.SearchView;
#Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
menu.clear();
mMenu = menu; // remember so we can get to later.
inflater.inflate(R.menu.library_forms, menu);
(removed some code not related to this)
// Implementing ActionBar Search inside a fragment
MenuItem item = menu.add("Search");
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
sv = new SearchView(getActivity());
// If we are on a Phone, make the search an icon, otherwise show it all
if (GlobalState.getInstance().isTwoPane == true) {
sv.setIconifiedByDefault(false);
}
else {
sv.setIconifiedByDefault(true);
}
sv.setFocusable(false);
// modifying the text inside edit text component
int id = sv.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
TextView textView = (TextView) sv.findViewById(id);
textView.setHint("Form or Reference Number");
textView.setHintTextColor(Color.WHITE);
textView.setTextColor(Color.WHITE);
// Change the Icon color
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int searchButtonId = sv.getContext().getResources().getIdentifier("android:id/search_button", null, null);
ImageView searchButton = (ImageView) sv.findViewById(searchButtonId);
searchButton.setImageTintList(ColorStateList.valueOf(Color.WHITE));
}
// implementing the listener
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
Handler handler = new Handler();
#Override
public boolean onQueryTextSubmit(String s) {
handler.removeCallbacksAndMessages(null);
if (s != null && s.trim().length() > 0)
{
searchFilter = s;
// Delay the lookup by 800 ms
handler.postDelayed(new Runnable() {
#Override
public void run() {
// do some stuff here...
}
}, 800);
}
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
// If the string is empty, reload the form
if (newText == null || newText.trim().length() == 0)
{
searchFilter = null;
// do some stuff here...
// Hides the soft keyboard
sv.setVisibility(View.INVISIBLE);
sv.setVisibility(View.GONE);
}
else {
onQueryTextSubmit(newText);
}
return true;
}
});
item.setActionView(sv);
}
The problem was this code:
// do some stuff here...
// Hides the soft keyboard
sv.setVisibility(View.INVISIBLE);
sv.setVisibility(View.GONE);
Which hid the keyboard and the icon.
I have an EditText in expandable action view in Toolbar. When I expand the action, the EditText is shown and I want it to get focus. To achieve that I do following:
action_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="#+id/connections_find_people_container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<EditText
android:id="#+id/connections_find_people_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"/>
</RelativeLayout>
In my fragment
#Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.add_connection, menu);
mAddMenuItem = menu.findItem(R.id.menu_add);
MenuItemCompat.setActionView(mAddMenuItem, R.layout.action_layout);
mSearchView = MenuItemCompat.getActionView(mAddMenuItem);
mSearchEditText = (EditText) mSearchView.findViewById(R.id.connections_find_people_edit);
MenuItemCompat.setOnActionExpandListener(mAddMenuItem, mOnSearchExpandListener);
super.onCreateOptionsMenu(menu, inflater);
}
private final OnSearchExpandListener mOnSearchExpandListener = new MenuItemCompat.OnActionExpandListener {
mSearchEditText.requestFocus();
return true;
}
#Override
public boolean onMenuItemActionCollapse(final MenuItem item) {
return true;
}
}
Surprisingly, this does not work. After tapping the action in toolbar, the view expands, mSearchEditText is shown, but doesn't get focus.
More specifically (and weirdly), mSearchEditText.requestFocus(); returns true, but software keyboard is still not shown and there is no cursor in mSearchEditText.
Showing software keyboard is not a big deal, there are ways to force it, but even when I show the keyboard, typing doesn't insert any text into mSearchEditText. It's only after I tap on mSearchEditText when cursor appears and I can type some text in it.
What I've tried:
Setting focusable and focusableInTouchMode both in XML and programatically and both in onCreateOptionsMenu() and when the action view is expanded
Clearing focus before requesting it like mSearchEditText.clearFocus()
Delaying requestFocus() after the view expands
It's really weird, because following
#Override
public boolean onMenuItemActionExpand(final MenuItem item) {
mSearchEditText.setFocusableInTouchMode(true);
mSearchEditText.setFocusable(true);
mSearchView.postDelayed(new Runnable() {
#Override
public void run() {
if (mSearchEditText.requestFocus()) {
KeyboardUtils.showSoftKeyboard(ConnectionsFragment.this);
}
}
}, 300);
return true;
}
shows the keyboard, which should mean mSearchEditText has focus, but typing doesn't enter any text. (Again, when I tap on the EditText, cursor appears and everything works fine).
Aaand as it happens sometimes, soon after posting the question I found the answer myself.
Instead of getting reference to the EditText in onCreateOptionsMenu() I had to use the MenuItem passed to onMenuItemActionExpand() and get the reference there.
So this now works for me:
#Override
public boolean onMenuItemActionExpand(final MenuItem item) {
final View actionView = MenuItemCompat.getActionView(item);
final View edit = actionView.findViewById(R.id.connections_find_people_edit);
if(edit.requestFocus()) {
KeyboardUtils.showSoftKeyboard(ConnectionsFragment.this);
}
return true;
}
Bellow mentioned is the code where i am registering framelayout for long click listener event.
private void createActivityLayout(Fragment fragment)
{
FrameLayout frameLayout = (FrameLayout)getLayoutInflater().inflate(R.layout.professional_pa_frame_layout, null, false);
frameLayout.setClickable(true);
frameLayout.setOnLongClickListener(new View.OnLongClickListener()
{
public boolean onLongClick(View view)
{
if (actionMode == null)
{
return false;
}
actionMode = view.startActionMode(actionModelCallback);
view.setSelected(true);
return false;
}
});
getFragmentManager().beginTransaction().add(id, fragment, tag).commit();
}
The fragment internally contains a series of edittext instances or a single imageview instances.
Whenever a long click is performed on framelayout, i guess the contextual action bar for edittext is displayed. I think the event is captured by editext and different contextual action bar is displayed. PFA image of the contextual action bar displayed whenever i get a long click event inside framelayout.
How can i capture long click event on my framelayout as a whole without displaying contextual action bar for its internal views. xml code written below is of the contextual action bar that i want to be displayed for my framelayout.
<item android:id="#+id/action_discard_notes"
android:icon="#drawable/discard_note"
android:title="#string/action_discard_notes"
android:showAsAction="always"
android:orderInCategory="1"/>
You need to set ActionModeCallback of Edittext so CAB aborted and call Framelayout long click like below code...
m_editText.setCustomSelectionActionModeCallback(new Callback()
{
#Override
public boolean onCreateActionMode(android.view.ActionMode p_mode, Menu p_menu)
{
return false;
}
#Override
public boolean onPrepareActionMode(android.view.ActionMode p_mode, Menu p_menu)
{
return false;
}
#Override
public void onDestroyActionMode(android.view.ActionMode p_mode)
{
}
#Override
public boolean onActionItemClicked(android.view.ActionMode p_mode, MenuItem p_item)
{
return false;
}
});
You need to return false in onCreateActionMode for abort CAB(contextual action bar).
I try to animate a MenuItem for ActionBar with an action view in a way simular to ActionBarHelper for Honeycomb to have a rotative refresh button. But I have 2 troubles :
When I display action view, width of item is smaller than MenuItem (see part 1 and 2 of screenshot)
When I want to stop animation and return to default MenuItem state via setActionView(null), my action view is still displayed inside my MenuItem (part 3 of screenshot)
Different steps of MenuItem (Screenshots)
ActionView Layout (R.layout.menu_item_refresh) is :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_menu_refresh" />
</LinearLayout>
onOptionsItemSelected methods code is :
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
default:
return super.onOptionsItemSelected(item);
case R.id.Menu_Feed_Refresh:
mAnimatedItem = item;
item.setActionView(R.layout.menu_item_refresh);
item.startAnimation(mAnimation);
load();
return true;
}
}
When load finished, I call an handler mAnimatedItem.setActionView(null)
if i undestood your code right, you apply animation to MenuItem. you delete ActionView by setActionView(null), but menuItem animates.
you need to get image from ActionView and apply animation to it:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
default:
return super.onOptionsItemSelected(item);
case R.id.Menu_Feed_Refresh:
mAnimatedItem = item;
item.setActionView(R.layout.menu_item_refresh);
ImageView iv = (ImageView) item.getActionView().findViewById(R.id.refresh_image_id);
iv.startAnimation(mAnimation);
load();
return true;
}
}
Call mAnimation.clearAnimation() when you want to stop.
Android Can anyone know about Actionbar item options long click , I want to show text on LongClick on actionbar menu option like a hint on long press of actionBar long press
Do you want to capture long press on menu item on action bar? As for me, after finding 2,3 hour, I found this solution. This is perfectly work for me.
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
new Handler().post(new Runnable() {
#Override
public void run() {
final View v = findViewById(R.id.action_settings);
if (v != null) {
v.setOnLongClickListener(new CustomLongOnClickListener());
}
}
});
return true;
}
For me, the following approach works fine for newer Android versions - I tested it with Android 4.2 and Android 5.0.1.
The idea is that I replace the action icon view by a custom view. Here, I have to handle the single click, and I can handle the long click.
If I want the appearance to be exactly like normal action bar icons, the following works.
First, create a layout containing just an ImageButton with your icon.
<?xml version="1.0" encoding="utf-8"?>
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/myButton"
style="?android:attr/actionButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#layout/text_view_initializing"
android:src="#drawable/ic_action_plus" />
Then put this ImageButton into the action bar and attach listeners to it.
MenuItem myItem = menu.findItem(R.id.my_action);
myItem.setActionView(R.layout.my_image_button);
myItem.getActionView().setOnClickListener(new OnClickListener() {
#Override
public void onClick(final View v) {
// here, I have to put the stuff that normally goes in onOptionItemSelected
}
});
myItem.getActionView().setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(final View v) {
// here, I put the long click stuff
}
});
Important remark: this will only work if the item appears in the action bar. So, whatever you want to do on long click will not be accessible in this way if the option appears in the menu dropdown.
user1206890, you do not need listen long click event. If you want show action hint, will be sufficient set title in menu add. Checked on 2.3 and 4.0.
If you create your own action view via android:actionLayout, you are welcome to set up listeners on your own widgets for long-click events. You do not have access to widgets in the action bar that you do not create yourself.
I think "findViewById" is the easiest way to find.
Just do
View action_example = findViewById(R.id.action_example);
if(action_example!=null)action_example.setOnLongClickListener(
new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(MainActivity.this, "action_example", Toast.LENGTH_SHORT).show();
return true;
}
}
);
This is the code of function that works with me thanks to #YeeKhin
change "main" to your menu name and "action_refresh" to your action name and "Activity" to your activity name
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
new Handler().post(new Runnable() {
#Override
public void run() {
final View v = findViewById(R.id.action_refresh);
if (v != null) {
v.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(Activity.this,"Long Press!!",Toast.LENGTH_LONG).show();
return false;
}
});
}
}
});
return true;
}