I have a TextView with a drawable as background. Using a StateListDrawable object I'm trying to set the background colour programmatically, but I'm running into unexpected behaviour: I set the colour in one object, and it changes in another. This should be impossible.
The relevant code:
GradientDrawable notPressed = (GradientDrawable) getResources().getDrawable(R.drawable.rectangle);
GradientDrawable isPressed = (GradientDrawable) getResources().getDrawable(R.drawable.rectangle);
isPressed.setColor(util.getColour(api, this));
StateListDrawable bg = new StateListDrawable();
// bg.addState(new int[] { android.R.attr.state_pressed }, isPressed);
bg.addState(StateSet.WILD_CARD, notPressed);
textView.setBackgroundDrawable(bg);
The drawable:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:width="1dp" android:color="#color/divider" />
<solid android:color="#color/background_button" />
</shape>
util.getColour returns a colour resource based on the value of api.
The strange thing is that in the above code the colour of the isPressed drawable is set, but after that this drawable is not used. Instead only the notPressed drawable is added to the background of the textView.
But the background colour of the textView becomes the colour of the isPressed drawable instead! This should be impossible, as they should be two different objects, even if they are created from the same drawable resource.
I think that when you get a resource you get the same reference to it. So notPressed and isPressed are the same object. I believe there's a clone operation somewhere...
Edit:
Yep, you have to call mutate() on the drawable before you modify it. See Adding a color filter to a Drawable changes all Buttons using the same Drawable.
Android uses the same object for drawable resources unless you specify that you need a new copy of it.
you can use this code to solve this issue:
Drawable isPressed = notPressed.getConstantState().newDrawable();
Related
Imageview wherever I touch on Android
I want to show. Can you help me?
In the article I wrote below, my project is how I want to use it.
You have to get screen pressure as we want from you, you should create a new component on the screen every time you click on the screen, you can do this on the java side, every component that is produced will appear and disappear on the screen for 1 second, you can use the timer, you can use the native animations of the android. In other words, what we want right now is to create a new circle with each click on the screen and to have more than one circle at the same time on the screen, and each will have its own start and end time, the components will be removed when the time is up.
use selector background:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- pressed -->
<item android:drawable="#drawable/button_1_selected" android:state_pressed="true"/>
<!-- focused -->
<item android:drawable="#drawable/button_1_normal" android:state_focused="true"/>
<!-- default -->
<item android:drawable="#drawable/button_1_normal"/>
Use state drawable on your image view. Set drawable what you want state_pressed="true" and state_pressed="false". This will do the magic what you want
State list drawable and disabled state
I'm making a to-do app and I'm using a RecyclerView to create a multiple grid layout like this:
I'm using a background layout to round the corners:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="6dp" />
<corners android:radius="20dp"/>
</shape>
My problem is that whenever I change the color dynamically in the adapter like this:
public void onBindViewHolder( ViewHolder holder, int position) {
holder.timee.setBackgroundColor(task.get(position).getColor());
holder.timee.setTextColor(Color.WHITE);
holder.grid.setBackgroundColor(Color.WHITE);
holder.namee.setTextColor(task.get(position).getColor());
}
The background color seems to ignore the boundaries I've set with the background layout and I get this result:
What is the best way to make it have both rounded corners and a different color for every item in the RecycerView?
The background "layout" you are using is in fact not a layout at all; It is a drawable resource. This means that though the visible borders are rounded, the view itself still has its original shape.
When you set a background color programmatically, it replaces the previous drawable that had rounded corners and fills the entire rectangular view. In order to have both rounded corners, and a solid color fill within those bounds, you will need to modify your drawable itself. The <solid> tag should suit this purpose.
To support multiple colors, you can either have separate drawable resources for each of them (useful if you have just a couple of them), or you can use different tints on a base drawable. Other methods can be found at this question.
This doesn't directly answer your question, but it offers an alternative that I find much easier to manage.
When I need views with rounded corners, I tend to use a CardView and I just remove the elevation. I can then modify the layout like any other programmatically:
<android.support.v7.widget.CardView
android:layout_width="50dp"
android:layout_height="50dp"
card_view:cardBackgroundColor="#5500FF00"
card_view:cardCornerRadius="10dp"
card_view:cardElevation="0dp" />
So you just use the CardView in your list item view that's inflated, and then in your code you simply do this:
public void onBindViewHolder( ViewHolder holder, int position) {
...
holder.cardView.setCardBackgroundColor(task.get(position).getColor());
...
}
Is it possible to add a bitmap as border of an ImageView in android dynamically in Java?
I have already tried the following:
Image view in XML and border as shape the result is wrong I want to add bitmap in border.
You have got multiple options:
Place an other View with the border (also imageview) above your Imageview. Thay might be the simples solution. Just add an other view to your xml and make sure they are overlapping. (Use for example a Relative or FrameLayout as container)
Use a Layer List and draw a shape above a Bitmap and add that to your ImageView
Write a custom ImageView and use the Canvas to draw the Border in the overwritten onDraw method. E.g. canvas.drawRect(...) its pretty straightforward.
The simple way:
A drawable for ImageView's attr that android:foreground
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:width="1px" android:color="#ff0000" />
<solid android:color="#android:color/transparent"/>
</shape>
Then XML,
<ImageView
android:id="#+id/unreserved_head_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:foreground="#drawable/shape_border"
/>
The simplest solution I found recently.
Try to use material theme in your app. Use "Theme.MaterialComponents.Light"
Then use image view inside and material card view.
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#color/white"
app:cardCornerRadius="8dp"
app:cardElevation="0dp"
app:strokeColor="#color/colorPrimary"
app:strokeWidth="1dp">
<ImageView/>//define you image view hear
</com.google.android.material.card.MaterialCardView>
With property stokeColor and strokeWidth you can have border on an image view and make it dynamic.
you can use 9 patch in andorid studio to make an image a border!
i was finding a solution but i did not find any so i skipped that part
then i go to the google images of firebase assets and i accidentaly discovered that they use 9patch
heres the link: https://developer.android.com/studio/write/draw9patch
you just need to drag where the edges are
its just like boder edge in unity
I've added an ImageButton(an image of a round gray X,transparent background) .It gets dynamically added to a layout.
final ImageButton btnx = new ImageButton(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
50, 50);
layoutParams.setMargins(14, 14, 14, 14);
l5.addView(btnx, layoutParams);
btnx.setImageResource(R.drawable.buttonx);
The problem here is that under it,there's a gray button.I know how i can hide it(make it transparent or set my image as the background) but then it won't have that nice effect of turning light blue when clicked.
How can i make it so that it still has this effect but the gray button doesn't show on the background?
Or is there any other way to make a button out of my gray X with transparent background and make it turn light blue(as the usual buttons do) when touched and get back to normal color when not touched/clicked ?
Also : does anyone know the standard size of an EditText.I need to align those X's to some EditTexts that are on the same row but on different layouts and i can't do that without knowing the exact size of the editTexts..if the size of the X is smaller or bigger it will start to be unaligned when i add like 100 rows dynamically.
Thanks !
You should use selector for button states:
final ImageButton btnx = new ImageButton(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
50, 50);
layoutParams.setMargins(14, 14, 14, 14);
l5.addView(btnx, layoutParams);
btnx.setImageResource(R.drawable.buttonx);
Also, add buttonx.xml into drawable folder:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/buttonx_pressed"/>
<item android:drawable="#drawable/buttonx_normal"/>
</selector>
And put your images with normal and pressed states ("buttonx_pressed" and "buttonx_normal") into drawable folder too.
Image button is a combination of two views, ImageView and Button by default.
When you touch an ImageButton, ImageView remains static but the default Button view changes its state. So either set background of the ImageButton as null and set and image resource as the "src" of the imageButton or use background selector.
Also if you want that Image button should not turn blue but should give pressed effect, for that you need have some images of the image button size
- one complete transparent for the normal state
- one transparent from center but tranlucent from borders for clicked effect.
Then set the actual image as the background and make a selector with these frame images and set it as the src of the ImageButton.
For the edit text, take a screen capture of your mobile screen and measure it.
How to show that ImageButton is pressed if i add image to it like this:
Drawable testPic = getResources().getDrawable(R.drawable.test_pic);
button.setImageDrawable( testPic );
And make transparent background so that there would be just image:
button.setBackgroundColor(Color.TRANSPARENT);
So when i press image button i don't see that it is pressed. I want that image would be highlighted or something when it is pressed.
Also every my button is created dynamically by code and i don't know what image would be and how many button there are.
So any ideas ?
Thanks.
you should use a selector for choosing all the different appearances of a UI element, including an ImageButton.
first comes the state_Pressed=true which means what does it look like when pressed. after that comes the regular which is the normal state of the button.
I think you should use State List for that...
You have to change Image at run time. You can achieve these with the help of xml file.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:drawable="#drawable/category_listing_bg_img" />
<item android:state_pressed="true" android:drawable="#drawable/category_listing_bg_img_pressed" />
</selector>
Copy this xml to your drawable folder