Android: Scale a Drawable or background image? - android

On a layout I want to scale the background image (keeping its aspect ratio) to the space allocated when the page gets created. Does anyone have an idea how to do this?
I am using layout.setBackgroundDrawable() and a BitmapDrawable() to set gravity for clipping and filling, but don't see any option for scaling.

To customize background image scaling create a resource like this:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center"
android:src="#drawable/list_bkgnd" />
Then it will be centered in the view if used as background. There are also other flags: http://developer.android.com/guide/topics/resources/drawable-resource.html

Haven't tried to do exactly what you want, but you can scale an ImageView using android:scaleType="fitXY"
and it will be sized to fit into whatever size you give the ImageView.
So you could create a FrameLayout for your layout, put the ImageView inside it, and then whatever other content you need in the FrameLayout as well w/ a transparent background.
<FrameLayout
android:layout_width="fill_parent" android:layout_height="fill_parent">
<ImageView
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:src="#drawable/back" android:scaleType="fitXY" />
<LinearLayout>your views</LinearLayout>
</FrameLayout>

There is an easy way to do this from the drawable:
your_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#color/bg_color"/>
<item>
<bitmap
android:gravity="center|bottom|clip_vertical"
android:src="#drawable/your_image" />
</item>
</layer-list>
The only downside is that if there is not enough space, your image won't be fully shown, but it will be clipped, I couldn't find an way to do this directly from a drawable. But from the tests I did it works pretty well, and it doesn't clip that much of the image. You could play more with the gravity options.
Another way will be to just create an layout, where you will use an ImageView and set the scaleType to fitCenter.

Use image as background sized to layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/imgPlaylistItemBg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:maxHeight="0dp"
android:scaleType="fitXY"
android:src="#drawable/img_dsh" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</FrameLayout>

To keep the aspect ratio you have to use android:scaleType=fitCenter or fitStart etc. Using fitXY will not keep the original aspect ratio of the image!
Note this works only for images with a src attribute, not for the background image.

When you set the Drawable of an ImageView by using the setBackgroundDrawable method, the image will always be scaled. Parameters as adjustViewBounds or different ScaleTypes will just be ignored. The only solution to keep the aspect ratio I found, is to resize the ImageView after loading your drawable. Here is the code snippet I used:
// bmp is your Bitmap object
int imgHeight = bmp.getHeight();
int imgWidth = bmp.getWidth();
int containerHeight = imageView.getHeight();
int containerWidth = imageView.getWidth();
boolean ch2cw = containerHeight > containerWidth;
float h2w = (float) imgHeight / (float) imgWidth;
float newContainerHeight, newContainerWidth;
if (h2w > 1) {
// height is greater than width
if (ch2cw) {
newContainerWidth = (float) containerWidth;
newContainerHeight = newContainerWidth * h2w;
} else {
newContainerHeight = (float) containerHeight;
newContainerWidth = newContainerHeight / h2w;
}
} else {
// width is greater than height
if (ch2cw) {
newContainerWidth = (float) containerWidth;
newContainerHeight = newContainerWidth / h2w;
} else {
newContainerWidth = (float) containerHeight;
newContainerHeight = newContainerWidth * h2w;
}
}
Bitmap copy = Bitmap.createScaledBitmap(bmp, (int) newContainerWidth, (int) newContainerHeight, false);
imageView.setBackgroundDrawable(new BitmapDrawable(copy));
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
imageView.setLayoutParams(params);
imageView.setMaxHeight((int) newContainerHeight);
imageView.setMaxWidth((int) newContainerWidth);
In the code snippet above is bmp the Bitmap object that is to be shown and imageView is the ImageView object
An important thing to note is the change of the layout parameters. This is necessary because setMaxHeight and setMaxWidth will only make a difference if the width and height are defined to wrap the content, not to fill the parent. Fill parent on the other hand is the desired setting at the beginning, because otherwise containerWidth and containerHeight will both have values equal to 0.
So, in your layout file you will have something like this for your ImageView:
...
<ImageView android:id="#+id/my_image_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
...

