Is there a way to add a drawable in any position within a text view programmatically without having to position it on a particular side of a text view? The following code works when using unicode character but I want to try the same with a vector drawable.
textView.text = getString(R.string.app_settings) + " \u2794 " + getString(R.string.display)
For me, ImageSpan works.
You can put a delimiter and replace it with the drawable. I used a google icon in this example
:
Code with delimiter replacement:
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.google_icon);
drawable.setBounds(0, 0, 100,100);
String text = " Google %google_icon% icon";
String delimiter = "%google_icon%";
int icon_index = text.indexOf("%google_icon%");
text = text.replace(delimiter," ");
Spannable span = new SpannableString(text);
ImageSpan image = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
span.setSpan(image, icon_index, icon_index+1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
textView.setText(span);
Or, you can place the drawable on any index like:
span.setSpan(image, start_index, end_index, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
PS: I used Display1 in text appearance. You need to change drawable bounds according to your own needs.
I have a set of images in my drawable resources. Now I want to be able to change a placeholder image accordingly with image.setImageResource(R.id.name_of_image) programmatically.
My ImageView is defined as ImageView image = findViewById(R.id.placeholder);
How would I do this? I have tried getIdentifier but that didn't work.
The images have the format Name.jpg
EDIT:
I currently have the following construction:
int resID = getResources().getIdentifier(name.toLowerCase(), "drawable", this.getPackageName());
ImageView image = findViewById(R.id.placeholder);
image.setImageResource(resID);
I have changed the image name to lowercase and it is now a png file.
Your images has to be in png format (prefered by android) and must contain only lowercase letters and digits ([a-z0-9_.].
Then you can use
image.setImageResource(R.drawable.name_of_image);
You can get the name of the drawable with this:
String name = context.getResources().getResourceEntryName(R.drawable.name_of_image);
To get the drawable with the string name:
int id = context.getResources().getIdentifier("name_of_image", "drawable", context.getPackageName());
image.setImageResource(id);
I'm looping through an array, in that for-loop I'm also using this array to get IDs for a couple of spinners:
Integer[] ids;
ids = new Integer[8];
ids[0] = R.id.nr_area;
ids[1] = R.id.nr_municipality;
ids[2] = R.id.nr_method;
ids[3] = R.id.nr_bait;
ids[4] = R.id.nr_sessionhours;
ids[5] = R.id.nr_bifangst_art;
ids[6] = R.id.nr_bifangst_released;
ids[7] = R.id.nr_name;
In the for loop:
for (int i = 0; i < fields.length; i++) {
if(fields[i].contains("*") || fields[i].matches("")){
String test = ids[i].toString();
int resID = getResources().getIdentifier(test, "id", getPackageName());
Spinner spnr = (Spinner) findViewById(resID); //error is on this row
spnr.setBackgroundColor(Color.GREEN);
}
}
Now the error I get is as follows:
android.support.v7.internal.widget.TintEditText cannot be cast to android.widget.Spinner
So I guess this can't be used with a spinner as I found the example code for a EditText.. but how can I do what I'm trying to do with a spinner?
I would appreciate any help! Been fighting with this for hours. Thanks alot..
I think the problem is that either one of the ids is of EditText or id was of EditText and you have changed it to Spinner in your xml lately. Make sure that ids are correct, relate them from xml, if still problem persists, try cleaning your project for indexing again, that should do it.
Hope this helps ...
I need to get the coordinates of my app on screen to use them as an offset for a popout.
View tempView = (View) findViewById(R.layout.main);
int[] loc = {0,0};
tempView.getLocationOnScreen(loc); /// crashes here!
Tried this code, but the last line of it makes the app crash. Maybe the tempView I'm getting from the main layout somehow doesn't correspond with the layout on screen?
Any suggestions... thanks! :)
added:
solved
int[] loc = new int[2];
View tempView = (View) findViewById(R.id.LL_whole);
tempView.getLocationOnScreen(loc);
post( String.valueOf(loc[1]) );
works! :)
Try checking to see if tempView is null. I suspect findViewById() is failing to find the id you've given it.
int[] loc = {0,0};
View tempView = (View) findViewById(R.layout.main);
if (tempView != null) {
tempView.getLocationOnScreen(loc);
} else {
Log.d("YourComponent", "tempView was null.");
}
In your XML you have something like this:
<SomeLayout android:id="#+id/myLayout" ... >
<SomeView android:id="#+id/myView" ... />
<SomeOtherView android:id="#+id/myOtherView" .../>
</SomeLayout>
So you want to say:
SomeView v = (SomeView)findViewById(R.id.myView);
Or perhaps:
SomeLayout l = (SomeLayout)findViewById(R.id.myLayout);
findViewById(R.layout.main)
You should place here R.id.something not R.layout.something.
I'm dynamically creating buttons. I styled them using XML first, and I'm trying to take the XML below and make it programattic.
<Button
android:id="#+id/buttonIdDoesntMatter"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="buttonName"
android:drawableLeft="#drawable/imageWillChange"
android:onClick="listener"
android:layout_width="fill_parent">
</Button>
This is what I have so far. I can do everything but the drawable.
linear = (LinearLayout) findViewById(R.id.LinearView);
Button button = new Button(this);
button.setText("Button");
button.setOnClickListener(listener);
button.setLayoutParams(
new LayoutParams(
android.view.ViewGroup.LayoutParams.FILL_PARENT,
android.view.ViewGroup.LayoutParams.WRAP_CONTENT
)
);
linear.addView(button);
You can use the setCompoundDrawables method to do this. See the example here. I used this without using the setBounds and it worked. You can try either way.
UPDATE: Copying the code here incase the link goes down
Drawable img = getContext().getResources().getDrawable(R.drawable.smiley);
img.setBounds(0, 0, 60, 60);
txtVw.setCompoundDrawables(img, null, null, null);
or
Drawable img = getContext().getResources().getDrawable(R.drawable.smiley);
txtVw.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null);
or
txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Simply you can try this also
txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Kotlin Version
Use below snippet to add a drawable left to the button:
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_favorite_white_16dp)
button.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
Important Point in Using Android Vector Drawable
When you are using an android vector drawable and want to have backward compatibility for API below 21, add the following codes to:
In app level build.gradle:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
In Application class:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
}
}
myEdtiText.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
For me, it worked:
button.setCompoundDrawablesWithIntrinsicBounds(com.example.project1.R.drawable.ic_launcher, 0, 0, 0);
Worked for me. To set drawable at the right
tvBioLive.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close_red_400_24dp, 0)
If you are using drawableStart, drawableEnd, drawableTop or drawableBottom; you must use "setCompoundDrawablesRelativeWithIntrinsicBounds"
edittext.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.anim_search_to_close, 0)
I did this:
// Left, top, right, bottom drawables.
Drawable[] drawables = button.getCompoundDrawables();
// get left drawable.
Drawable leftCompoundDrawable = drawables[0];
// get new drawable.
Drawable img = getContext().getResources().getDrawable(R.drawable.ic_launcher);
// set image size (don't change the size values)
img.setBounds(leftCompoundDrawable.getBounds());
// set new drawable
button.setCompoundDrawables(img, null, null, null);
as #Jérémy Reynaud pointing out, as described in this answer, the safest way to set the left drawable without changing the values of the other drawables (top, right, and bottom) is by using the previous values from the button with setCompoundDrawablesWithIntrinsicBounds:
Drawable leftDrawable = getContext().getResources()
.getDrawable(R.drawable.yourdrawable);
// Or use ContextCompat
// Drawable leftDrawable = ContextCompat.getDrawable(getContext(),
// R.drawable.yourdrawable);
Drawable[] drawables = button.getCompoundDrawables();
button.setCompoundDrawablesWithIntrinsicBounds(leftDrawable,drawables[1],
drawables[2], drawables[3]);
So all your previous drawable will be preserved.
Might be helpful:
TextView location;
location=(TextView)view.findViewById(R.id.complain_location);
//in parameter (left,top,right,bottom) any where you wnat to put
location.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.arrow,0);
Add a Kotlin Extension
If you are going to be doing this frequently, adding an extension makes your code more readable. Button extends TextView; use Button if you want to be more narrow.
fun TextView.leftDrawable(#DrawableRes id: Int = 0) {
this.setCompoundDrawablesWithIntrinsicBounds(id, 0, 0, 0)
}
To use the extension, simply call
view.leftDrawable(R.drawable.my_drawable)
Anytime you need to clear, don't pass a param or make another extension called removeDrawables
Following is the way to change the color of the left icon in edit text and set it in left side.
Drawable img = getResources().getDrawable( R.drawable.user );
img.setBounds( 0, 0, 60, 60 );
mNameEditText.setCompoundDrawables(img,null, null, null);
int color = ContextCompat.getColor(this, R.color.blackColor);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
DrawableCompat.setTint(img, color);
} else {
img.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
Try this:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
fillButton[i].setBackground(getBaseContext().getResources().getDrawable(R.drawable.drawable_name));
}
else {
fillButton[i].setBackgroundColor(Color.argb(255,193,234,203));
}
Try this:
((Button)btn).getCompoundDrawables()[0].setAlpha(btn.isEnabled() ? 255 : 100);