How to programmatically set drawableLeft on Android button? - java

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);

Related

Vector drawable in any location within text view (not outside of it)

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.

Imebra library shows completely gray image for transfer syntax 1.2.840.10008.1.2.1

Iam trying to use Imebra library to display DICOM images in android. Iam using version 5.0 of the library.
The bitmap shown is completely gray, transfer syntax for image is 1.2.840.10008.1.2.1.For other supported transfer syntax i.e JPEG it works fine.
Also I am unable to add VOILUT transform functionality as mentioned in documentation it gives error cons tructor not found for VOILUT.
Below is the code Iam using, VOILUT transform part is giving constructor not found. if i remove VOILUT transform part things work fine but for image with transfer syntax 1.2.840.10008.1.2.1 it shows completely grey image
private Bitmap fromDicom(String filePath, int frameNumber){
// have been applied).
Image dicomImage = loadedDataSet.getImageApplyModalityTransform(frameNumber);
// Use a DrawBitmap to build a stream of bytes that can be handled by the
// Android Bitmap class.
com.imebra.TransformsChain chain = new com.imebra.TransformsChain();
if( com.imebra.ColorTransformsFactory.isMonochrome(dicomImage.getColorSpace()))
{
// Retrieve the VOIs (center/width pairs)
com.imebra.VOIs vois = loadedDataSet.getVOIs();
if(!vois.isEmpty())
{
// Get the first VOI setting from the dataset
chain.addTransform(new VOILUT(vois.get(0)));
}
else
{
// The dataset does not have any VOI setting, find the optimal one
com.imebra.SWIGTYPE_p_imebra__VOIDescription voiDescription = VOILUT.getOptimalVOI(dicomImage, 0, 0, dicomImage.getWidth(), dicomImage.getHeight());
chain.addTransform(new VOILUT(voiDescription));
}
}
DrawBitmap drawBitmap = new DrawBitmap(chain);
Memory memory = drawBitmap.getBitmap(dicomImage, drawBitmapType_t.drawBitmapRGBA, 4);
// Build the Android Bitmap from the raw bytes returned by DrawBitmap.
Bitmap renderBitmap = Bitmap.createBitmap((int)dicomImage.getWidth(), (int)dicomImage.getHeight(), Bitmap.Config.ARGB_8888);
byte[] memoryByte = new byte[(int)memory.size()];
memory.data(memoryByte);
ByteBuffer byteBuffer = ByteBuffer.wrap(memoryByte);
renderBitmap.copyPixelsFromBuffer(byteBuffer);
// Update the image
return renderBitmap;
}
After changing the code suggested by you, I don't find classes mentioned
VOIDescription instead i see class SWIGTYPE_p_imebra__VOIDescription should i use that class
There is one more error no getWidth() method available with vois.get(0).getWidth
One last Error i don't see class vois_t instead there is a class VOIs should VOIs be used
Thanks for the reponse
The VOILUT must be initialized with the proper contrast settings from the dataset like in the code below.
However, the dataset contains a VOI setting that is wrong (the window width is 0) so this file will be displayed correctly only if you use custom VOI settings or just use automatic settings when width is zero (see alternative code below which checks for width > 0).
Code that does not check for width:
if(com.imebra.ColorTransformsFactory.isMonochrome(dicomImage.getColorSpace());
{
// Retrieve the VOIs (center/width pairs)
com.imebra.vois_t vois = loadedDataSet.getVOIs();
if(!vois.isEmpty())
{
// Get the first VOI setting from the dataset
chain.addTransform(new VOILUT(vois.get(0)));
}
else
{
// The dataset does not have any VOI setting, find the optimal one
com.imebra.VOIDescription voiDescription = VOILUT.getOptimalVOI(dataSetImage, 0, 0, width, height);
chain.addTransform(new VOILUT(voiDescription));
}
}
Alternative code that checks if width is 0:
if(com.imebra.ColorTransformsFactory.isMonochrome(dicomImage.getColorSpace());
{
// Retrieve the VOIs (center/width pairs)
com.imebra.vois_t vois = loadedDataSet.getVOIs();
if(!vois.isEmpty() && vois.get(0).getWidth() > 0.1)
{
// Get the first VOI setting from the dataset
chain.addTransform(new VOILUT(vois.get(0)));
}
else
{
// The dataset does not have any VOI setting, find the optimal one
com.imebra.VOIDescription voiDescription = VOILUT.getOptimalVOI(dataSetImage, 0, 0, width, height);
chain.addTransform(new VOILUT(voiDescription));
}
}

Iterating over drawables in Android

In Android, I have only found answers as to how to open a single specific Drawable from MainActivity.java, but not how to iterate over each Drawable from res/drawables. The Drawables names do not follow any patterns (e.g. being numbered from 0 to 25), so the answer suggested here sadly doesn't solve my problem. Does anyone know how to do the latter?
Thank you in advance :)
First, put your drawables into an arrays
<array name="dashboard_item_menu_drawable">
<item>#drawable/ic_file_green</item>
<item>#drawable/ic_email_green</item>
<item>#drawable/ic_linear_scale_green</item>
<item>#drawable/ic_undo_green</item>
<item>#drawable/ic_check_circle_green</item>
<item>#drawable/ic_archive_green</item>
</array>
Then, iterate your array drawables
val icons = ArrayList<Int>()
val arr = resources.obtainTypedArray(R.array.dashboard_item_menu_drawable)
(0 until arr.length()).forEach {
// get resource id of each drawable
val icon = arr.getResourceId(it, -1)
icons.add(icon)
}
Next, recycles resource
arr.recycle()
Then you can use your drawable
iconView.setImageDrawable(ContextCompat.getDrawable(this, icons[index]))
If you want to iterate through drawables that have similar names like: image1, image2, ..., image10 you can do it like this:
for (int i = 0; i < 10; i++) {
int id = getResources().getIdentifier("image" + i, "drawable", getPackageName());
Drawable d = ContextCompat.getDrawable(this, id);
// your code here
}
The easiest way to do it is to put the names of your drawables in a String array:
String[] symbols = {"first_img", "second_img", "third_img", "fourth_img"};
Then iterate over them like this (I put the images into a GridLayout):
for(String symbol : symbols) {
int id = getResources().getIdentifier(symbol, "drawable", getPackageName());
ImageView img = new ImageView(this);
LinearLayout.LayoutParams imgParams = new LinearLayout.LayoutParams(300, 300);
imgParams.setMargins(30, 30, 30, 30);
img.setLayoutParams(imgParams);
img.setBackgroundResource(id);
symbolGrid.addView(img);
}

how to align text to top of a text view dynamically

I have hit a problem when trying to align my text to the top of a text view dynamically. I have a method that creates textviews dynamically. I have set the gravity of the text view to Gravity.TOP. Which a believe should place the text at the very top of the textView object. However when I run the project there is a gap of about 2 lines of text from the top of the object. I can work around this by changing the height of the textView but I would rather it loaded in an set the size depending on how much text there is too load into the textView.
Here is my function, it works well and does what it is supposed to do:
public void addItems(LinearLayout page,int id,String text,int row){
LinearLayout item = new LinearLayout(this);
item.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
TextView itemNum = new TextView(this);
//itemNum.setLayoutParams(new ViewGroup.LayoutParams(50,50));
itemNum.setWidth(50);
itemNum.setTextSize(40);
itemNum.setTextAppearance(getApplicationContext(), R.style.large_text);
itemNum.setLeft(0);
itemNum.setText(row+":");
LayoutParams numParams = new LinearLayout.LayoutParams(70, 70);
numParams.setMargins(25, 0, 0, 0);
TextView itemDetails = new TextView(this);
itemDetails.setLayoutParams(new ViewGroup.LayoutParams(150,LayoutParams.WRAP_CONTENT));
itemDetails.setText(text);
itemDetails.setWidth(100);
itemDetails.setLeft(5);
itemDetails.setRight(5);
itemDetails.setTop(0);
itemDetails.setVisibility(View.VISIBLE);
itemDetails.setGravity(itemDetails.getGravity() | Gravity.TOP);
itemDetails.setPadding(0,0,0,0);
Button delete = new Button(this);
//delete.setLayoutParams(new ViewGroup.LayoutParams(50,50));
delete.setText("Delete");
LayoutParams btnParams = new LinearLayout.LayoutParams(70, 70);
btnParams.setMargins(0, 0, 15, 0);
item.addView(itemNum,numParams);
item.addView(itemDetails);
item.addView(delete,btnParams);
page.addView(item);
Log.d("Loop","Loop is adding function in");
}
If anybody can see where I have gone wrong I would really appreciate it. The method above may seem very long winded but I am new to Java.
Not sure if it will help but here is my string to show in the textView:
String formatText = lat + ", " + lng + " /n" + result;

How do i clear the OSMdroid cache

I loaded the same tiles (Mapbox) into OSmdroid, but know when i modify it on the web, it changes in my app, but the former map still remaines in the cache, and is replace by the new map little by little.
I want to know how to delete the cache, programmatically, so it can load the tiles normally.
I've got the code to load it right here :
private void loadMap() {
String html = "http://a.tiles.mapbox.com/v3/myUsername.map-f1rhoycw/";
String name = "500x300";
XYTileSource freemap = new XYTileSource(name, null, 0, 16, 256, ".png", html);
map.setTileSource(freemap);
mapController = map.getController();
mapController.setZoom(16);
map.setMultiTouchControls(true);
}
Try this:
mMapView.getTileProvider().clearTileCache()

Categories