getDrawable (int) in Context cannot be applied to (java.lang.String) [duplicate] - java

This question already has answers here:
How to get a resource id with a known resource name?
(10 answers)
Closed 4 years ago.
Here's the code:
String id = "R.drwable.br" + mQuestionNumber;
mSlikaNastavi.setImageDrawable(getDrawable(id));
error found on getDrawable(id): getDrawable (int) in Context cannot be
applied to (java.lang.String)
mSlikaNstavi is ImageView, and I would like to change image from java. I cant write in R.drawable.br2 in getDrwable() because every time mQuestionNumber is different.

I guess you have drawables like br1, br2, br3,... and you think that by concatenating R.drawable.br and mQuestionNumber you get the id of the drawable but this is not the case.
do this:
int id = getResources().getIdentifier("br" + mQuestionNumber, "drawable", getPackageName());
mSlikaNastavi.setImageDrawable(getDrawable(id));

A drawable Id needs to be int rather than String. You can get the relative int Id using getIdentifier()
Instead of
mSlikaNastavi.setImageDrawable(getDrawable(id))
Use
String id = "br" + mQuestionNumber;
mSlikaNastavi.setImageDrawable(getDrawable(getResources().getIdentifier(id, "drawable", getPackageName())));`

Here you need to extract the Drawable Id by passing your own id value, instead of the ids which are present in R.java
So for that getIdentifier method is used where you need to provide the drawable name, type of the resource which is "drawable" in your case, and the packageName where Android will search the drawable from.
int drawableId = getResources().getIdentifier("br" + mQuestionNumber,"drawable",getPackageName());
After the id is found, use it to show it in imageView using setImageDrawable() and as it required Drawable get the Drawabel from its iD using getDrawable() passing in the ID.
mSlikaNastavi.setImageDrawable(getResources().getDrawable(drawableId));
So the code is:
int drawableId = getResources().getIdentifier("br" + mQuestionNumber,"drawable",getPackageName());
mSlikaNastavi.setImageDrawable(getResources().getDrawable(drawableId));

Related

How can I get and set a string resource dynamically in a for-loop using a findViewById() method?

In my app, I want a counter from 0 to 8 to decide the number of players in a game.
Below there are 8 possible fields to write a name inside, which are all set to invisible. If the players-counter is set to 3 players, there should be the first 3 fields visible. Depending on the actual number of the counter, the visibility of the fields changes (1player = first field, 5 players = first 5 fields).
When the +1 (player) button is clicked, a certain method is activated. I tried to run a for-loop everytime the button is clicked. In this for-loop from 0 to "whatever amount" (max. 8 players) the actual fields should be found with "findById" and set to visible.
I tried it with a string resource (.xml) and I can get the text of the resource but with my thought process, I have to update the string resource to every number of the field (if 3 players: "field_" + "1", "field_" + "2", "field_" + "3").
How can I get and (most importantly) set/update a string resource for this specific purpose?
(Switch is too inefficient and I can't use a string with the findViewBy Id()-method by updating the String (not string resource) like mentioned before.
Please help, and accept the fact that I'm new to Android Studio for one week!)
You can use "getIdentifier" which takes a String parameter. So you can set the type as "id" in the second parameter of this method. This method returns the id of the view you want, but beware, it will throw a "FATAL EXCEPTION" if the id of the View doesn't exist. With this id, you can use findViewById to fetch the TextView and change its visibility. The "getIdentifier" method can be called from the "getResources()" method.
Below you can see what it would be like to make visible a TextView that has the id "textView1":
int id = getResources().getIdentifier("textView1", "id", getPackageName());
TextView textView = findViewById(id);
textView.setVisibility(View.VISIBLE);
Below you can see how you would make 8 TextView with id 1 to 8 visible:
TextView textView;
for (int i = 1; i <= 8; i++) {
int id = getResources().getIdentifier("textView" + i, "id", getPackageName());
textView = findViewById(id);
textView.setVisibility(View.VISIBLE);
}
So, just put the limit at i <= x , with x being the limit of players who will play:
TextView textView;
for (int i = 1; i <= totalPlayers; i++) {
int id = getResources().getIdentifier("textView" + i, "id", getPackageName());
textView = findViewById(id);
textView.setVisibility(View.VISIBLE);
}
Do you just want to make some EditTexts visible and others not? Personally I'd keep it simple, do the lookups once (in onCreate or wherever) and store the references in a list. Then when you need to display n fields, you can just iterate over the list and set the first n to VISIBLE and the rest to INVISIBLE.
I feel like it's fine to just list all the EditText IDs (R.id.field_1 etc) and generate your list of actual Views from that, but if that repetition bothers you, there's a few things you could do. Like:
set a tag attribute on each field in the XML, and use findViewWithTag to look them up, generating the lookup strings programmatically, like "field_" + i
do a similar thing with the resource ID, like in #Moises's answer
lookup their containing layout, use getChildCount and [getChildAt] to iterate over the views in that layout, and use isInstance to collect all the EditTexts in order3
create and add the EditTexts in code - you probably don't want to do this, but you could!
I'm not really sure what you mean about the string resource or what you're trying to do - I'd honestly just make a list of R.id.field_1 etc, iterate over that to do findViewById on each and store those in a new list, and you're done. Also my Java's a bit rusty so sorry no example code!

Change TextView value in a Fragment Class using Seekbar

I am using a Seekbar library so when I drag the seeker, I expect the textview to be updated with the value from the seeker but unfortunately my app crashes. I get an error that says, "resource not found on the TextView".
The code is below:
RangeSeekBar seekBar1;
seekBar1 = (RangeSeekBar)rootView.findViewById(R.id.seekBar);
seekBar1.setValue(10);
seekBar1.setOnRangeChangedListener(new RangeSeekBar.OnRangeChangedListener() {
#Override
public void onRangeChanged(RangeSeekBar view, float min, float max, boolean isFromUser) {
seekBar1.setProgressDescription((int)min+"%");
TextView txtAmount;
txtAmount = (TextView)rootView.findViewById(R.id.txtAmount);
txtAmount.setText((int) min);
}
});
Solution: You can't set int to the TextView like that, try this instead:
txtAmount.setText(Float.toString(min));
The overload you were using would look for a string resource identifier, that doesn't exist in this case. Here's the correct one that takes a CharSequence as an argument (string is a CharSequence).
Nice to know: If you're now left wondering how an int can be an argument to setText, it's quite simple. In your app, you can have a strings.xml file that defines a set of resources strings to be used in the application:
<resources>
<string name="test">This is a test</string>
</resources>
With that defined, you can show the text on your TextView like this:
txtAmount.setText(R.string.test);
If you pass an integer into setText, android expects the value to be a resource. The system is trying to find a resource who's id is equal to min. You need to convert min to a string.
So to get it working change txtAmount.setText((int) min); to txtAmount.setText(String.valueOf(min));

ImageView setBackround inside the activity dynamically

Inside my drawabale folder I have these images: levelone, leveltwo, level three.
i need to set the ImageView according to the inputted string as follows:
levelindicatorImageView = (ImageView) findViewById(R.id.levelindicatorImageView);
String tempo="R.drawable.level"+LevelReached;
Drawable replacer = getResources().getDrawable(tempo);
int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
levelindicatorImageView.setBackgroundDrawable(replacer);
} else {
levelindicatorImageView.setBackground(replacer);
}
levelindicatorImageView.invalidate();
now inside LevelReached variable i have the needed level (one, two, three)
I need to set the Image R.drawable.leveltwo etc...
How is that possible please?
as getDrawable doesn't work with tempo (needs int)
thanks for the help!
You have 2 options:
Option 1:
Simply use a switch-case to get the correct drawable, then set it as a background image as you normally would
// Get the level drawable resource id
int imageRes = R.drawable.default_image;
switch (levelReached) {
case LEVEL_ONE: // 1
imageRes = R.drawable.level_one;
break;
case LEVEL_TWO: // 2
imageRes = R.drawable.level_two;
break;
...
}
// Set the drawable as a background
levelIndicatorImageView.setBackgroundResource(imageRes);
Where LEVEL_ONE == 1; LEVEL_TWO == 2; as const or enum.
Option 2:
You can find a drawable resource by name (as you wanted), but it is less recommended since it is more error prune. But if you must, use following example:
// Get the level drawable resource id
int imageRes = getResources().getIdentifier("level"+levelReached, "drawable", getPackageName());
// Set the drawable as a background
levelIndicatorImageView.setBackgroundResource(imageRes);
Note:
You don't need to explicitly invalidate the view if you set the background since setting a new background will trigger invalidation by itself. So, this line:
levelindicatorImageView.invalidate();
is not needed.
You cant append input string to image name, but what you can do is,
select the image based on input string and then If you have 3 different images, try with ;
if(input.equalsIgnoreCase("input one"))
{
int id = R.drawable.<img one>;
}
else
{
//so on
}
levelindicatorImageView.setBackground(getResources().getDrawable( id) );
You need to do something like this:
public int getResourecId(String level) {
if(level.equalsIgnoreCase("one"))
return R.drawable.levelone;
if(level.equalsIgnoreCase("two"))
return R.drawable.leveltwo;
if(level.equalsIgnoreCase("three"))
return R.drawable.levelthree;
return 0;
}
and then:
Drawable replacer = getResources().getDrawable(getResourceId(LevelReached));
You need to associate the levels to a resource, in this case, an int. An idiomatic way of doing this would be to store the levels as an enum, say
enum Level { ONE, TWO, THREE }
Using an enum in this way allows you some flexibility with your level conventions. For example, if you later wanted to add the level TWO_THIRDS, there is nothing stoping you. Then, associate each level with a resource in an EnumMap, for example:
Map<Level, Integer> levelResources = new EnumMap<Level, Integer>(Level.class);
levelResources.put(ONE, R.drawable.levelOne);
levelResources.put(TWO, R.drawable.levelTwo);
levelResources.put(THREE, R.drawable.levelThree);
Now, instead of passing around a string which describes your current level, you can pass around an enum, which you can use to determine the correct resource without concatenating strings. So, suppose that levelReached is of type Level, you could write:
Integer tempo = levelResources.get(levelReached);
Drawable replacer = getResources().getDrawable(tempo);

numbered images on setImageResource

I'm working on an Android App, and I had the following code:
int digit = 0;
imageButton = (ImageView)findViewById(R.id.btn1);
numberedImage = (ImageView)findViewById(R.id.Digit1);
imageButton.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
digit++;
numberedImage.setImageResource(R.drawable.number + ((digit) + 1));
}
});
and some images on a drawable folder called number1, number2, and so on...
This code was working perfectly, and then, suddenly, it's not working anymore.
I want the ImageView to change the images each click, and what made me completely confused, is the fact that this code was working completely fine (even though it might be wrong some way, I'm not a programmer), and all of the sudden, it's not anymore...
After that I also tried using arrays and loops, but I encountered the same error:
"number cannot be resolved or is not a field"
which wasn't a problem before.
You have some misunderstanding. But may be fortunately(or unfortunately) your code gave you some successful result for which your misunderstanding was more firmed.
ImageView.setImageResource takes a resource id as parameter. not a image name. so when you are adding a digit to the resource id it is setting the image of next id. as your images' names are sequential so the ids were also sequential that's why you got successful result. But it is not guranteed that you will always be getting that done.
I guess previously it was working because there was an image named number in your resource. But now it is removed.
Proposed solution
Resources res = getResources();
String mDrawableName = "number" + digit + 1; // be sure those exist
int resID = res.getIdentifier(mDrawableName , "drawable", getPackageName()); numberedImage.setImageResource(resId);
please kindly use
for(int i=0;i<imageCount;i++){
int imageResId = getResources().getIdentifier("image" + i, "id", YourActivity.this.getPackageName());
numberedImage.setImageResource(imageResId);
}
in order to access image by resource name.

Dynamically get drawables by ID

I want to take a byte and append it to a resource ID to be able to get the image that corresponds to that numbered deck in the game. It was easy to with paths on other devices, but with the Resource ID's I am unsure how I could go about do this.
Here's what I have now:
switch(GameSettings.gameDeck)
{
case 1:
deckImage.setBackgroundResource(R.drawable.deck1);
break;
case 2:
deckImage.setBackgroundResource(R.drawable.deck2);
break;
case 3:
deckImage.setBackgroundResource(R.drawable.deck3);
break;
case 4:
deckImage.setBackgroundResource(R.drawable.deck4);
break;
}
In my Blackberry version of this, I simply had:
deckImage.setBitmap(Bitmap.getBitmapResource("/path/deck" + GameSettings.gameDeck + ".png"));
Is there a way to accomplish something similar using Resource IDs on Android?
Use getResources().getIdentifier() from your Context (e.g., Activity), but please cache the result if you will use it more than once. getIdentifier() is implemented on Resources.
For example:
int drawableId=getResources().getIdentifier("foo"+index, "drawable", getPackageName());
would return the value of R.drawable.fooN, where N is the number given by index.
For more, see this and this and this.
In your case, the image drawable name are same at begining charecters and the different are the numbers. so when your app is complied. The generated ids for your drawable name are a sequence of consecutive increments.
These are ids that generated when I named my drawable as same as your sample code
int drawable deck1 0x7f07007a //convert hex to decimal = 2131165306
int drawable deck2 0x7f07007b //convert hex to decimal = 2131165307
int drawable deck3 0x7f07007c //convert hex to decimal = 2131165308
int drawable deck4 0x7f07007d //convert hex to decimal = 2131165309
You can check the R.txt file which generated by android studio.
So the simple solution is:
int deckId = R.drawable.deck1 + GameSettings.gameDeck - 1
deckImage.setImageResource(deckId)

Categories