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.
Related
I got JSON response which have elementId and flag for hide/show that element
Call function using this(From JSON Response)
displayView(templateDefinationItem.getTemplateDefinationId(), templateDefinationItem.isActive());
I have created one function for hide the views
public void displayView(final int elementId, boolean isVisible) {
try {
View view = findViewById(elementId);
if (isVisible) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.GONE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
In above code i passed elementId and true/false value for the operation, where
elementId of(EditTextId,TextView,LinearLayout,Buttons etc.)
Error
i got error in this line View view = findViewById(elementId); getting null.
What i want
is there any way to bind any type of element? Or any generic view for same?
in my case i used this View view = findViewById(elementId); for binding but i got null.
Rather passing view id you should pass view in display method that is more convenient.
First Views Ids are generated automatically so if things you are storing this ids some Where and later used to get views it not right thing because Ids are generated and it different device to device and might change any time when application closed and start again.
You can do it by getIdentifier()
try {
String buttonID = elementId;//String name of id
int resID = getResources().getIdentifier(buttonID, "id", getPackageName());
View view = findViewById(resID);
if (isVisible) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.GONE);
} catch (Exception e) {
e.printStackTrace();
}
as above we are passing view id with combination of i and j values and then using getIdentifier() method to make Views objects .
I thing above code is solution towards your problem.
I would suggest using Kotlin instead of Java, and additionally using the core ktx library (it's a library of usefull Kotlin extensions for Android).
With it, you can do something like this:
view.isVisible = true sets the view to View.VISIBLE, whereas view.isVisible = false sets it to View.GONE
Similarly you have view.isInvisible which toggles between Invisible and Visible, and view.isGone which toggles between Gone and Visible.
In case you need the documentation of these methods, you can find it here.
Also, if you're using Kotlin instead of Java, you don't need to do findViewById(R.id.xxx), you can simply do a static import of any View.
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().
I currently have an AppCompatActivity and I want to be able to switch its layout using one of the menu buttons I have set up.
I am able to do that currently using setContentView, however in order to then switch back to the original View displayed, I need to know which one is currently displayed.
How do I go about getting the current ID of the layout file being displayed?
This is what I have currently, the logic is okay but the code doesn't seem to work:
View currentLayout = findViewById(android.R.id.content);
int currentLayoutID = currentLayout.getId();
if (currentLayoutID == R.layout.two) {
setContentView(R.layout.one);
} else if (currentLayoutID == R.layout.one) {
setContentView(R.layout.two);
}
You can use findViewById to find a particular view that exists only in the one which is currently. If findViewById doesn't return null, that means you were viewing that particular layout.
You compare the Id of a view with the layout name:
int currentLayoutID = currentLayout.getId();
if (currentLayoutID == R.layout.two) {
I would introduce a simple class attribute which store the current chosen layout:
private static final int CUR_LAYOUT_ONE = 1;
private static final int CUR_LAYOUT_TWO = 2;
private int currentLayoutID;
// ....
if (currentLayoutID == CUR_LAYOUT_TWO) {
setContentView(R.layout.one);
currentLayoutID = CUR_LAYOUT_ONE;
} else if (currentLayoutID == R.layout.one) {
setContentView(R.layout.two);
currentLayoutID = CUR_LAYOUT_TWO;
}
Maybe you need some additional onSaveInstanceState()-behaviour. Depends on your use case.
if (currentLayoutID == R.layout.two) {
setContentView(R.layout.one);
} else if (currentLayoutID == R.layout.one) {
setContentView(R.layout.two);
}
You are comparing the id to the R.layout. Those are two different entries in the R file. You need to compare the the actual Ids you've given your views. Usually you set them in the xml file.
For instance R.id.layout1
Maybe you should consider using ViewSwitcher. This will be a lot faster then setContentView
http://developer.android.com/reference/android/widget/ViewSwitcher.html
You just define ViewSwitcher as the parent of your views (you can switch between 2 views only) in xml like this:
<ViewSwitcher
android:id="#+id/viewSwitcher"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
and you programatically switch between views like this:
switcher.setDisplayedChild(1);
I need to know how to check how to compare or check for an image resource on an image button
First I setup the button.
button1 = (ImageButton) findViewById(R.id.ib1);
button1.setImageResource(R.drawable.smiley);
if( currentTime%2==0 ) {
button1.setImageResource(R.drawable.smiley);
}
else {
button1.setImageResource(R.drawable.smileyhit);
}
Later at some point I need to check if the image resource of the button is the smiley drawable and increase the score.
something like
if( button1.getImageResource() == R.drawable.smiley ) {
score = score + 1;
}
What should I do to compare that? I do not want to use tags. Please help me out!
Use ImageButton.setTag and ImageButton.getTag to identify which image is currently in ImageButton background as:
if( currentTime%2==0 ) {
button1.setImageResource(R.drawable.smiley);
button1.setTag(R.drawable.smiley);
}
else {
button1.setImageResource(R.drawable.smileyhit);
button1.setTag(R.drawable.smileyhit);
}
use button1.getTag to check current image:
if(Integer.parseInt(button1.getTag().toString()) == R.drawable.smiley ) {
score = score + 1;
}
using setTag and getTag you can easily differentiate images.
if( currentTime%2==0 ) {
button1.setImageResource(R.drawable.smiley);
button1.setTag("smiley");
}
else {
button1.setImageResource(R.drawable.smileyhit);
button1.setTag("smileyhit");
}
if(button1.getTag().toString().equalsIgnoreCase("smiley")){
score = score + 1;
}
Maintain an array with currentTime%2==0 in it for each button. One should not depend on the UI to retrieve the state of the app since the UI is recreated at several different points in the life-cycle of an app. All your data which determines the state of the app should be seperated from the UI.
EDIT
Okie.. as you say you have more images, i still would go through array or list rather than depending on UI to get the data.My method would be as follows,
Create constants for each Image resource with an Int value
eg: public static final int image1=1;
create the int array for the number of images and maintain them with initial values.
Each time to you change the image change the corresponding array element accordingly.
To find out which resource is used, check the corresponding array element.
While restoring UI(like onResume) use the array to set the corresponding draw able resource.
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().