I want to get the current background to do a condition base on it.
For example, I have a xml with a next arrow, if the background=R.drawable.A, I want to change the background to R.drawable.B when next Button is pressed.
I defined my relative layout as follows :
final RelativeLayout rl = (RelativeLayout) findViewById(R.id.myLayout);
if (rl.getBackground()== R.drawable.A){ //here the error
rl.setBackgroundResource(R.drawable.B);
}
The error is :
incompatible operands types int and drawable.
If there a way to get the current background and base on it do something?
Actually I don't know why they didn't override the equals method in the Drawable class. So you should use getConstantState() method from the Drawable object that returns a Drawable.ConstantState instance that holds the shared state of this Drawable to be able to compare it.
Kotlin
val drawableAConstantState = ContextCompat.getDrawable(this, R.drawable.A)?.constantState
rl.setBackgroundResource(if (rl.background?.constantState == drawableAConstantState) R.drawable.B else R.drawable.A)
Java
if (rl.getBackground() != null && rl.getBackground().getConstantState().equals(getResources().getDrawable(R.drawable.A).getConstantState()) {
rl.setBackgroundResource(R.drawable.B);
} else {
rl.setBackgroundResource(R.drawable.A);
}
You can check if the background drawable is null or not like this:
if (rl.getBackground() != null){
rl.setBackgroundResource(R.drawable.B);
}else{
// do whatever you want
}
Well to remedy the error just change it to:
final RelativeLayout rl = (RelativeLayout) findViewById(R.id.myLayout);
if (rl.getBackground() == getResources().getDrawable(R.drawable.A){ //<-- fixes the error
rl.setBackgroundResource(R.drawable.B);
}
a side note: I suggest you check which drawable should be set against a logical component and not it's manifestation in the UI, but this is up to you.
Related
I have one ImageView and set a drawable on it. Now I need to get the ID of the drawable on click event of ImageView dynamically. How can I get it?
imgtopcolor = (ImageView) findViewById(R.id.topcolor);
imgtopcolor.setImageResource(R.drawable.dr); // How do I get this back?
Now on touch event of imgtopcolor i want to need drawable id because I am setting different drawable each time and want to compare the drawable with other
I think if I understand correctly this is what you are doing.
ImageView view = (ImageView) findViewById(R.id.someImage);
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
ImageView imageView = (ImageView) view;
assert(R.id.someImage == imageView.getId());
switch(getDrawableId(imageView)) {
case R.drawable.foo:
imageView.setDrawableResource(R.drawable.bar);
break;
case R.drawable.bar:
default:
imageView.setDrawableResource(R.drawable.foo);
break;
}
});
Right? So that function getDrawableId() doesn't exist. You can't get a the id that a drawable was instantiated from because the id is just a reference to the location of data on the device on how to construct a drawable. Once the drawable is constructed it doesn't have a way to get back the resourceId that was used to create it. But you could make it work something like this using tags
ImageView view = (ImageView) findViewById(R.id.someImage);
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
ImageView imageView = (ImageView) view;
assert(R.id.someImage == imageView.getId());
// See here
Integer integer = (Integer) imageView.getTag();
integer = integer == null ? 0 : integer;
switch(integer) {
case R.drawable.foo:
imageView.setDrawableResource(R.drawable.bar);
imageView.setTag(R.drawable.bar);
break;
case R.drawable.bar:
default:
imageView.setDrawableResource(R.drawable.foo);
imageView.setTag(R.drawable.foo);
break;
}
});
I answered something like this in another question already, but will change it just a little for this one.
Unfortunately, there is no getImageResource() or getDrawableId(). But, I created a simple workaround by using the ImageView tags.
In onCreate():
imageView0 = (ImageView) findViewById(R.id.imageView0);
imageView1 = (ImageView) findViewById(R.id.imageView1);
imageView2 = (ImageView) findViewById(R.id.imageView2);
imageView0.setTag(R.drawable.apple);
imageView1.setTag(R.drawable.banana);
imageView2.setTag(R.drawable.cereal);
Then, if you like, you can create a simple function to get the drawable id:
private int getDrawableId(ImageView iv) {
return (Integer) iv.getTag();
}
Too easy.
As of today, there is no support on this function. However, I found a little hack on this one.
imageView.setImageResource(R.drawable.ic_star_black_48dp);
imageView.setTag(R.drawable.ic_star_black_48dp);
So if you want to get the ID of the view, just get it's tag.
if (imageView.getTag() != null) {
int resourceID = (int) imageView.getTag();
//
// drawable id.
//
}
Digging StackOverflow for answers on the similar issue I found people usually suggesting 2 approaches:
Load a drawable into memory and compare ConstantState or bitmap itself to other one.
Set a tag with drawable id into a view and compare tags when you need
that.
Personally, I like the second approach for performance reason but tagging bunch of views with appropriate tags is painful and time consuming. This could be very frustrating in a big project. In my case I need to write a lot of Espresso tests which require comparing TextView drawables, ImageView resources, View background and foreground. A lot of work.
So I eventually came up with a solution to delegate a 'dirty' work to the custom inflater. In every inflated view I search for a specific attributes and and set a tag to the view with a resource id if any is found. This approach is pretty much the same guys from Calligraphy used. I wrote a simple library for that: TagView
If you use it, you can retrieve any of predefined tags, containing drawable resource id that was set in xml layout file:
TagViewUtils.getTag(view, ViewTag.IMAGEVIEW_SRC.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_LEFT.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_TOP.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_RIGHT.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_BOTTOM.id)
TagViewUtils.getTag(view, ViewTag.VIEW_BACKGROUND.id)
TagViewUtils.getTag(view, ViewTag.VIEW_FOREGROUND.id)
The library supports any attribute, actually. You can add them manually, just look into the Custom attributes section on Github.
If you set a drawable in runtime you can use convenient library methods:
setImageViewResource(ImageView view, int id)
In this case tagging is done for you internally. If you use Kotlin you can write a handy extensions to call view itself. Something like this:
fun ImageView.setImageResourceWithTag(#DrawableRes int id) {
TagViewUtils.setImageViewResource(this, id)
}
You can find additional info in Tagging in runtime
I recently run into the same problem. I solved it by implementing my own ImageView class.
Here is my Kotlin implementation:
class MyImageView(context: Context): ImageView(context) {
private var currentDrawableId: Int? = null
override fun setImageResource(resId: Int) {
super.setImageResource(resId)
currentDrawableId = resId
}
fun getDrawableId() {
return currentDrawableId
}
fun compareCurrentDrawable(toDrawableId: Int?): Boolean {
if (toDrawableId == null || currentDrawableId != toDrawableId) {
return false
}
return true
}
}
A simple solution might be to just store the drawable id in a temporary variable. I'm not sure how practical this would be for your situation but it's definitely a quick fix.
Even easier: just store the R.drawable id in the view's id: use v.setId(). Then get it back with v.getId().
The background color of my View is #FFFFFFFF. I want to get this through code. I do not want to just put #FFFFFFFF into the method because I will be changing the background through code, so this value will change all the time.
public void toggleEraser() {
ImageView btnEraser = (ImageView) this.findViewById(R.id.imgEraser);
ImageView btnBrush = (ImageView) this.findViewById(R.id.imgBrush);
if (erase) {
btnEraser.setImageResource(R.drawable.greyeraser);
btnBrush.setImageResource(R.drawable.brush);
} else {
btnEraser.setImageResource(R.drawable.eraser);
btnBrush.setImageResource(R.drawable.greybrush);
}
erase = !erase;
if (erase){
//Here is the problem
drawView.setColor(//drawView.getBackgroundColor());
}
else
drawView.setColor(brushColor);
drawView.setErase(erase);
}
store the color you want 0xFFFFFFFF in somevariable and then
change drawView.setColor( to drawView.setBackgroundColor(somevariable);
Check out this answer: Get the background color of a button in android. it is a little different but can lead you on the right path.
Android Studio 0.4.6
minSdkVersion 10
targetSdkVersion 19
I have an activity called ReadingLamp and a Relativelayout called activity_reading_lamp.xml.
I am programmatically trying to set the layout to a different background color.
In my onCreate and set the content view to this layout.
setContentView(R.layout.activity_reading_lamp);
I try and get the root view by doing the following:
mActivityBackground = getWindow().getDecorView().getRootView();
Then later in my app I want to change the color so I do like this:
mActivityBackground.setBackgroundColor(Color.parseColor("#0cf5ff"));
However, the above line doesn't do anything to change the background.
I have also tried doing the following:
mActivityBackground = (RelativeLayout)findViewById(R.layout.activity_reading_lamp);
Where am I going wrong in my code?
you have declared, setContentView(R.layout.activity_reading_lamp); in your Activity. Then you should look for the view you want to change the background color. It has to belongs to R.layout.activity_reading_lamp.
View view = findViewById(R.id.declared_inside_reading_lamp);
Then you can call
view.setBackgroundColor(Color.GREEN)
You have to ensure that all layouts in your activity_reading_lamp.xml have transparent background
You need to specify which background you need to set. For example, you can make id for the parent layout on your activity then do:
RelativeLayout parentLayout = (RelativeLayout)findViewById(R.id."your parent layout id and not your activity name");
parentLayout.setBackgroundColor(Color.TRANSPARENT);
If you would like to make a transition to the new color try this:
#SuppressLint("NewApi") private void tintColor(View rootView, String newColor) {
// currentColor can be given as a new parameter or set as a field
ColorDrawable[] color = {
new ColorDrawable(Color.parseColor(currentColor)),
new ColorDrawable(Color.parseColor(newColor)) };
TransitionDrawable trans = new TransitionDrawable(color);
int sdk = android.os.Build.VERSION.SDK_INT;
if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
rootView.setBackgroundDrawable(trans);
} else {
rootView.setBackground(trans);
}
trans.startTransition(ANIMATION_TIME); // ANIMATION_TIME : time in milliseconds
}
The code accepts hex color strings.
RelativeLayout rl = (RelativeLayout)findViewById(R.id.your_layout_id);
rl.setBackgroundColor(Color.RED);
I have a View object on my Activity and I'd like to change the background resource of the view. More specifically, I'd like to toggle it.
So I'll need some logic like this:
if (myView.getBackgroundResource() == R.drawable.first) {
myView.setBackgroundResource(R.drawable.second);
}
else {
myView.setBackgroundResource(R.drawable.first);
}
The issue here being that there is no getBackgroundResource() method.
How can I obtain the resource a View is using for its background?
I don't think the View remembers what resource it is using after it gets the Drawable from the resource.
Why not use an instance variable in your Activity, or subclass the View and add an instance variable to it?
Wouldn't it be easier to just have a control variable that maintains the state? Lets you be flexible and allows you any number of drawables.
int[] backgrounds = {
R.drawable.first,
R.drawable.second,
R.drawable.third
};
int currentBg;
void switch() {
currentBg++;
currentBg %= backgrounds.length;
myView.setBackgroundResource(backgrounds[currentBg]);
}
You could use a flag to keep track of which was last set
private static final int FIRST_BG = 0;
private static final int SECOND_BG = 1;
private int mCurrentBg;
...
if (mCurrentBg == FIRST_BG) {
myView.setBackgroundResource(R.drawable.second);
mCurrentBg = SECOND_BG;
}
else {
myView.setBackgroundResource(R.drawable.first);
mCurrentBg = FIRST_BG;
}
You would have to initialize mCurrentBg wherever the background is initially set though.
You can get the ID of a resource via the getResources().getIdentifier("filename", "drawable", "com.example.android.project"); function. As you can see you will need the filename, the type of resource (drawable, layout or whatever) and the package it is in.
EDIT: Updated my logic fail.
I think you might be able to put the setTag() and getTag() methods to use here:
//set the background and tag initially
View v = (View)findViewById(R.id.view);
v.setBackgroundResource(R.drawable.first);
v.setTag(R.drawable.first);
if(v.getTag().equals(R.drawable.first)) {
v.setBackgroundResource(R.drawable.second);
v.setTag(R.drawable.second);
} else {
v.setBackgroundResource(R.drawable.first);
v.setTag(R.drawable.first);
}
I have not tested this, but I think it should work, in theory. The downside is that you add a little overhead by having to manually tag it the first time, but after the initial tagging, you shouldn't have to worry about keeping track of flags.
I have one ImageView and set a drawable on it. Now I need to get the ID of the drawable on click event of ImageView dynamically. How can I get it?
imgtopcolor = (ImageView) findViewById(R.id.topcolor);
imgtopcolor.setImageResource(R.drawable.dr); // How do I get this back?
Now on touch event of imgtopcolor i want to need drawable id because I am setting different drawable each time and want to compare the drawable with other
I think if I understand correctly this is what you are doing.
ImageView view = (ImageView) findViewById(R.id.someImage);
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
ImageView imageView = (ImageView) view;
assert(R.id.someImage == imageView.getId());
switch(getDrawableId(imageView)) {
case R.drawable.foo:
imageView.setDrawableResource(R.drawable.bar);
break;
case R.drawable.bar:
default:
imageView.setDrawableResource(R.drawable.foo);
break;
}
});
Right? So that function getDrawableId() doesn't exist. You can't get a the id that a drawable was instantiated from because the id is just a reference to the location of data on the device on how to construct a drawable. Once the drawable is constructed it doesn't have a way to get back the resourceId that was used to create it. But you could make it work something like this using tags
ImageView view = (ImageView) findViewById(R.id.someImage);
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
ImageView imageView = (ImageView) view;
assert(R.id.someImage == imageView.getId());
// See here
Integer integer = (Integer) imageView.getTag();
integer = integer == null ? 0 : integer;
switch(integer) {
case R.drawable.foo:
imageView.setDrawableResource(R.drawable.bar);
imageView.setTag(R.drawable.bar);
break;
case R.drawable.bar:
default:
imageView.setDrawableResource(R.drawable.foo);
imageView.setTag(R.drawable.foo);
break;
}
});
I answered something like this in another question already, but will change it just a little for this one.
Unfortunately, there is no getImageResource() or getDrawableId(). But, I created a simple workaround by using the ImageView tags.
In onCreate():
imageView0 = (ImageView) findViewById(R.id.imageView0);
imageView1 = (ImageView) findViewById(R.id.imageView1);
imageView2 = (ImageView) findViewById(R.id.imageView2);
imageView0.setTag(R.drawable.apple);
imageView1.setTag(R.drawable.banana);
imageView2.setTag(R.drawable.cereal);
Then, if you like, you can create a simple function to get the drawable id:
private int getDrawableId(ImageView iv) {
return (Integer) iv.getTag();
}
Too easy.
As of today, there is no support on this function. However, I found a little hack on this one.
imageView.setImageResource(R.drawable.ic_star_black_48dp);
imageView.setTag(R.drawable.ic_star_black_48dp);
So if you want to get the ID of the view, just get it's tag.
if (imageView.getTag() != null) {
int resourceID = (int) imageView.getTag();
//
// drawable id.
//
}
Digging StackOverflow for answers on the similar issue I found people usually suggesting 2 approaches:
Load a drawable into memory and compare ConstantState or bitmap itself to other one.
Set a tag with drawable id into a view and compare tags when you need
that.
Personally, I like the second approach for performance reason but tagging bunch of views with appropriate tags is painful and time consuming. This could be very frustrating in a big project. In my case I need to write a lot of Espresso tests which require comparing TextView drawables, ImageView resources, View background and foreground. A lot of work.
So I eventually came up with a solution to delegate a 'dirty' work to the custom inflater. In every inflated view I search for a specific attributes and and set a tag to the view with a resource id if any is found. This approach is pretty much the same guys from Calligraphy used. I wrote a simple library for that: TagView
If you use it, you can retrieve any of predefined tags, containing drawable resource id that was set in xml layout file:
TagViewUtils.getTag(view, ViewTag.IMAGEVIEW_SRC.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_LEFT.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_TOP.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_RIGHT.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_BOTTOM.id)
TagViewUtils.getTag(view, ViewTag.VIEW_BACKGROUND.id)
TagViewUtils.getTag(view, ViewTag.VIEW_FOREGROUND.id)
The library supports any attribute, actually. You can add them manually, just look into the Custom attributes section on Github.
If you set a drawable in runtime you can use convenient library methods:
setImageViewResource(ImageView view, int id)
In this case tagging is done for you internally. If you use Kotlin you can write a handy extensions to call view itself. Something like this:
fun ImageView.setImageResourceWithTag(#DrawableRes int id) {
TagViewUtils.setImageViewResource(this, id)
}
You can find additional info in Tagging in runtime
I recently run into the same problem. I solved it by implementing my own ImageView class.
Here is my Kotlin implementation:
class MyImageView(context: Context): ImageView(context) {
private var currentDrawableId: Int? = null
override fun setImageResource(resId: Int) {
super.setImageResource(resId)
currentDrawableId = resId
}
fun getDrawableId() {
return currentDrawableId
}
fun compareCurrentDrawable(toDrawableId: Int?): Boolean {
if (toDrawableId == null || currentDrawableId != toDrawableId) {
return false
}
return true
}
}
A simple solution might be to just store the drawable id in a temporary variable. I'm not sure how practical this would be for your situation but it's definitely a quick fix.
Even easier: just store the R.drawable id in the view's id: use v.setId(). Then get it back with v.getId().