I recently found a bug with Material Design TexInputLayout and the way it makes the endIcon visible.
Consider you have setup everything right and have end icon enabled like:
inputLayout.endIconMode == END_ICON_CLEAR_TEXT
The problem is that if you define a focusListener like:
inputLayout.editText?.setOnFocusChangeListener { view, hasFocus -> ...}
and navigate to a screen which has this textInputLayout in it with some already filled text in like following pic
You'll notice that the endIcon is not showing, but if you tap on where it's supposed to be, it will work.
Even making sure it should be displayed by making it visible inputLayout.isEndIconVisible = doesn't help. Through the debugging you can see you are hitting the public void setEndIconVisible(boolean visible) with true value but still it doesn't make the icon visible.
I found a solution which I have posted as the answer.
The issue is that ClearTextEndIconDelegate has a default OnFocusChangeListener which when you click on the editText it runs an animation which through it the alpha value of the private/internal endIconView(which holds the endIconDrawable) changes from 0 to 1. When you override and set your own OnFocusChangeListener you actually discard this process and setting the inputLayout.isEndIconVisible = true enables the view but you can't see it still. I didn't find any way to access to the parent view and change the alpha.
Actually you can by doing something like
(((inputLayout.getChildAt(0) as FrameLayout).getChildAt(2) as LinearLayout).getChildAt(1) as FrameLayout).getChildAt(0).alpha = 1f
Take a look at image below you'll get how I ended up the above:
But this is not a great solution also if the hierarchy of the view changes it won't work anymore.
Ultimate Solution
What I came with is the invoking the original OnFocusChangeListener within my OnFocusChangeListener something like :
val originalListener = inputLayout.editText?.onFocusChangeListener
inputLayout.editText?.setOnFocusChangeListener { view, hasFocus ->
originalListener?.onFocusChange(view, hasFocus)
// do your thing here
}
For this case, it will be better to set custom mode for end icon
textInputLayout.endIconMode = TextInputLayout.END_ICON_CUSTOM // may be set in xml
textInputLayout.setEndIconDrawable(R.drawable.your_icon)
textInputLayout.setEndIconOnClickListener {
textInputEditText.text?.clear()
}
And then add your custom OnFocusChangeListener:
inputLayout.editText?.setOnFocusChangeListener { view, hasFocus ->
textInputLayout.isEndIconVisible = hasFocus
// add your code here
}
For me, none of the solution worked and the end icon was invisible because the alpha is set to 0.
So I decided to manually set drawable end in the TextInputEditText.
// First, set the endIconMode to None and set the click listener to clear the text
testInputLayout.endIconMode = TextInputLayout.END_ICON_NONE
testInputLayout.setEndIconOnClickListener {
binding.customTextInput.editText?.text?.clear()
}
// Inside the custom focusChangeListener, show/hide the drawable end
textInputLayout.editText?.setOnFocusChangeListener { _, hasFocus ->
// This is required so that the clear text click action can be handled
binding.customTextInput.isEndIconVisible = hasFocus
if (hasFocus) {
// Display Drawable end
textInputLayout.editText?.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(context, R.drawable.ic_clear), null)
} else {
// Hide Drawable end
textInputLayout.editText?.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
}
// Do what you want
}
TextInputLayout's textwatcher checks if the view has focus and if there is any text in its EditText and sets the visibility of the end icon. Probably, it sets the end icon visibility to Visibility.GONE since it does not have the focus even if there is any text in its underlying EditText. So the TextInputLayout needs to have the focus as well. So the below code worked for me
inputLayout.requestFocus()
inputLayout.edittext.setText(YOUR_TEXT)
inputLayout.edittext.setSelection(YOUR_TEXT_LENGTH)
Extending to Amir's answer
Running on a Pixel 5 API 32 device and targetSdkVersion to 31.
The children of TextInputEditText are shown as below:
So we might use following code to set this view's alpha by:
id_of_text_input_layout.findViewById<View>(R.id.text_input_end_icon)?.alpha = 1f
After trying the solutions from this thread and finding they don't work in my case (the "clear text icon" from com.google.android.material.textfield.TextInputLayout wasn't always being displayed, not even with alpha 0), I ended up implementing the "clear text icon" from scratch, ie:
add an ImageView with my "clear text icon" to TextInputLayout's parent ViewGroup
attach an onClickListener to that ImageView and place the text-clearing logic there
attach onTextChanged and onFocusChange listeners to my EditText to trigger ImageView's visibility changes.
make the ImageView visible by animating its alpha from 0 to 1 and setting its visibility to View.VISIBLE at the end. To make it invisible, do the reverse, ie. animate its alpha from 1 to 0 and set its visibility to View.GONE at the end. Weirdly enough, when just toggling the visibility between GONE and VISIBLE, that ImageView wasn't always being displayed.
when the ImageView is shown, add endPadding to TextInputLayout, so that text in the EditText doesn't show under the ImageView
I am trying to build an application and want to build a view that has inward shadow effect as shown in the picture. I wanted to do it in both Android and iOS (SwiftUI).
For now in SwiftUI it is possible to do only using different images for selected and non-selected states.
Here is a demo of approach to do this
struct TestSelectedTabs: View {
#State var selectedTab = 1
var body: some View {
TabView(selection: $selectedTab){
Text("One")
.tabItem {
Image(systemName: selectedTab == 0 ? "printer.fill" : "printer")
Text("Print")
}.tag(0)
Text("Two")
.tabItem {
Image(systemName: selectedTab == 1 ? "tv.fill" : "tv")
Text("Show")
}.tag(1)
}
}
}
so having two set of icons (flat & pressed in) you can achieve required effect. Or, of course, you can generate image with desired "press in" effect in code, say using CoreGraphics, Layers, etc. but finally it needs to be just image.
Well you could just create a custom background with that particular shadow in mind and then just whenever the user presses the button change the button's background to reflect the shadow background, and since its custom you could do the shape of your liking and the depth of your liking too.
You would normally keep the icons/buttons flat right? and then when pressed/selected/active just change the background to this,so as to show emphasis on it being selected.
This is an almost similar approach to the method in the above answer.
Before I decided to ask it, I search some Remove Tint Color Programmatically, but it marked as duplicate so I didn't know if this is also a duplicate or not? because it didn't answer my question, I think.
Because I am asking also if is it possible to RESET or REMOVE the tint of ImageView after changing the drawable.
This is the normal image
This is the selected image
and this is the normal image again after deselecting the image
and this is my code.
if (isSelected) {
// Reset the ImageView to normal
isSelected = false
imgHeart.setImageDrawable(itemView.context.getDrawable(R.drawable.baseline_favorite_border_24))
} else {
// Tint ImageView to Red
isSelected = true
imgHeart.setImageDrawable(itemView.context.getDrawable(R.drawable.baseline_favorite_24))
imgHeart.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(itemView.context, R.color.colorRedHeart))
}
I also try the imgHeart.imageTintList = null but the image is turning into white or disappear.
I also try the imgHeart.colorFilter = null but the image is do nothing and turning into the last image.
I am using the Material Design Icon.
What I want to bring back the image into normal drawable as you see in the first image.
Thank you.
The selected drawable is a completely different drawable than the other 2. You can't tint baseline_favorite_border_24 to look like the selected one, you can tint only the borders and can't fill it with color. By the way imageTintList requires API 21+. So use 2 drawables(you don't need to download them, they exist in Android Studio), name the selected one as baseline_favorite_filled_24 and toggle between them.
if (isSelected) {
isSelected = false
imgHeart.setImageDrawable(itemView.context.getDrawable(R.drawable.baseline_favorite_border_24))
} else {
isSelected = true
imgHeart.setImageDrawable(itemView.context.getDrawable(R.drawable.baseline_favorite_filled_24))
}
In my project I have to verify if a backround is equal to another for an edit text (the edit text has a custom drawable). I have tried this code but it's not working:
if (editText.getBackground().equals(getResources().getDrawable(R.drawable.edit_text_box_red)))
{
editText.setBackgroundResource(R.drawable.edit_text_box_white);
}
I need this, because when I press a button and my editText background is red I have to make it white, to it's previous state. How can I do this?
I think it would make sense to store the background information when you change the background in the first place. One way to do this would be setTag(). For example, when you change the view's background to red, you also perform editText.setTag("red"). Then later, you can do
if (editText.getTag().equals("red")) {
editText.setBackgroundResource(R.drawable.edit_text_box_white);
editText.setTag("white");
}
How about "Flagging"?
Its like you create a static bool red = false
Then when you change the color, change the red value to true
In the selection :
if(red == true){
editText.setBackgroundResource(R.drawable.edit_text_box_white);
red = false;}
Hope this help :D
I'm trying to set the background color of a View (in this case a Button).
I use this code:
// set the background to green
v.setBackgroundColor(0x0000FF00 );
v.invalidate();
It causes the Button to disappear from the screen. What am I doing wrong, and what is the correct way to change the background color on any View?
Thanks.
You made your button transparent. The first byte is the alpha.
Try v.setBackgroundColor(0xFF00FF00);
When you call setBackgoundColor it overwrites/removes any existing background resource, including any borders, corners, padding, etc.
What you want to do is change the color of the existing background resource...
View v;
v.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
Experiment with PorterDuff.Mode.* for different effects.
Several choices to do this...
Set background to green:
v.setBackgroundColor(0x00FF00);
Set background to green with Alpha:
v.setBackgroundColor(0xFF00FF00);
Set background to green with Color.GREEN constant:
v.setBackgroundColor(Color.GREEN);
Set background to green defining in Colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="myGreen">#00FF00</color>
<color name="myGreenWithAlpha">#FF00FF00</color>
</resources>
and using:
v.setBackgroundResource(R.color.myGreen);
and:
v.setBackgroundResource(R.color.myGreenWithAlpha);
or the longer winded:
v.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.myGreen));
and:
v.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.myGreenWithAlpha));
You can set the hex-color to any resource with:
View.setBackgroundColor(Color.parseColor("#e7eecc"));
// set the background to green
v.setBackgroundColor(0x0000FF00 );
v.invalidate();
The code does not set the button to green. Instead, it makes the button totally invisible.
Explanation: the hex value of the color is wrong. With an Alpha value of zero, the color will be invisible.
The correct hex value is 0xFF00FF00 for full opacity green. Any Alpha value between 00 and FF would cause transparency.
For setting the first color to be seen on screen, you can also do it in the relevant layout.xml (better design) by adding this property to the relevant View:
android:background="#FF00FF00"
and what is the correct way to change
the background color on any View?
On any View? What you have is correct, though you should drop the invalidate() call.
However, some Views already have backgrounds. A Button, for example, already has a background: the face of the button itself. This background is a StateListDrawable, which you can find in android-2.1/data/res/drawable/btn_default.xml in your Android SDK installation. That, in turn, refers to a bunch of nine-patch bitmap images, available in multiple densities. You would need to clone and modify all of that to accomplish your green goals.
In short, you will be better served finding another UI pattern rather than attempting to change the background of a Button.
try to add:
setBackgroundColor(Color.parseColor("#FF0000"));
I use at API min 16 , target 23
Button WeekDoneButton = (Button) viewWeeklyTimetable.findViewById(R.id.week_done_button);
WeekDoneButton.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.colorAccent));
mButton.setBackgroundColor(getResources().getColor(R.color.myColor));
You can simple use :
view.setBackgroundColor(Color.parseColor("#FFFFFF"));
You can simple use :
view.setBackgroundColor(Color.rgb(0, 198, 255));
This question talks about changing the background color of a view. In one of the answers, the person explains how to change the background color during runtime. Obviously you are going to look into how to modify other objects on the screen, but this should give you a good start by at least allowing you to modify the background color of the view on button click.
Stating with Android 6 use ContextCompact
view.setBackgroundColor( ContextCompat.getColor(this, R.color.your_color));
This works for me
v.getBackground().setTint(Color.parseColor("#212121"));
That way only changes the color of the background without change the background itself. This is usefull for example if you have a background with rounded corners.
In kotlin you could do it like this:
val backgroundColor = R.color.whatever_color_you_like
view.setBackgroundColor(getColorCompat(backgroundColor))
Where getColorCompat() is an extension function:
/**
* Extension method to provide simpler access to {#link ContextCompat#getColor(int)}.
*/
fun Context.getColorCompat(color: Int) = ContextCompat.getColor(this, color)
view.setBackgroundColor(R.color.primaryColor);
Adds color to previous color value, so i have a different color.
What works for me is :
view.setBackgroundResource(R.color.primaryColor);
Let suppose we have a primary color in values=>colors.xml as:
<resources>
<color name="primary">#FDD835</color>
</resources>
so if we want to use our custom color into setBackgroundColor(#ColorInt int Color) then we just need an annotation #SuppressLint("ResourceAsColor") with constructor/method which will be used as:
#SuppressLint("ResourceAsColor")
public _LinearLayout(Context context) {
super(context);
// Formatting our layout : )
super.setBackgroundColor(R.color.primary);
....
}
You must pass an int in the argument.
First Example:
view.setBackgroundColor(-500136)
Second Example:
int colorId = R.color.green;
view.setBackgroundResource(colorId);
This should work fine: v.setBackgroundColor(0xFF00FF00);
I tried all the above ways. But I havent achieve what i need. Here is my try.
If you are using hexcode for color and want to set the color as background of image, then this is the kotlin code.
val bitmap = Bitmap.createBitmap(30, 30, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
val colorCode = "#ffffff"
canvas.drawColor(Color.parseColor(colorCode))
mImageViewLogo.setImageBitmap(bitmap)
When calling setBackgroundColor on a view you need to set the alpha value to a non-zero value (e.g. 0xFF), otherwise the color will not show up.
TextView tv = (TextView)findViewById(R.id.myTextview);
int rgb = 0xF05922; // Orange
tv.setBackgroundColor(0xFF000000|rgb); // Use bitwise OR to add alpha to RGB value