This is not the most performant solution, but as somebody suggested instead of background you can create FrameLayout or RelativeLayout and use ImageView as pseudo background - other elements will be position simply above it:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<ImageView
android:id="#+id/ivBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:scaleType="fitStart"
android:src="#drawable/menu_icon_exit" />
<Button
android:id="#+id/bSomeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="61dp"
android:layout_marginTop="122dp"
android:text="Button" />
</RelativeLayout>
The problem with ImageView is that only scaleTypes available are:
CENTER, CENTER_CROP, CENTER_INSIDE, FIT_CENTER,FIT_END, FIT_START, FIT_XY, MATRIX
(http://etcodehome.blogspot.de/2011/05/android-imageview-scaletype-samples.html)
and to "scale the background image (keeping its aspect ratio)" in some cases, when you want an image to fill the whole screen (for example background image) and aspect ratio of the screen is different than image's, the necessary scaleType is kind of TOP_CROP, because:
CENTER_CROP centers the scaled image instead of aligning the top edge to the top edge of the image view and FIT_START fits the screen height and not fill the width. And as user Anke noticed FIT_XY doesn't keep aspect ratio.
Gladly somebody has extended ImageView to support TOP_CROP
public class ImageViewScaleTypeTopCrop extends ImageView {
public ImageViewScaleTypeTopCrop(Context context) {
super(context);
setup();
}
public ImageViewScaleTypeTopCrop(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public ImageViewScaleTypeTopCrop(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
private void setup() {
setScaleType(ScaleType.MATRIX);
}
#Override
protected boolean setFrame(int frameLeft, int frameTop, int frameRight, int frameBottom) {
float frameWidth = frameRight - frameLeft;
float frameHeight = frameBottom - frameTop;
if (getDrawable() != null) {
Matrix matrix = getImageMatrix();
float scaleFactor, scaleFactorWidth, scaleFactorHeight;
scaleFactorWidth = (float) frameWidth / (float) getDrawable().getIntrinsicWidth();
scaleFactorHeight = (float) frameHeight / (float) getDrawable().getIntrinsicHeight();
if (scaleFactorHeight > scaleFactorWidth) {
scaleFactor = scaleFactorHeight;
} else {
scaleFactor = scaleFactorWidth;
}
matrix.setScale(scaleFactor, scaleFactor, 0, 0);
setImageMatrix(matrix);
}
return super.setFrame(frameLeft, frameTop, frameRight, frameBottom);
}
}
https://stackoverflow.com/a/14815588/2075875
Now IMHO would be perfect if somebody wrote custom Drawable which scales image like that. Then it could be used as background parameter.
Reflog suggests to prescale drawable before using it. Here is instruction how to do it:
Java (Android): How to scale a drawable without Bitmap?
Although it has disadvantage, that upscaled drawable/bitmap will use more RAM, while scaling on the fly used by ImageView doesn't require more memory. Advantage could be less processor load.

The Below code make the bitmap perfectly with same size of the imageview. Get the bitmap image height and width and then calculate the new height and width with the help of imageview's parameters. That give you required image with best aspect ratio.
int bwidth=bitMap1.getWidth();
int bheight=bitMap1.getHeight();
int swidth=imageView_location.getWidth();
int sheight=imageView_location.getHeight();
new_width=swidth;
new_height = (int) Math.floor((double) bheight *( (double) new_width / (double) bwidth));
Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap1,new_width,new_height, true);
imageView_location.setImageBitmap(newbitMap)

What Dweebo proposed works. But in my humble opinion it is unnecessary.
A background drawable scales well by itself. The view should have fixed width and height, like in the following example:
< RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/black">
<LinearLayout
android:layout_width="500dip"
android:layout_height="450dip"
android:layout_centerInParent="true"
android:background="#drawable/my_drawable"
android:orientation="vertical"
android:padding="30dip"
>
...
</LinearLayout>
< / RelativeLayout>

One option to try is to put the image in the drawable-nodpi folder and set background of a layout to the drawable resource id.
This definitely works with scaling down, I haven't tested with scaling up though.

Kotlin:
If you needed to draw a bitmap in a View, scaled to FIT.
You can do the proper calculations to set bm the height equal to the container and adjust width, in the case bm width to height ratio is less than container width to height ratio, or the inverse in the opposite scenario.
Images:
// binding.fragPhotoEditDrawCont is the RelativeLayout where is your view
// bm is the Bitmap
val ch = binding.fragPhotoEditDrawCont.height
val cw = binding.fragPhotoEditDrawCont.width
val bh = bm.height
val bw = bm.width
val rc = cw.toFloat() / ch.toFloat()
val rb = bw.toFloat() / bh.toFloat()
if (rb < rc) {
// Bitmap Width to Height ratio is less than Container ratio
// Means, bitmap should pin top and bottom, and have some space on sides.
// _____ ___
// container = |_____| bm = |___|
val bmHeight = ch - 4 //4 for container border
val bmWidth = rb * bmHeight //new width is bm_ratio * bm_height
binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth.toInt(), bmHeight)
}
else {
val bmWidth = cw - 4 //4 for container border
val bmHeight = 1f/rb * cw
binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth, bmHeight.toInt())
}

you'll have to pre-scale that drawable before you use it as a background

You can use one of following:
android:gravity="fill_horizontal|clip_vertical"
Or
android:gravity="fill_vertical|clip_horizontal"

Related

Calculating view height using screen width and aspect ratio not working on 1440p screen

I am programatically changing the height of a ConstraintLayout and its contained ImageView in a RecyclerView's onBindViewHolder() method:
fun bind(model: CommunityOffer) {
itemView.communityImageCl.requestLayout()
itemView.communityImageIv.requestLayout()
val aspectRatioSplit = model.mediaAspectRatio.split(":")
val widthRatio = Integer.parseInt(aspectRatioSplit[0])
val heightRatio = Integer.parseInt(aspectRatioSplit[1])
if (model.mediaAspectRatio =="9:16" || model.mediaAspectRatio == "16:9"){
communityImageIv.scaleType = ImageView.ScaleType.FIT_XY
communityImageCl.layoutParams.height = (communityImageCl.width / widthRatio) * heightRatio
communityImageIv.layoutParams.height = (communityImageIv.width / widthRatio) * heightRatio
} else if (widthRatio == heightRatio){
communityImageIv.scaleType = ImageView.ScaleType.FIT_XY
communityImageCl.layoutParams.height = communityImageCl.width
communityImageIv.layoutParams.height = communityImageIv.width
} else{
communityImageIv.scaleType = ImageView.ScaleType.FIT_XY
communityImageCl.layoutParams.height = (communityImageCl.width / widthRatio) * heightRatio
communityImageIv.layoutParams.height = (communityImageIv.width / widthRatio) * heightRatio
}
}
View layout:
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/communityImageCv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="16dp"
app:cardCornerRadius="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/communityImageCl"
android:layout_width="match_parent"
android:layout_height="0dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/communityImageIv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/transparent"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="#color/alpha_grey" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
When the aspect ratio of an image, sent as metadata as a result of an API call, is conventional (16:9, 9:16, or 1:1), the image appears appropriately. However, a view whose aspect ratio is simply its dimensions (847:1280), gets scrunched into a square on 1440p phones, distorting the image
Is there something wrong with my formula for calculating height? The debugger lists the height of the image view and constraint layout as zero, I assume because that's how they are set in xml. The width of the view must take up the whole screen and the aspect ration must be kept, even if it stretches the photo.
First of all, I checked your screenshot, and can tell, that this distorted proportion is not exactly 1:1, which you can see here (I drew a red square over it):
I think it might be that as you divide the width value by a big integer, you get very small integer, then you multiply it (as int it would be missing precision) so the result might be unexpected.
Simply cast it to float as you calculate it, the cast the result back to int, and it should work.
... ((communityImageCl.width.toFloat() / widthRatio.toFloat()) * heightRatio).toInt()
P.S. I have never used Kotlin, so please someone edit above code if necessary.

