Can anyone see why this is not working..
My SearchView is in the ActionBar and is always shown. I want to know when a user PRESSES the searchview... not when it expands or gains focus.
This code sits within onCreateOptionsMenu
SearchView = _searchView;
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
_searchView = (SearchView) menu.findItem(R.id.menu_finder_text_search).getActionView();
_searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
_searchView.setIconifiedByDefault(false); // Do not iconify the widget, we want to keep it open!
_searchView.setFocusable(false);
_searchView.setClickable(true);
_searchView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//DO SOMETHING!
}
});
Anyone?
SearchView is inherited from LinearLayout, so we can setOnClickListener for each child, like this:
public static void setSearchViewOnClickListener(View v, OnClickListener listener) {
if (v instanceof ViewGroup) {
ViewGroup group = (ViewGroup)v;
int count = group.getChildCount();
for (int i = 0; i < count; i++) {
View child = group.getChildAt(i);
if (child instanceof LinearLayout || child instanceof RelativeLayout) {
setSearchViewOnClickListener(child, listener);
}
if (child instanceof TextView) {
TextView text = (TextView)child;
text.setFocusable(false);
}
child.setOnClickListener(listener);
}
}
}
from: http://www.trinea.cn/android/searchview-setonclicklistener-not-working/
Ok, it does not answer the problem it only avoids it.
I have used this link to create a listener for when the keyboard is shown. This gives me an event at the right time for me.
https://stackoverflow.com/a/7423586/1312937
Try this:
1) Bind the view
#BindView(R.id.search) SearchView search;
2) In your onCreate(), write the following code.
search.setIconifiedByDefault(false);
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
search.setIconified(false);
}
});
3) And your SearchView should have this following attributes.
<SearchView
android:id="#+id/search"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:background="#drawable/rounded_corners_box"
android:drawableLeft="#android:drawable/ic_menu_search"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:queryHint="Search your item.."
android:textColor="#android:color/black"
android:textColorHint="#color/colorPrimary"
app:defaultQueryHint="Select locality"/>
NOTE:
android:background="#drawable/rounded_corners_box" -- your custom border xml file.
android:drawableLeft="#android:drawable/ic_menu_search" -- search icon from drawable file.
Bind the Searchviews button to a custom ImageView and add the onClickListener there
ImageView searchButton = this.searchView.findViewById(android.support.v7.appcompat.R.id.search_button);
searchButton.setOnClickListener(v -> {
// Your code here
//This is needed since you are overwriting the default click behaviour
searchView.setIconified(false);
});
Recently stuck with this problem and found a simple solution.
searchView.setOnQueryTextFocusChangeListener(object : View.OnFocusChangeListener{
override fun onFocusChange(p0: View?, p1: Boolean) {
// Enter your code here
}
})
This method will be called when you will tap on search field and soft keyboard will appear.
Use the interface OnTouchListener: http://developer.android.com/reference/android/view/View.OnTouchListener.html
This requires a tiny bit more implementation code, but gives superior control over the UI. This solution assumes the user will be using a touch screen to interact with the View.
int search_button_id = context.getResources().getIdentifier("android:id/search_button", null, null);
ImageView search_button_view = (ImageView) mSearchView.findViewById(search_button_id);
search_button_view.setOnTouchListener((view, motionEvent) -> {
mSearchView.setIconified(false);
return true;
});
Related
I am using a TextInputLayout with the new function from the Support Library: passwordToggleEnabled. This gives a nice "eye"-icon that lets the user toggle password visibility on and off.
My question is if there is a way to use this functionality but start with password visible?
My xml:
<android.support.design.widget.TextInputLayout
android:id="#+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:passwordToggleEnabled="true">
<EditText
android:id="#+id/password_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/prompt_password"
android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout>
The toggle looks similar to this:
I have not found a way to do this in xml, and not a way to manually toggle the visibility after the view is rendered. If I set the input type of the EditText to textVisiblePassword, the toggle is not shown. If I do it in code using for instance mPasswordEditText.setTransformationMethod(null); the password is shown but the toggle is gone and the user can't hide the password again. I know I can do it all manually but just wondering if I can make it work with the new magic toggle
Easiest way is below Another solution is at last of this answer
private void setupPasswordToggleView() {
final TextInputLayout textInputLayout = mRootView.findViewById(R.id.password);
// You can skip post-call and write directly the code which is inside run method.
// But to be safe (as toggle-view is child of TextInputLayout, post call
// has been added.
textInputLayout.post(new Runnable() {
#Override
public void run() {
CheckableImageButton passwordToggleView = textInputLayout.findViewById(R.id.text_input_password_toggle);
// passwordToggleView.toggle(); // Can not use as restricted to use same library group
// passwordToggleView.setChecked(true); // Can not use as restricted to use same library group
passwordToggleView.performClick();
}
});
}
Now let me explain the answer
While looking into code of TextInputLayout.java I found that, there is a layout design_text_input_password_icon.xml which is being added to TextInputLayout.java. Below is that code
private void updatePasswordToggleView() {
if (mEditText == null) {
// If there is no EditText, there is nothing to update
return;
}
if (shouldShowPasswordIcon()) {
if (mPasswordToggleView == null) {
mPasswordToggleView = (CheckableImageButton) LayoutInflater.from(getContext())
.inflate(R.layout.design_text_input_password_icon, mInputFrame, false);
mPasswordToggleView.setImageDrawable(mPasswordToggleDrawable);
mPasswordToggleView.setContentDescription(mPasswordToggleContentDesc);
mInputFrame.addView(mPasswordToggleView); // << HERE IS THAT
.........
}
Now next target was to find design_text_input_password_icon.xml and lookup id of the toggle view. So found the layout design_text_input_password_icon.xml here and it has written as
18<android.support.design.widget.CheckableImageButton
19 xmlns:android="http://schemas.android.com/apk/res/android"
20 android:id="#+id/text_input_password_toggle"
21 android:layout_width="wrap_content"
22 android:layout_height="wrap_content"
23 android:layout_gravity="center_vertical|end|right"
24 android:background="?attr/selectableItemBackgroundBorderless"
25 android:minHeight="48dp"
26 android:minWidth="48dp"/>
I found the id text_input_password_toggle of that view and now everything was easy to just find that view in it's viewgroup and perform action on that.
Another solution would be to iterate childs of TextInputLayout and check if it is CheckableImageButton and then perform click on it. By this way there would not be dependancy on id of that view and if Android changes the id of view, our solution will still work. (Although they do not change id of a view in normal cases).
private void setupPasswordToggleViewMethod2() {
final TextInputLayout textInputLayout = mRootView.findViewById(R.id.password);
textInputLayout.post(new Runnable() {
#Override
public void run() {
View toggleView = findViewByClassReference(textInputLayout, CheckableImageButton.class);
if (toggleView != null) {
toggleView.performClick();
}
}
});
}
Where findViewByClassReference(View rootView, Class<T> clazz) original utility class is defined as below
public static <T extends View> T findViewByClassReference(View rootView, Class<T> clazz) {
if(clazz.isInstance(rootView)) {
return clazz.cast(rootView);
}
if(rootView instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) rootView;
for(int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
T match = findViewByClassReference(child, clazz);
if(match != null) {
return match;
}
}
}
return null;
}
With the Material Components Library (1.1.0 , 1.2.0-beta01, 1.3.0-alpha01) to start with a visible password just use:
<com.google.android.material.textfield.TextInputLayout
app:endIconMode="password_toggle"
/>
and in your code:
textInputLayout.getEditText().setTransformationMethod(null);
If you want to return to the default behavior:
textInputLayout.getEditText()
.setTransformationMethod(PasswordTransformationMethod.getInstance());
Just removing android:inputType="textPassword" worked for me
One of the ways is, we can search CheckableImageButton from TextInputLayout, and then programmatically perform onClick on it, based on the password visibility status of EditText.
Here's the code snippet.
private CheckableImageButton findCheckableImageButton(View view) {
if (view instanceof CheckableImageButton) {
return (CheckableImageButton)view;
}
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0, ei = viewGroup.getChildCount(); i < ei; i++) {
CheckableImageButton checkableImageButton = findCheckableImageButton(viewGroup.getChildAt(i));
if (checkableImageButton != null) {
return checkableImageButton;
}
}
}
return null;
}
//...
if (passwordEditText.getTransformationMethod() != null) {
CheckableImageButton checkableImageButton = findCheckableImageButton(passwordTextInputLayout);
if (checkableImageButton != null) {
// Make password visible.
checkableImageButton.performClick();
}
}
I was able to get it to start in clear-text mode with the following bit of code. Basically, I had to find the right View using the content description.
If they provided a setter method for mPasswordToggledVisibility that would make things a lot easier...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextInputLayout til = findViewById(R.id.password);
CharSequence cs = til.getPasswordVisibilityToggleContentDescription();
ArrayList<View> ov = new ArrayList<>();
til.findViewsWithText(ov, cs,View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
if( ov.size() == 1 ) {
Checkable c = (Checkable)ov.get(0);
// As far as I can tell the check for "isChecked" here isn't needed,
// since it always starts unchecked by default. However, if you
// wanted to check for state, you could do it this way.
if( c != null && !c.isChecked()) {
ov.get(0).performClick();
}
}
}
try this
if (inputEditText.getTransformationMethod() == null) {
inputEditText.setTransformationMethod(new PasswordTransformationMethod());
} else {
inputEditText.setTransformationMethod(null);
}
inputEditText.setSelection(inputEditText.getText().length());
You can use the bellow code:
TextInputLayout yourTextInputLayoutId = findViewById(R.id.yourTextInputLayoutId);
FrameLayout frameLayout = (FrameLayout) (yourTextInputLayoutId).getChildAt(0);
CheckableImageButton checkableImageButton = (CheckableImageButton) frameLayout.getChildAt(1);
checkableImageButton.performClick();
Here yourTextInputLayoutId is your TextInputLayout id from xml.
To start with Password visible,
Do not include
android:inputType="textPassword"
In
<com.google.android.material.textfield.TextInputEditText>
....
</com.google.android.material.textfield.TextInputEditText>
You can add in your xml file in TextInputLayout
passwordToggleEnabled="true"
passwordToggleDrawable=""#drawable/show_password_selector"
and make your show_password_selector.xml
this will look the same as the picture you sent
You can use:
yourEditText.setTransformationMethod(new PasswordTransformationMethod());
To re-show the readable password, just pass null as transformation method:
yourEditText.setTransformationMethod(null);
so user can hide it again.
I have a problem with searchview implementation in android toolbar.
The empty space padding is too big.
I don't want to hide other actions, but these actions are
overlapped by SearchView.
SearchView's underline is not visible
How do i fix issues mentioned above ?
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<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:title="#string/car_num"
android:icon="#drawable/ic_search_white_24dp"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always" />
<item
android:id="#+id/action_add_client"
android:icon="#drawable/ic_account_multiple_plus"
android:title="#string/action_add_client"
app:showAsAction="always" />
</menu>
fragment
#Override
public void onCreateOptionsMenu(final Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_fragment_reg_vehicles, menu);
final MenuItem item = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setQueryHint("Search");
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(this);
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
#Override
public boolean onClose() {
setItemsVisibility(menu, item, true);
return false;
}
});
searchView.setOnSearchClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setItemsVisibility(menu, item, false);
searchView.requestFocus();
}
});
}
Regarding your posted code, this is the output:
As you can see, there is two left margins: the widget's container and the magnify icon. This is why you have an empty space bigger than an another window with a title. And the menu items are pushed outside the toolbar which, I think, it's the default SearchView ActionView when it's not a CollapseActionView so it fills the parent.
From the source of SearchView widget and its layout abc_search_view.xml, I tried to remove the extra margins and avoid pushing the other items outside the toolbar.
But after many manipulations, my guess is you have to use a custom widget and/or a custom layout. Or to play with setIconifiedByDefault(true) which removes the magnify icon and its extra margin and to use setMaxWidth(MAX_SIZE) where MAX_SIZE is calculated dynamically by Integer.MAX_VALUE - (SIZE_OF_A_MENU_ITEM * NB_OF_MENU_ITEMS)... But it requires a lot of work for nothing. So using a custom layout could be the solution.
However, there is a possible way to keep the appcompat widget, some little workarounds. First, to avoid puhsing out the other items, you can use the CollapseActionView.
<item
...
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always|collapseActionView"/>
And to maintain your requirements, you have to expand it when you initialize it:
final SearchView searchView =
(SearchView) MenuItemCompat.getActionView(item);
MenuItemCompat.expandActionView(item);
Be aware that you have to use setOnActionExpandListener() in order to close the window if you don't want to collapse the item. This suggestion will give you this result:
Still the extra margins, right? Therefore, you have to retrieve the container and the magnify icon by their ids (which you can find in abc_search_view.xml... but let's save some time: they are R.id.search_edit_frame and R.id.search_mag_icon). You can remove their margins by using this method:
private void changeSearchViewElements(View view) {
if (view == null)
return;
if (view.getId() == R.id.search_edit_frame
|| view.getId() == R.id.search_mag_icon) {
LinearLayout.LayoutParams p =
(LinearLayout.LayoutParams) view.getLayoutParams();
p.leftMargin = 0; // set no left margin
view.setLayoutParams(p);
}
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
changeSearchViewElements(viewGroup.getChildAt(i));
}
}
}
By calling it in a thread:
final SearchView searchView =
(SearchView) MenuItemCompat.getActionView(item);
...
searchView.post(new Runnable() {
#Override
public void run() {
changeSearchViewElements(searchView);
}
});
Here's the output:
Finally, to get the line under the field, there is a possible workaround as using a 9-patch drawable and set it as a background. You can easily find how-to on Google. So the condition will be:
private void changeSearchViewElements(View view) {
...
if (view.getId() == R.id.search_edit_frame
|| view.getId() == R.id.search_mag_icon) {
LinearLayout.LayoutParams p =
(LinearLayout.LayoutParams) view.getLayoutParams();
p.leftMargin = 0; // set no left margin
view.setLayoutParams(p);
} else if (view.getId() == R.id.search_src_text) {
AutoCompleteTextView searchEdit = (AutoCompleteTextView) view;
searchEdit.setBackgroundResource(R.drawable.rect_underline_white);
}
...
}
From the OP's comment below, the underline's field can also be done with the following statement:
searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text)
.setBackgroundResource(R.drawable.abc_textfield_search_default_mtrl_alpha);
After these workarounds, as I said, it might be easier to use a custom layout. But if you want to keep the default SearchView widget, this might help.
So I have a menu item, that's defined as:
<item
android:id="#+id/action_live"
android:title="#string/action_live"
android:orderInCategory="1"
app:showAsAction="ifRoom|withText" />
It shows as text, as you can see below:
And I want to programmatically change the "LIVE" text color. I've searched for a while and I found a method:
With globally defined:
private Menu mOptionsMenu;
and:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
mOptionsMenu = menu;
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
I do:
MenuItem liveitem = mOptionsMenu.findItem(R.id.action_live);
SpannableString s = new SpannableString(liveitem.getTitle().toString());
s.setSpan(new ForegroundColorSpan(Color.RED), 0, s.length(), 0);
liveitem.setTitle(s);
But nothing happens!
If I do the same for an item of the overflow menu, it works:
Is there some limitation for app:showAsAction="ifRoom|withText" items? Is there any workaround?
Thanks in advance.
Bit late to the party with this one, but I spent a while working on this and found a solution, which may be of use to anyone else trying to do the same thing. Some credit goes to Harish Sridharan for steering me in the right direction.
You can use findViewById(R.id.MY_MENU_ITEM_ID) to locate the menu item (provided that the menu had been created and prepared), and cast it to a TextView instance as suggested by Harish, which can then be styled as required.
public class MyAwesomeActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
super.onCreate(savedInstanceState);
// Force invalidatation of the menu to cause onPrepareOptionMenu to be called
invalidateOptionsMenu();
}
private void styleMenuButton() {
// Find the menu item you want to style
View view = findViewById(R.id.YOUR_MENU_ITEM_ID_HERE);
// Cast to a TextView instance if the menu item was found
if (view != null && view instanceof TextView) {
((TextView) view).setTextColor( Color.BLUE ); // Make text colour blue
((TextView) view).setTextSize(TypedValue.COMPLEX_UNIT_SP, 24); // Increase font size
}
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean result = super.onPrepareOptionsMenu(menu);
styleMenuButton();
return result;
}
}
The trick here is to force the menu to be invalidated in the activity's onCreate event (thereby causing the onPrepareMenuOptions to be called sooner than it would normally). Inside this method, we can locate the menu item and style as required.
#RRP give me a clue ,but his solution does not work for me. And #Box give a another, but his answer looks a little not so cleaner. Thanks them. So according to them, I have a total solution.
private static void setMenuTextColor(final Context context, final Toolbar toolbar, final int menuResId, final int colorRes) {
toolbar.post(new Runnable() {
#Override
public void run() {
View settingsMenuItem = toolbar.findViewById(menuResId);
if (settingsMenuItem instanceof TextView) {
if (DEBUG) {
Log.i(TAG, "setMenuTextColor textview");
}
TextView tv = (TextView) settingsMenuItem;
tv.setTextColor(ContextCompat.getColor(context, colorRes));
} else { // you can ignore this branch, because usually there is not the situation
Menu menu = toolbar.getMenu();
MenuItem item = menu.findItem(menuResId);
SpannableString s = new SpannableString(item.getTitle());
s.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, colorRes)), 0, s.length(), 0);
item.setTitle(s);
}
}
});
}
In order to change the colour of menu item you can find that item, extract the title from it, put it in a Spannable String and set the foreground colour to it. Try out this code piece
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
MenuItem mColorFullMenuBtn = menu.findItem(R.id.action_submit); // extract the menu item here
String title = mColorFullMenuBtn.getTitle().toString();
if (title != null) {
SpannableString s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(Color.parseColor("#FFFFFF")), 0, s.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); // provide whatever color you want here.
mColorFullMenuBtn.setTitle(s);
}
return super.onCreateOptionsMenu(menu);
}
It only becomes a text view after inspection, its real class is ActionMenuItemView, on which we can further set the text color like this:
public static void setToolbarMenuItemTextColor(final Toolbar toolbar,
final #ColorRes int color,
#IdRes final int resId) {
if (toolbar != null) {
for (int i = 0; i < toolbar.getChildCount(); i++) {
final View view = toolbar.getChildAt(i);
if (view instanceof ActionMenuView) {
final ActionMenuView actionMenuView = (ActionMenuView) view;
// view children are accessible only after layout-ing
actionMenuView.post(new Runnable() {
#Override
public void run() {
for (int j = 0; j < actionMenuView.getChildCount(); j++) {
final View innerView = actionMenuView.getChildAt(j);
if (innerView instanceof ActionMenuItemView) {
final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
if (resId == itemView.getId()) {
itemView.setTextColor(ContextCompat.getColor(toolbar.getContext(), color));
}
}
}
}
});
}
}
}
}
You could put the change of the color in the onPrepareOptionsMenu:
override fun onPrepareOptionsMenu(menu: Menu?): Boolean
{
val signInMenuItem = menu?.findItem(R.id.menu_main_sign_in)
val title = signInMenuItem?.title.toString()
val spannable = SpannableString(title)
spannable.setSpan(
ForegroundColorSpan(Color.GREEN),
0,
spannable.length,
Spannable.SPAN_INCLUSIVE_INCLUSIVE)
SgnInMenuItem?.title = spannable
return super.onPrepareOptionsMenu(menu)
}
of course you can make it shorter above...
now you can change the color appearance upon other (ie. viewmodel) values...
RG
I spent a lot of hours on this and finally got it into work. There is easy solusion for Android 6 and 7 but it doesn't work on Android 5. This code works on all of them. So, if you are doing it in Kotlin this is my suggestion:
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
setToolbarActionTextColor(menu, R.color.black)
this.menu = menu
return true
}
private fun setToolbarActionTextColor(menu: Menu, color: Int) {
val tb = findViewById<Toolbar>(R.id.toolbar)
tb?.let { toolbar ->
toolbar.post {
val view = findViewById<View>(R.id.my_tag)
if (view is TextView) {
view.setTextColor(ContextCompat.getColor(this, color))
} else {
val mi = menu.findItem(R.id.my_tag)
mi?.let {
val newTitle: Spannable = SpannableString(it.title.toString())
val newColor = ContextCompat.getColor(this, color)
newTitle.setSpan(ForegroundColorSpan(newColor),
0, newTitle.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
it.title = newTitle
}
}
}
}
}
It's complicated, but you can use the app:actionLayout attribute. For example,
my_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/englishList"
android:orderInCategory="1"
app:showAsAction="ifRoom|withText"
app:actionLayout="#layout/custom_menu_item_english_list"
android:title=""/>
</menu>
custom_menu_item_english_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/englishListWhiteText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:lineHeight="16dp"
android:textSize="16sp"
android:text="英文"
android:layout_marginRight="8dp"/>
</LinearLayout>
MainActivity.java:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_menu, menu);
MenuItem item = menu.findItem(R.id.englishList);
item.getActionView().findViewById(R.id.englishListWhiteText)
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
//Handle button click.
}
});
return true;
}
Result:
More Detailed Example=
https://medium.com/#info.anikdey003/custom-menu-item-using-action-layout-7a25118b9d5
if you are using popup menu function to show the menu items in the application and trying to change the design or color of your text items in the menu list, first create a style item in your style.xml file:
<style name="PopupMenuStyle" parent="Widget.AppCompat.PopupMenu">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#color/ColorPrimary</item>
<item name="android:textSize">#dimen/textsize</item>
<item name="android:fontFamily">#font/myfonts</item></style>
and use this style in your code as:
val popupWrapper = ContextThemeWrapper(this, R.style.PopupMenuStyle)
val popup = PopupMenu(popupWrapper, your_menu_view)
MenuItem as defined by documentation is an interface. It will definitely be implemented with a view widget before being portrayed as an menu. Most cases these menu items are implemented as TextView. You can use UiAutomatorViewer to see the view hierarchy or even use hierarchyviewer which will be found in [sdk-home]/tools/. Attached one sample uiautomatorviewer screenshot for a MenuItem
So you can always typecast your MenuItem and set the color.
TextView liveitem = (TextView)mOptionsMenu.findItem(R.id.action_live);
liveitem.setTextColor(Color.RED);
EDIT:
Since there was request to see how to use this tool, I'm adding a few more contents.
Make sure you have set environment variable $ANDROID_HOME pointing to your SDK HOME.
In your terminal:
cd $ANDROID_HOME
./tools/uiautomatorviewer
This tool will open up.
The second or third button (refer screenshot) in the menu will capture the screenshot of your attached device or emulator and you can inspect the view and their hierarchy. Clicking on the view will describe the view and their information. It is tool purposely designed for testing and you can inspect any application.
Refer developer site for more info: uiautomatorviewer
How to detect a click on searchView?
I have tried using setOnClickListener, setOnSearchClickListener, setOnFocusChangedListener, but to no avail.
The problem seems to be only click on textbox. If I click anywhere outside of textbox onClickListener triggers, but not if click inside the textbox.
The problem that I am trying to solve is that I need to close a if user clicks anywhere. But I dont know how to handle the SearchView.
I have managed to find a way to solve my problem.
It's a bit hackish, but it works. You have to get the editText from searchView and set OnClickListener to it
int id = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
EditText editText = (EditText) searchView.findViewById(id);
editText.setOnClickListener(listener);
Try this:
searchView = (SearchView)findViewById(R.id.searchView);
searchView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
searchView.setIconified(false);
}
});
Try adding app:iconifiedByDefault="false" to the SearchView tag in your layout XML.
An answer from a similar question: How to detect if SearchView is expanded?
searchView.setOnQueryTextFocusChangeListener { _ , hasFocus ->
if (hasFocus) {
// searchView expanded
} else {
// searchView not expanded
}
}
Can you help me on how to disable searchview when button is pressed? I'm trying this code:
searchView.setEnabled(false);
searchView.setFocusableInTouchMode(false);
searchView.clearFocus();
but it seems not working. I can still input text in searchview.
Thanks.. :))
All above questions don't work for me.
Becase SearchView is a ViewGroup, so we have to disable all its child views.
private void enableSearchView(View view, boolean enabled) {
view.setEnabled(enabled);
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
enableSearchView(child, enabled);
}
}
}
In other place, call this:
enableSearchView(searchView, true/false);
You can use:
searchView.clearFocus();
and if you want to hide it using:
searchView.setVisibility(View.GONE);
Try the following:
searchview.setInputType(InputType.TYPE_NULL);
SearchView isn't the actual EditText you type into, but rather is a LinearLayout which holds a bunch of views, including the EditText.
To get the view you actually want for disabling it:
EditText searchViewEditText = (EditText) searchView.findViewById(R.id.search_src_text);
Note, this only works if you're using support v7 SearchView, since the particular resource id is internal if you use the framework SearchView.
searchView.findViewById(R.id.search_button).setEnabled(false);
But you must check it for null and hide searchView:
ImageView searchBtn = (ImageView) searchView.findViewById(R.id.search_button);
if (searchBtn != null) searchBtn.setEnabled(false);
searchView.setVisibility(View.GONE);
I think this will work
Did you try
searchView.setVisibility(View.GONE); ?
This worked for me
ImageView searchIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_button);
searchIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Don't perform any action.
}
});
searchView.setOnQueryTextFocusChangeListener( new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus && !v.isEnabled()) v.clearFocus();
}
}
Try below code:
searchView.setIconified(true);
val searchEditText: EditText =
searchView.findViewById(androidx.appcompat.R.id.search_src_text)
searchEditText.isEnabled=false
This will work
If you want to clear it (SearchView), do:
searchView.clearFocus();
and if you want to hide it temporarily, do:
searchView.setVisibility(View.GONE);