I have a collapsed search EditView menu within my Actionbar (ActionbarSherlock). When setShowAsAction method is set to SHOW_AS_ACTION_NEVER, the keyboard displays and the user can start typing, as expected.
However when I set the value to SHOW_AS_ACTION_ALWAYS, the user has to touch the EditText before they start typing as it doesn't appear to have focus!
Is there something wrong with my code or a way to work around this problem?
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
final MenuItem search = menu.add(0, MENU_SEARCH, MENU_SEARCH, getString(R.string.search));
search.setIcon(R.drawable.ic_action_search);
search.setActionView(R.layout.action_search);
search.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_SEARCH:
mSearch = (EditText) item.getActionView();
mSearch.addTextChangedListener(mFilterTextWatcher);
mSearch.requestFocus();
mSearch.postDelayed(new Runnable() {
#Override
public void run() {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
}, 200);
break;
}
return true;
}
action_search.xml
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:hint="#string/search" />
The solution was to nest the fragment within the Activity.
public class ProductListActivity extends SherlockFragmentActivity {
…
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
ProductListFragment list = new ProductListFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, list).commit();
}
}
public static class ProductListFragment extends SherlockListFragment {
…
}
}
Related
I have created a fragment with action bar menu, that menu was shown but not working when its clicked.
Here is My Fragment:
public class ComposeFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_compose, container, false);
userName = (TextView) view.findViewById(R.id.user_name);
subjectSpinner = (Spinner) view.findViewById(R.id.subject_spinner);
sendButton = (Button) view.findViewById(R.id.send_btn);
messageEditText = (EditText) view.findViewById(R.id.message);
userName.setText(Ezcation.getInstance().userName);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.compose_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.e("Menu","Before Switch");
switch (item.getItemId()){
case R.id.sent:
Log.e("Menu","Sent");
if (messageEditText.getText().toString().equals("")){
messageEditText.setError("Please Enter your Message");
}else {
sendMessage(messageEditText.getText().toString());
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.messageActivity = (MessageActivity) context;
SpannableString s = new SpannableString("Compose Message");
s.setSpan(new TypefaceSpan(messageActivity, "Miller-Text.ttf"), 0, s.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
messageActivity.setTitle(s);
}
}
When menu was clicked even Log.e("Menu","Before Switch"); not working.
My Menu xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/sent"
android:title="Sent"
android:orderInCategory="10"
android:icon="#drawable/sent"
app:showAsAction="ifRoom" />
</menu>
For Future visiters you should use this in Activity class:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
To work properly hardcoding false isnt the right way
add this in your Activity.
#Override public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
break;
}
return super.onOptionsItemSelected(item);;
}
The super call is missing inside onCreateOptionsMenu
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.compose_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
In my sign in activity I added a method that set a border for the edit text if it is focusable so that the user can know that he is entering data in this field and the border will be highlighted...but when the activity start, the method directly is applied on the first username edit text knowing that I'm hiding the keyboard...I want this method to work when the keyboard appears not before.Thank you of helping me...This is my code
Java
public class FoodSafetyLogIn extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_food_safety_log_in);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setCustomView(R.layout.t1_layout);
//Hide Keyboard
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
EditText username = (EditText) findViewById(R.id.input_username);
focus(username);
EditText password = (EditText) findViewById(R.id.input_password);
focus(password);
password.setTypeface(Typeface.DEFAULT);
}
#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_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_back) {
Intent i = new Intent(FoodSafetyLogIn.this, MainActivity.class);
startActivity(i);
overridePendingTransition(R.animator.slide_in_right,R.animator.slide_in_right);
return true;
}
return super.onOptionsItemSelected(item);
}
public void OnClick(View view){
}
public void focus(View view){
view.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
v.setBackgroundResource(R.drawable.focus_border_style);
else
v.setBackgroundResource(R.color.colorPrimary);
}
});
}
}
This is an example:
<LinearLayout
android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
your edit text... />
Add this tag in your EditView
android:focusableInTouchMode="true"
I want to set custom search layout in Toolbar Menu. My problem is when I setting expand listener to the search item - the action view is not expanding anymore.
I tryed to call
item.expandActionView();
MenuItemCompat.expandActionView(item);
in onOptionsItemSelected, but it doesn`t work.
My Code:
menu_projects.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_search"
android:actionLayout="#layout/search_layout"
android:icon="#android:drawable/ic_menu_search"
android:title="#string/search"
app:showAsAction="always|collapseActionView"/>
</menu>
search_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/searchEditText"
android:layout_width="match_parent"
android:layout_height="38dp"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:layout_toLeftOf="#+id/closeSearchImageView"
android:layout_toStartOf="#+id/closeSearchImageView"
android:background="#null"
android:hint="#string/search"
android:imeOptions="flagNoExtractUi"
android:inputType="textCapSentences"
android:paddingLeft="10dp"
android:paddingRight="5dp"
android:singleLine="true"
android:textColor="#android:color/white"
android:textColorHint="#7dffffff"
android:textCursorDrawable="#drawable/cursor"/>
<ImageView
android:id="#+id/closeSearchImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:padding="3dp"
android:src="#drawable/abc_ic_clear_mtrl_alpha"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_below="#+id/searchEditText"
android:background="#7dffffff"/>
</RelativeLayout>
inside fragment
#Override
public void onPrepareOptionsMenu(Menu menu) {
searchViewExpandCollapse = new SearchViewExpandCollapse(menu);//fragment field
super.onPrepareOptionsMenu(menu);
}
private class SearchViewExpandCollapse implements MenuItemCompat.OnActionExpandListener
{
private Menu menu;
public SearchViewExpandCollapse(Menu menu) {
this.menu = menu;
MenuItem searchItem = menu.findItem(R.id.action_search);
MenuItemCompat.setOnActionExpandListener(searchItem, this);//action view not expanding with this
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return false;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
return false;
}
}
Any ideas?
I found the solution. First of all I set ActionView to MenuItem programmaticaly after setting listener. And after that I changed return value on listener methods from false to true. Maybe will be helpfull for someone.
Full code:
#Override
public void onPrepareOptionsMenu(Menu menu) {
searchController = new SearchViewExpandCollapse(menu);
if (!query.isEmpty()) {
searchController.expandActionView();
searchController.setQuery(query);
}
super.onPrepareOptionsMenu(menu);
}
private class SearchViewExpandCollapse implements MenuItemCompat.OnActionExpandListener, OnClickListener
{
private final EditText editText;
private final MenuItem searchItem;
private Menu menu;
private View searchView;
public SearchViewExpandCollapse(Menu menu) {
this.menu = menu;
searchItem = menu.findItem(R.id.action_search);
MenuItemCompat.setOnActionExpandListener(searchItem, this);
searchItem.setActionView(R.layout.search_layout);
searchView = searchItem.getActionView();
editText = (EditText) searchView.findViewById(R.id.searchEditText);
editText.addTextChangedListener(textWatcher);
searchView.findViewById(R.id.closeSearchImageView).setOnClickListener(this);
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
menu.setGroupVisible(R.id.main_group, false);
editText.requestFocus();
editText.post(new Runnable()
{
#Override
public void run() {
InputMethodManager imm = (InputMethodManager) getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
}
});
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
menu.setGroupVisible(R.id.main_group, true);
editText.clearFocus();
InputMethodManager inputManager = (InputMethodManager) getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
return true;
}
private TextWatcher textWatcher = new TextWatcher()
{
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
query = s.toString();
searchAdapter.getFilter().filter(query);
}
};
public void expandActionView() {
searchItem.expandActionView();
}
public void setQuery(String query) {
editText.removeTextChangedListener(textWatcher);
editText.setText(query);
editText.setSelection(query.length());
editText.addTextChangedListener(textWatcher);
}
public void onClick(View v) {
if (editText.getText().length() != 0) {
editText.setText("");
} else {
searchItem.collapseActionView();
}
}
}
In case anyone else finds this later on having the same problem (like me) the issue is here:
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return false;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
return false;
}
by returning false you override the original action of the menu item. This should instead be:
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
//what you want to do
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
//what you want to do
return true;
}
I have an ActionBarActivity and one Fragment. The Activity has no menu inflated, while the Fragment has a menu with two buttons. Fragment menu is visible, but the buttons don't react at all when tapped. At debugging I can see that both onCreateOptionsMenu() for Fragment and Activity get called, but when tapping buttons no onOptionsItemSelected() gets called, neither from Activity nor from Fragment.
Activity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return false;
}
Fragment
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity = (NavigationActivity)getActivity();
setHasOptionsMenu(true);
}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState){
return (ScrollView) inflater.inflate(R.layout.tutoring_detail, container, false);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.query_details_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.accept_query:
respondToQuery(true);
return true;
case R.id.decline_query:
respondToQuery(false);
return true;
default:
break;
}
return false;
}
Menu to be displayed in Fragment
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<item
android:id="#+id/accept_query"
android:orderInCategory="100"
app:showAsAction="always"
android:checkable="true"
style="?android:attr/borderlessButtonStyle"
app:actionViewClass="android.widget.ImageButton"/>
<item
android:id="#+id/decline_query"
android:orderInCategory="101"
app:showAsAction="always"
android:checkable="true"
style="?android:attr/borderlessButtonStyle"
app:actionViewClass="android.widget.ImageButton"/>
</menu>
In the Activity class,
#Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
return false;
}
In the Fragment,
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(getActivity(), "called " + item.getItemId(), Toast.LENGTH_SHORT).show();
return super.onOptionsItemSelected(item);
}
You must use super.onOptionsItemSelected(item) in the parent activity's onOptionsItemSelected(...) method.
From Activity | Android Developers:
Derived classes should call through to the base class for it to perform the default menu handling.
Try moving setHasOptionsMenu(true) inside of the onCreateView() method in your Fragment instead of onCreate().
I had a similar issue after making special layout for my action button (I made an Image Button and needed to pad it and change some other things so I had to use layout for it).
Then onOptionsItemSelected lost connection with this imageButton so I just use clickListener for it inside onCreateOptionsMenu. It might not be the best practice, maybe there is a better solution, but this is what solve my problem.
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.picker_list_menu, menu);
MenuItem itemDone = menu.findItem(R.id.menu_done);
MenuItemCompat.setActionView(itemDone, R.layout.menu_layout_done);
menuDoneIB = (ImageButton) MenuItemCompat.getActionView(itemDone);
itemDone.getActionView().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//your code..
}
});
}
Try using oncreateview
public static class ExampleFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
If you have dynamically changed menu item, for instance, a badge menu (https://stackoverflow.com/a/16648170/2914140 or https://stackoverflow.com/a/26017587/2914140), you should initialize the item in onCreateOptionsMenu and re-set setOnClickListeners after every change of the item.
In my case:
private MenuItem menuItem;
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_catalog, menu);
menuItem = menu.findItem(R.id.action_badge);
writeBadge(0);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_badge) {
// Your code.
return true;
}
return super.onOptionsItemSelected(item);
}
private void writeBadge(int count) {
MenuItemCompat.setActionView(menuItem, R.layout.item_badge);
RelativeLayout layout = (RelativeLayout) MenuItemCompat.getActionView(menuItem);
// A TextView with number.
TextView tv = (TextView) layout.findViewById(R.id.badge);
if (count == 0) {
tv.setVisibility(View.INVISIBLE);
} else {
tv.setVisibility(View.VISIBLE);
tv.setText(String.valueOf(count));
}
// An icon, it also must be clicked.
ImageView imageView = (ImageView) layout.findViewById(R.id.image);
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
onOptionsItemSelected(menuItem);
}
};
menuItem.getActionView().setOnClickListener(onClickListener);
imageView.setOnClickListener(onClickListener);
}
I am passing the click event to fragment from the activity. This worked for me.
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
return getSupportFragmentManager().getFragments().get(getSupportFragmentManager().getFragments().size() - 1)
.onOptionsItemSelected(item);
}
I would like to add a badge over ActionBar MenuItem
But the digit icon didn't shows.
Here's what I have done so far
public class Main extends SherlockFragmentActivity
{
private Fragment menuFrag=null;
private MenuItem menuMsg=null;
private BadgeView badge=null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
//Do my stuff...
initUI();
}
private void initUI()
{
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
menuFrag=fm.findFragmentByTag("f1");
if(menuFrag==null)
{
menuFrag=new MenuFragment();
ft.add(menuFrag, "f1");
}
ft.commit();
// badge=new BadgeView(Main.this, (View)menuMsg); //Not working
badge=new BadgeView(Main.this, menuMsg.getActionView()); //Not working as well
badge.setBackgroundResource(R.drawable.badge_ifaux);
badge.setTextSize(10);
badge.setBadgeMargin(2);
badge.setText("1");
badge.show();
}
private class MenuFragment extends SherlockFragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
menu.add("Cloud").setIcon(R.drawable.icon_cloud).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add("List").setIcon(R.drawable.icon_list).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menuMsg=menu.add("Msg");
menuMsg.setIcon(R.drawable.icon_msg).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
Toast.makeText(Main.this, "Got click: " + item.toString(), Toast.LENGTH_SHORT).show();
return true;
}
}
}
Where do I did wrong ?
RRTW,
The library you are using doesn't support badging Actionbar menu items natively.
https://github.com/jgilfelt/android-viewbadger/commit/e08c3a78cb92c0c8587790b15e73434f972912cf
However, it doesn't mean you can't get it to work.
The setup is going to be as follows (this assumes you already have the viewbager library setup in your project)
(1) onCreateOptionsMenu --> (2) Add a R.menu.your_place_holder_item --> (3) setActionView with custom xml layout --> (4) findViewById of the MenuItem object to get your button/view to set the badge.
1) setup your onCreateOptionsMenu and create a the R.menu.actionbar_menu_messages
R.menu.actionbar_menu_messages:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
>
<item android:showAsAction="ifRoom" android:icon="#drawable/action_bar_pk_content_email"
android:id="#+id/menuMessages" android:title="More"></item>
</menu>
onCreateOptionsMenu:
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getSupportMenuInflater(); //If you are using the support library otherwise use: getMenuInflater();
inflater.inflate(R.menu.actionbar_menu_messages, menu);
this.setupMessagesBadge(menu.findItem(R.id.menuMessages)); //This is part of step 2
return true;
}
2) Defined the common_messages_indicator
R.layout.common_messages_indicator:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="64dp"
android:layout_height="fill_parent"
android:paddingTop="10dp"
android:gravity="center">
<ImageView
android:id="#+id/imgMessagesIcon"
android:layout_width="32dp"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:src="#drawable/messages_button"
android:background="#android:color/transparent"
android:focusable="false"
/>
</FrameLayout>
perform setActionView to add your custom xml layout to the ActionView
private void setupMessagesBadge(final MenuItem msgItem) {
msgItem.setActionView(R.layout.common_messages_indicator);
if(msgItem.getActionView().findViewById(R.id.imgMessagesIcon) != null)
{
ImageView imgMessagesIcon = ((ImageView)msgItem.getActionView().findViewById(R.id.imgMessagesIcon));
imgMessagesIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Your click on the action bar item will be captured here
}
});
int badgeCnt = 20;// Add your count here
if(messageCenterBadge == null && badgeCnt > 0)
{
//imgMessagesIcon is the imageview in your custom view, apply the badge to this view.
messageCenterBadge = new BadgeView(this, imgMessagesIcon);
messageCenterBadge.setBadgePosition(BadgeView.POSITION_TOP_RIGHT);
messageCenterBadge.setBadgeMargin(0);
messageCenterBadge.setTextSize(12);
messageCenterBadge.setText(String.valueOf(badgeCnt));
messageCenterBadge.show();
}
else if(messageCenterBadge != null && badgeCnt > 0 )
{
messageCenterBadge.setText(String.valueOf(badgeCnt));
messageCenterBadge.show();
}
else if(messageCenterBadge != null && badgeCnt == 0) {
messageCenterBadge.hide();
}
}
}