How to populate Image inside ImageView by custom left and top coordinate | Android

I need to show some Images inside the Frame (Multiple Image Frames), I have left and top coordinates correspondence to each Image.
For example, I have Image coordinates 100 from left and 100 from top, So what i need to do is just to show the image inside the ImageView which starts from (100,100).
Can anyone tell me how could i do that without Bitmap, because i need to show the list of Frames with Multiple Images inside RecyclerView.
I have used TouchImageView.class for Zoom and Move feature for creating the Frame.
1. Below screen shot while i am selecting layout, as you can clearly seen that both the images are quite close to each other. I mean that i am selecting half portion of each image.
2. Next is the Home screen at which i need to replot that image, I am having the left and top coordinate of both the images.But How can i plot that Image inside ImageView by some custom x and y.
Code snippet for populating image inside ImageView from left and top -
img.setPadding((int) x, (int) y, 0, 0);
But still not working.
Please suggest me something, i have done google search but didn't got the appropriate solution for my requirement.
Suggestions really appreciated.
Many Thanks in advance.
Kind Regards.
Update: I have added a sample app at the end of this post to illustrate this concept.
Second update: Added some code to to sample app to accommodate xy scaling
I have changed the sample app to include code that will fit the image, whether smaller or larger than the ImageView, to the view size while respecting the aspect ratio. This may not be exactly what you are looking for, but it should get you into the ballpark. This is sample code, so there are assuredly other things to accommodate in an actual application. For instance, xScale and yScale could go negative in extreme cases. I am not sure what happens if they do, but a crash is probably the result, so a bounds check is in order.
If I understand what you are trying to do, you want a fixed size ImageView to show different parts of a
larger image by setting custom (x,y) coordinates of the image to sit at the (0,0) coordinate of the ImageView.
This is basically a cropping of the image across the top and left edges.
There are probably many different ways to do this and which one works best for you will depend on your exact needs,
but here is one way:
Use the following, or some variation, in your code:
float xOffset = -100;
float yOffset = -100;
ImageView imageView = (ImageView) findViewById(R.id.shiftedView);
Matrix matrix = new Matrix();
matrix.setTranslate(xOffset, yOffset);
imageView.setImageMatrix(matrix);
Set up your ImageView something like the following. The key here is android:scaleType="matrix"
<ImageView
android:id="#+id/shiftedView"
android:layout_width="200dp"
android:layout_height="match_parent"
android:background="#FF00CCCC"
android:scaleType="matrix"
android:src="#drawable/image" />
I hope this helps you.
Sample App
Here is a quick mock-up of this concept. This app is composed of the main activity and one layout. You will have to supply an image that is the source for the ImageView to see how this works.
The seven buttons will shift the image left, right, up and down on a click within the layout of the ImageView. The "Fit X" and "Fit Y" buttons will scale the image to the corresponding dimension available within the ImageView. The "Reset" button will set the image back to the original default setting of the ImageView.
MainActivity.java
package com.example.imageshift;
import android.graphics.Matrix;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ImageView imageView;
float xOffset = 0f;
float yOffset = 0f;
float xScale = 1.0f;
float yScale = 1.0f;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.shiftedView);
findViewById(R.id.shiftUp).setOnClickListener(this);
findViewById(R.id.shiftDown).setOnClickListener(this);
findViewById(R.id.shiftLeft).setOnClickListener(this);
findViewById(R.id.shiftRight).setOnClickListener(this);
findViewById(R.id.shiftReset).setOnClickListener(this);
findViewById(R.id.fitX).setOnClickListener(this);
findViewById(R.id.fitY).setOnClickListener(this);
}
public void doMatrixTransformations() {
Matrix matrix = new Matrix();
matrix.setTranslate(xOffset, yOffset);
matrix.postScale(xScale, yScale);
imageView.setImageMatrix(matrix);
}
#Override
public void onClick(View view) {
final int shiftAmount = 50;
switch (view.getId()) {
case R.id.shiftUp:
yOffset -= shiftAmount;
break;
case R.id.shiftDown:
yOffset += shiftAmount;
break;
case R.id.shiftLeft:
xOffset -= shiftAmount;
break;
case R.id.shiftRight:
xOffset += shiftAmount;
break;
case R.id.fitX:
xScale = (float) imageView.getWidth() / (
(float) imageView.getDrawable().getIntrinsicWidth() + xOffset);
yScale = xScale;
break;
case R.id.fitY:
yScale = (float) imageView.getHeight() /
((float) imageView.getDrawable().getIntrinsicHeight() + yOffset);
xScale = yScale;
break;
case R.id.shiftReset:
xOffset = 0;
yOffset = 0;
xScale = 1.0f;
yScale = 1.0f;
break;
}
doMatrixTransformations();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.imageshift.MainActivity">
<ImageView
android:id="#+id/shiftedView"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:padding="2dp"
android:scaleType="matrix"
android:src="#drawable/image" />
<Button
android:id="#+id/shiftUp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#id/shiftedView"
android:text="Up" />
<Button
android:id="#+id/shiftDown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/shiftUp"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#id/shiftedView"
android:text="Down" />
<Button
android:id="#+id/shiftLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/shiftDown"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#id/shiftedView"
android:text="Left" />
<Button
android:id="#+id/shiftRight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/shiftLeft"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#id/shiftedView"
android:text="Right" />
<Button
android:id="#+id/fitX"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/shiftRight"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#id/shiftedView"
android:text="Fit X" />
<Button
android:id="#+id/fitY"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/fitX"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#id/shiftedView"
android:text="Fit Y" />
<Button
android:id="#+id/shiftReset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/fitY"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#id/shiftedView"
android:text="Reset" />
</RelativeLayout>
It sounds like you want to take two images and create a new image based on some combination of the two images.
There are lots of different ways to go about this. The most straightforward ways involve using Bitmaps. There's two main approaches I can see that are straightforward to accomplish this.
Position your image views how you like within some common parent and create a bitmap of that parent to use as your resulting image.
Create a bitmap yourself by drawing the images of your imageviews based on your own calculations that should mimic the layout structure you have.
Since you already seem to be showing the two images on the screen in the way you want the resulting image to look like, the first is going to be the most straightforward and won't require you to redo the calculations that your layouts and imageviews are already performing.
What we're going to do is take advantage of the fact that every view will draw itself onto a canvas and at the end of the day is just translating itself into an image itself. To get a bitmap of your parent layout you can simply create a bitmap of the same size and then tell your parent layout to draw itself onto a canvas of the bitmap, like so:
private Bitmap getCombinedBitmap(View parentView) {
Bitmap result = Bitmap.createBitmap(parentView.getWidth(), parentView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
parentView.draw(canvas);
return result;
}
If however you would like to not be bound by just whatever the parent layout is drawing to the screen, you can create the bitmap you want by drawing your images onto a similar canvas. Here I have implemented the first layout from your question:
private Bitmap getCombinedBitmap(Bitmap a, Bitmap b) {
int aWidth = a.getWidth() / 2;
int bWidth = b.getWidth() / 2;
int resultHeight = a.getHeight() < b.getHeight()? a.getHeight() : b.getHeight();
Bitmap result = new Bitmap(aWidth + bWidth, resultHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Rect aRect = new Rect(0, 0, aWidth, resultHeight);
Rect aResultRect = new Rect(0, 0, aWidth, resultHeight);
canvas.drawBitmap(a, aRect, aResultRect);
Rect bRect = new Rect(0, 0, bWidth, resultHeight);
Rect bResultRect = new Rect(bWidth, 0, bWidth, resultHeight);
canvas.drawBitmap(b, bRect, bResultRect);
return result;
}
In this example I opted for clearer code rather than more optimised code. You can optimise this by not creating as many Rects, etc and generally simplifying your calculations. But you can use this approach to recreate any of your layouts onto a single bitmap, you would just need to change the calculations.
What we are doing is first creating a bitmap that has a width of half the first image plus half the second image, and the height of the smallest of the two images. We then take a section of the first image that is the left most half width wise and as high as the result height wise and we draw that onto our result. We then do the same with the second image except this time the section is the right most half width wise.
Hope this helps.
I have to admit that I'm not 100% sure I understand what you want to do. If I understand correctly, what you need is to put an ImageView inside another element (I show an example with FrameLayout but you could use LinearLayout or RelativeLayout too). Then you set the padding on the outer element.
<!-- we put the ImageView inside a Frame so that we can change -->
<!-- the padding size to create borders -->
<FrameLayout
android:layout_width="140dp"
android:layout_height="140dp"
android:id="#+id/image_frame"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/image_view"
/>
</FrameLayout>
Then in the code: (use frame instead of img)
FrameLayout frame = (FrameLayout)itemLayout.findViewById(R.id.image_frame);
frame.setPadding((int) x, (int) y, 0, 0);
If I understand what you want to do, this will do it.
You can do it easily by merging BitMaps.
I have created a test project which loads 2 image bitmaps with Glide and then merges them in one BitMap using canvas and then set it on any ImageView.
You can also save the image in a file on SD Card to avoid heavy calculation each time. It looks like this (Gif - https://github.com/hiteshsahu/Android-Merge-Bitmaps-With-Glide/blob/master/Art/demo.gif ):-
I have used a single Image view as the background of my Frame layout and I have used seek bar to change the relative position of the movie poster Raees. You can change start X and Y coordinates of either of the bitmaps using those seekbars.
How I did it:-
This is the code snippet of how I did it. It is self-explanatory
Glide.with(context)
.load(R.drawable.raees)
.asBitmap()
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
// Add Bitmap in Array and load next bitmap
arts[0] = resource;
Glide.with(context)
.load(R.drawable.raees_edited)
.asBitmap()
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource1, GlideAnimation<? super Bitmap> glideAnimation) {
// Both Bitmap loaded do the Merging
arts[1] = resource1;
//Set seekbars Max
satrtX1SeekBar.setMax(arts[0].getWidth());
satrtX2SeekBar.setMax(arts[1].getWidth());
satrtY1SeekBar.setMax(arts[0].getHeight());
satrtY2SeekBar.setMax(arts[1].getHeight());
Bitmap bmOverlay = Bitmap.createBitmap(arts[0].getWidth(), arts[0].getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmOverlay);
if (shouldDrawLeftHalf) {
// Rect(left, top, right, bottom)
canvas.drawBitmap(arts[0],
new Rect(0, 0, arts[0].getWidth() / 2, arts[0].getHeight()),
new Rect(0, 0, arts[0].getWidth() / 2, arts[0].getHeight()), null);
} else {
canvas.drawBitmap(arts[0], startX1, startY1, null);
}
if (shouldDrawRightHalf) {
// Rect(left, top, right, bottom)
canvas.drawBitmap(arts[1],
new Rect(arts[1].getWidth() / 2, 0, arts[0].getWidth(), arts[1].getHeight()),
new Rect(arts[1].getWidth() / 2, 0, arts[1].getWidth(), arts[1].getHeight()), null);
} else {
canvas.drawBitmap(arts[1], startX2, startY2, null);
}
background.setImageBitmap(bmOverlay);
// saveToDisk("Test", bmOverlay);
}
});
}
});
You can download entire project from My GitHub
https://github.com/hiteshsahu/Android-Merge-Bitmaps-With-Glide
Eventually i have found the solution of my question -
Thanks for all the help provided.
So, basically i have view height, view width, top coordinate, left coordinate, Original Image Height and Original Image Width.
I need to calculate the aspect factor regarding View and Image.
Here is the formula for that -
float newAspectFactor = 0;
if (viewHeight > viewWidth) {
//Aspect factor for Height
newAspectFactor = viewHeight / bean.getPostMedia().get(i).getImg_height();
} else {
//Aspect factor for Width
newAspectFactor = viewWidth / bean.getPostMedia().get(i).getImg_width();
}
float imgNewHeight = newAspectFactor * imageHeight;
float imgNewWidth = newAspectFactor * imageWidth;
Logger.logsError(TAG, " Image New Height : " + imgNewHeight);
Logger.logsError(TAG, " Image New Width : " + imgNewWidth);
if (imgNewHeight < viewHeight) {
newAspectFactor = viewHeight / bean.getPostMedia().get(i).getImg_height();
} else if (imgNewWidth < viewWidth) {
newAspectFactor = viewWidth / bean.getPostMedia().get(i).getImg_width();
}
Top and Left coordinates.
float x = 42.0;
float y = 0.0;
Magic starts from here.
Matrix m = img.getImageMatrix();
RectF drawableRect = new RectF(x,
y,
((x * newAspectFactor) + viewWidth) / newAspectFactor,
imageHeight);
RectF viewRect = new RectF(0,
0,
viewWidth,
viewHeight);
m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.FILL);
img.setImageMatrix(m);
img.setScaleType(ImageView.ScaleType.MATRIX);
imageLoaderNew.displayImage("IMAGE URL", img, optionsPostImg);

Android ImageView topCrop/bottomCrop scaletype?

I have a square ImageView which displays pictures of varying dimensions. I want to always maintain the original aspect ratio of the pictures and have no margin around the image (so that the image takes up the whole ImageView). For this, I am using the centerCrop scaleType on the ImageView. However, I want to make it so that if the top and bottom of the image are cut off (i.e.: the image is taller than it is wide), the image gets pulled towards the bottom of the container. So instead of having equal amounts of pixels cropped at the top and bottom, the image is flush with the top and sides of the ImageView and the bottom of the image has twice as much cropped off. Is this possible in xml, if not, is there a java solution?
You won't be able to do that with a regular ImageView and it's properties in xml. You can accomplish that with a proper scaleType Matrix, but tbh writing it is a pain in the ass. I'd suggest you use a respected library that can handle this easily. For example CropImageView.
You probably can't do this in layout. But it's possible with a piece of code like this:
final ImageView image = (ImageView) findViewById(R.id.image);
// Proposing that the ImageView's drawable was set
final int width = image.getDrawable().getIntrinsicWidth();
final int height = image.getDrawable().getIntrinsicHeight();
if (width < height) {
// This is just one of possible ways to get a measured View size
image.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int measuredSize = image.getMeasuredWidth();
int offset = (int) ((float) measuredSize * (height - width) / width / 2);
image.setPadding(0, offset, 0, -offset);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
image.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
image.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
}
Note that if your ImageView has predefined size (likely it has) then you need to put this size to dimen resources and the code will be even simpler:
ImageView image = (ImageView) findViewById(R.id.image2);
// For sure also proposing that the ImageView's drawable was set
int width = image.getDrawable().getIntrinsicWidth();
int height = image.getDrawable().getIntrinsicHeight();
if (width < height) {
int imageSize = getResources().getDimensionPixelSize(R.dimen.image_size);
int offset = (int) ((float) imageSize * (height - width) / width / 2);
image.setPadding(0, offset, 0, -offset);
}
See also:
findViewById()
getResources()

android- bitmap drawable as background image to fill screen but keep aspect ratio

I cant figure out how to use a bitmap as background image in a way that it is scaled to fill the screen but keeps the aspect ratio. So far I have only found the solution that I use an additional ImageView instead of a background image and use android:scaleType="centerCrop"
...
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:contentDescription="#string/desc_background"
android:scaleType="centerCrop"
android:src="#drawable/background"
/>
...
Nevertheless I would prefer to solve this by setting the activity background on the window
<style ...>
<item name="android:windowBackground">#drawable/background</item>
as I was told (and see) that this is much faster. (#drawable/background being a XML drawable)
Seems like such a common task yet I cant find a solution so far. Any advice would be highly appreciated.
Thanks
martin
Did you try to set adjustViewBounds property to true ?
http://developer.android.com/reference/android/widget/ImageView.html#attr_android:adjustViewBounds
I have stumbled upon the same problem a number of times in my projects and each time due to lack of time (and laziness) I would be satisfied with a less than optimum solution. But recently I found some time to crack down this particular issue. Here is my solution and I hope it helps you as well.
Bitmap scaleDownLargeImageWithAspectRatio(Bitmap image)
{
int imaheVerticalAspectRatio,imageHorizontalAspectRatio;
float bestFitScalingFactor=0;
float percesionValue=(float) 0.2;
//getAspect Ratio of Image
int imageHeight=(int) (Math.ceil((double) image.getHeight()/100)*100);
int imageWidth=(int) (Math.ceil((double) image.getWidth()/100)*100);
int GCD=BigInteger.valueOf(imageHeight).gcd(BigInteger.valueOf(imageWidth)).intValue();
imaheVerticalAspectRatio=imageHeight/GCD;
imageHorizontalAspectRatio=imageWidth/GCD;
Log.i("scaleDownLargeImageWIthAspectRatio","Image Dimensions(W:H): "+imageWidth+":"+imageHeight);
Log.i("scaleDownLargeImageWIthAspectRatio","Image AspectRatio(W:H): "+imageHorizontalAspectRatio+":"+imaheVerticalAspectRatio);
//getContainer Dimensions
int displayWidth = getWindowManager().getDefaultDisplay().getWidth();
int displayHeight = getWindowManager().getDefaultDisplay().getHeight();
//I wanted to show the image to fit the entire device, as a best case. So my ccontainer dimensions were displayWidth & displayHeight. For your case, you will need to fetch container dimensions at run time or you can pass static values to these two parameters
int leftMargin = 0;
int rightMargin = 0;
int topMargin = 0;
int bottomMargin = 0;
int containerWidth = displayWidth - (leftMargin + rightMargin);
int containerHeight = displayHeight - (topMargin + bottomMargin);
Log.i("scaleDownLargeImageWIthAspectRatio","Container dimensions(W:H): "+containerWidth+":"+containerHeight);
//iterate to get bestFitScaleFactor per constraints
while((imageHorizontalAspectRatio*bestFitScalingFactor <= containerWidth) &&
(imaheVerticalAspectRatio*bestFitScalingFactor<= containerHeight))
{
bestFitScalingFactor+=percesionValue;
}
//return bestFit bitmap
int bestFitHeight=(int) (imaheVerticalAspectRatio*bestFitScalingFactor);
int bestFitWidth=(int) (imageHorizontalAspectRatio*bestFitScalingFactor);
Log.i("scaleDownLargeImageWIthAspectRatio","bestFitScalingFactor: "+bestFitScalingFactor);
Log.i("scaleDownLargeImageWIthAspectRatio","bestFitOutPutDimesions(W:H): "+bestFitWidth+":"+bestFitHeight);
image=Bitmap.createScaledBitmap(image, bestFitWidth,bestFitHeight, true);
//Position the bitmap centre of the container
int leftPadding=(containerWidth-image.getWidth())/2;
int topPadding=(containerHeight-image.getHeight())/2;
Bitmap backDrop=Bitmap.createBitmap(containerWidth, containerHeight, Bitmap.Config.RGB_565);
Canvas can = new Canvas(backDrop);
can.drawBitmap(image, leftPadding, topPadding, null);
return backDrop;
}

How can I shrink the drawable on a button?

how can I make the drawable on a button smaller? The icon is too big, actually higher than the button. This is the code I am using:
<Button
android:background="#drawable/red_button"
android:drawableLeft="#drawable/s_vit"
android:id="#+id/ButtonTest"
android:gravity="left|center_vertical"
android:text="S-SERIES CALCULATOR"
android:textColor="#android:color/white"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:drawablePadding="10dp">
</Button>
The upper is how it should look, the lower how it looks right now.
I tried this but there is no image displayed. :-(
Resources res = getResources();
ScaleDrawable sd = new ScaleDrawable(res.getDrawable(R.drawable.s_vit), 0, 10f, 10f);
Button btn = (Button) findViewById(R.id.ButtonTest);
btn.setCompoundDrawables(sd.getDrawable(), null, null, null);
I have found a very simple and effective XML solution that doesn't require ImageButton
Make a drawable file for your image as below and use it for android:drawableLeft
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/half_overlay"
android:drawable="#drawable/myDrawable"
android:width="40dp"
android:height="40dp"
/>
</layer-list>
You can set the image size with android:width and android:height properties.
This way you could at least get the same size for different screens.
The drawback is that it is not exactly like fitXY which would scale image width to fit X and scale image height accordingly.
You should use a ImageButton and specify the image in android:src, and set android:scaletype to fitXY
Setting scaled drawable in code
Drawable drawable = getResources().getDrawable(R.drawable.s_vit);
drawable.setBounds(0, 0, (int)(drawable.getIntrinsicWidth()*0.5),
(int)(drawable.getIntrinsicHeight()*0.5));
ScaleDrawable sd = new ScaleDrawable(drawable, 0, scaleWidth, scaleHeight);
Button btn = findViewbyId(R.id.yourbtnID);
btn.setCompoundDrawables(sd.getDrawable(), null, null, null); //set drawableLeft for example
Buttons do not resize their inner images.
My solution does not require code manipulation.
It uses a layout with TextView and ImageView.
The background of the layout should have the red 3d drawable.
You may need to define the android:scaleType xml attribute.
Example:
<LinearLayout
android:id="#+id/list_item"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:padding="2dp" >
<ImageView
android:layout_width="50dp"
android:layout_height="fill_parent"
android:src="#drawable/camera" />
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:lines="1"
android:gravity="center_vertical"
android:text="Hello - primary" />
</LinearLayout>
BTW:
Counting on different resolution icons may result in a non predictable UI (icon too big or too small)
Text in textview (including in buttons) does not fill the component. This is an Android problem and I don't know how to solve it.
You can use it as an include.
Good luck
Use a ScaleDrawable as Abhinav suggested.
The problem is that the drawable doesn't show then - it's some sort of bug in ScaleDrawables. you'll need to change the "level" programmatically. This should work for every button:
// Fix level of existing drawables
Drawable[] drawables = myButton.getCompoundDrawables();
for (Drawable d : drawables) if (d != null && d instanceof ScaleDrawable) d.setLevel(1);
myButton.setCompoundDrawables(drawables[0], drawables[1], drawables[2], drawables[3]);
My DiplayScaleHelper, that works perfectly:
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ScaleDrawable;
import android.widget.Button;
public class DisplayHelper {
public static void scaleButtonDrawables(Button btn, double fitFactor) {
Drawable[] drawables = btn.getCompoundDrawables();
for (int i = 0; i < drawables.length; i++) {
if (drawables[i] != null) {
if (drawables[i] instanceof ScaleDrawable) {
drawables[i].setLevel(1);
}
drawables[i].setBounds(0, 0, (int) (drawables[i].getIntrinsicWidth() * fitFactor),
(int) (drawables[i].getIntrinsicHeight() * fitFactor));
ScaleDrawable sd = new ScaleDrawable(drawables[i], 0, drawables[i].getIntrinsicWidth(), drawables[i].getIntrinsicHeight());
if(i == 0) {
btn.setCompoundDrawables(sd.getDrawable(), drawables[1], drawables[2], drawables[3]);
} else if(i == 1) {
btn.setCompoundDrawables(drawables[0], sd.getDrawable(), drawables[2], drawables[3]);
} else if(i == 2) {
btn.setCompoundDrawables(drawables[0], drawables[1], sd.getDrawable(), drawables[3]);
} else {
btn.setCompoundDrawables(drawables[0], drawables[1], drawables[2], sd.getDrawable());
}
}
}
}
}
You can call setBounds on the "compound" drawables to modify the size of the image.
Try this code to autosize the drawable of your button:
DroidUtils.scaleButtonDrawables((Button) findViewById(R.id.ButtonTest), 1.0);
defined by this function:
public final class DroidUtils {
/** scale the Drawables of a button to "fit"
* For left and right drawables: height is scaled
* eg. with fitFactor 1 the image has max. the height of the button.
* For top and bottom drawables: width is scaled:
* With fitFactor 0.9 the image has max. 90% of the width of the button
* */
public static void scaleButtonDrawables(Button btn, double fitFactor) {
Drawable[] drawables = btn.getCompoundDrawables();
for (int i = 0; i < drawables.length; i++) {
if (drawables[i] != null) {
int imgWidth = drawables[i].getIntrinsicWidth();
int imgHeight = drawables[i].getIntrinsicHeight();
if ((imgHeight > 0) && (imgWidth > 0)) { //might be -1
float scale;
if ((i == 0) || (i == 2)) { //left or right -> scale height
scale = (float) (btn.getHeight() * fitFactor) / imgHeight;
} else { //top or bottom -> scale width
scale = (float) (btn.getWidth() * fitFactor) / imgWidth;
}
if (scale < 1.0) {
Rect rect = drawables[i].getBounds();
int newWidth = (int)(imgWidth * scale);
int newHeight = (int)(imgHeight * scale);
rect.left = rect.left + (int)(0.5 * (imgWidth - newWidth));
rect.top = rect.top + (int)(0.5 * (imgHeight - newHeight));
rect.right = rect.left + newWidth;
rect.bottom = rect.top + newHeight;
drawables[i].setBounds(rect);
}
}
}
}
}
}
Be aware, that this may not be called in onCreate() of an activity, because button height and width are not (yet) available there. Call this in on onWindowFocusChanged() or use this solution to call the function.
Edited:
The first incarnation of this function did not work correctly. It used userSeven7s code to scale the image, but returning ScaleDrawable.getDrawable() does not seem to work (neither does returning ScaleDrawable) for me.
The modified code uses setBounds to provide the bounds for the image. Android fits the image into these bounds.
If you want to use 1 image and display it in different size, you can use scale drawable ( http://developer.android.com/guide/topics/resources/drawable-resource.html#Scale ).
I am doing it as below. This creates a 100x100 size image in the button independent of the input image.
drawable.bounds = Rect(0,0,100,100)
button.setCompoundDrawables(drawable, null, null, null)
Not using ScaleDrawable either. Not using button.setCompoundDrawablesRelativeWithIntrinsicBounds() solved my problem, as that seems to use intrinsic bounds (source image size) instead of the bounds you just set.
You can use different sized drawables that are used with different screen densities/sizes, etc. so that your image looks right on all devices.
See here: http://developer.android.com/guide/practices/screens_support.html#support
Did you try wrapping your image in a ScaleDrawable and then using it in your button?
Here the function which I created for scaling vector drawables. I used it for setting TextView compound drawable.
/**
* Used to load vector drawable and set it's size to intrinsic values
*
* #param context Reference to {#link Context}
* #param resId Vector image resource id
* #param tint If not 0 - colour resource to tint the drawable with.
* #param newWidth If not 0 then set the drawable's width to this value and scale
* height accordingly.
* #return On success a reference to a vector drawable
*/
#Nullable
public static Drawable getVectorDrawable(#NonNull Context context,
#DrawableRes int resId,
#ColorRes int tint,
float newWidth)
{
VectorDrawableCompat drawableCompat =
VectorDrawableCompat.create(context.getResources(), resId, context.getTheme());
if (drawableCompat != null)
{
if (tint != 0)
{
drawableCompat.setTint(ResourcesCompat.getColor(context.getResources(), tint, context.getTheme()));
}
drawableCompat.setBounds(0, 0, drawableCompat.getIntrinsicWidth(), drawableCompat.getIntrinsicHeight());
if (newWidth != 0.0)
{
float scale = newWidth / drawableCompat.getIntrinsicWidth();
float height = scale * drawableCompat.getIntrinsicHeight();
ScaleDrawable scaledDrawable = new ScaleDrawable(drawableCompat, Gravity.CENTER, 1.0f, 1.0f);
scaledDrawable.setBounds(0,0, (int) newWidth, (int) height);
scaledDrawable.setLevel(10000);
return scaledDrawable;
}
}
return drawableCompat;
}
Using "BATCH DRAWABLE IMPORT" feature you can import custom size depending upon your requirement example 20dp*20dp
Now after importing use the imported drawable_image as drawable_source for your button
It's simpler this way
It is because you did not setLevel. after you setLevel(1), it will be display as u want
I made a custom button class to achieve this.
CustomButton.java
public class CustomButton extends android.support.v7.widget.AppCompatButton {
private Drawable mDrawable;
public CustomButton(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.CustomButton,
0, 0);
try {
float mWidth = a.getDimension(R.styleable.CustomButton_drawable_width, 0);
float mHeight = a.getDimension(R.styleable.CustomButton_drawable_width, 0);
Drawable[] drawables = this.getCompoundDrawables();
Drawable[] resizedDrawable = new Drawable[4];
for (int i = 0; i < drawables.length; i++) {
if (drawables[i] != null) {
mDrawable = drawables[i];
}
resizedDrawable[i] = getResizedDrawable(drawables[i], mWidth, mHeight);
}
this.setCompoundDrawables(resizedDrawable[0], resizedDrawable[1], resizedDrawable[2], resizedDrawable[3]);
} finally {
a.recycle();
}
}
public Drawable getmDrawable() {
return mDrawable;
}
private Drawable getResizedDrawable(Drawable drawable, float mWidth, float mHeight) {
if (drawable == null) {
return null;
}
try {
Bitmap bitmap;
bitmap = Bitmap.createBitmap((int)mWidth, (int)mHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return drawable;
} catch (OutOfMemoryError e) {
// Handle the error
return null;
}
}
}
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomButton">
<attr name="drawable_width" format="dimension" />
<attr name="drawable_height" format="dimension" />
</declare-styleable>
</resources>
Usage in xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.MainActivity">
<com.example.CustomButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="#drawable/ic_hero"
android:text="Avenger"
custom:drawable_height="10dp"
custom:drawable_width="10dp" />
</RelativeLayout>
I tried the techniques of this post but didnot find any of them so attractive. My solution was to use an imageview and textview and align the imageview top and bottom to the textview. This way I got the desired result. Here's some code:
<RelativeLayout
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="48dp" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignTop="#+id/textViewTitle"
android:layout_alignBottom="#+id/textViewTitle"
android:src="#drawable/ic_back" />
<TextView
android:id="#+id/textViewBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/textViewTitle"
android:layout_alignBottom="#+id/textViewTitle"
android:layout_toRightOf="#+id/imageView1"
android:text="Back"
android:textColor="#color/app_red"
android:textSize="#dimen/title_size" />
</RelativeLayout>
Using Kotlin Extension
val drawable = ContextCompat.getDrawable(context, R.drawable.my_icon)
// or resources.getDrawable(R.drawable.my_icon, theme)
val sizePx = 25
drawable?.setBounds(0, 0, sizePx, sizePx)
// (left, top, right, bottom)
my_button.setCompoundDrawables(drawable, null, null, null)
I suggest creating an extension function on TextView (Button extends it) for easy reuse.
button.leftDrawable(R.drawable.my_icon, 25)
// Button extends TextView
fun TextView.leftDrawable(#DrawableRes id: Int = 0, #DimenRes sizeRes: Int) {
val drawable = ContextCompat.getDrawable(context, id)
val size = context.resources.getDimensionPixelSize(sizeRes)
drawable?.setBounds(0, 0, size, size)
this.setCompoundDrawables(drawable, null, null, null)
}

Categories

Resources