Android drawables sizes not scaling - java

Alright, this seems like it can be a very confusing question but I'm going to try anyway.
I am developing an application right now, and the only thing that you should know is that there are two drawables in this application.
Both drawables have the same exact width. There is a background drawable that obviously goes in the background of the XML. And then theres an ImageView of a simple line. This line is a drawable aswell.
On some devices/emulators, the line is not the full width of its resolution. Despite the fact that both drawables have the same exact width. And both are viewed in the same portrait mode.
Is there any fix to this? Basically this line moves upwards and represents something important, but I can't have it be a different size than the background. I really don't fully understand why the background with a width of 600, and a line with a width of 600 isn't the same size on some devices. Despite putting both drawables in the Drawable folder, and not one for the different resolutions. I currently do not have any screenshots, I will make some if need be, but I hope someone knows why this problem is bugging me and if I am doing something wrong. Can I perhaps tell the application that its resolution must be 800x600, so that all devices that are capable of showing that many pixels, will do so? If this is possible, how do I do this? I hope someone is able to help
a newbie out :)
XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background"
android:gravity="top"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="-60dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
android:src="#drawable/line" />
</RelativeLayout>

Try setting the scaleType of the imageview to fitXY.
android:scaleType="fitXY"

Related

Setting ImageView width and height relative to text height

I have a ListView. On each row is an image and text. I want to scale image so it fits the row height i.e.
image shouldn't cause the row height is bigger
image height should be the same as the row height
image width should be calculated so the original width height ratio is maintained
All solutions that I figured out seem too complex for which I'd assume is a relatively common requirement so I'd like to check if I'm missing something - do you have an idea how to achieve this in a simpler way ?
The following are solutions I considered.
Solution 1:
Nested views for ListView item and set android:layout_height="match_parent".
Image is resized correctly but ImageView occupies the width as if it was not resized. (See the following picture. I added black background to see how much space occupies ImageView.)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView android:id="#+id/Image"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitStart"
android:background="#000000"
android:padding="1dp"/>
<TextView
android:id="#+id/Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#id/Image" />
</LinearLayout>
</RelativeLayout>
Solution 2:
Using
ViewTreeObserver observer = MyTextView.getViewTreeObserver()
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw(){
observer.removeOnPreDrawListener(this);
// Finding out height of TextView and then calculating width and height of image and setting size of ImageView. Of course, I could also get observer from ImageView and then just set width as height is correct
}
}
This seems like too complicated.
Solution 3:
Use, e.g., Paint.FontMetrics to calculate height but I'd also need to find out the font used (e.g., system one ...) Also ListView probably has some padding, etc. so kind of lots of things to retrieve.
Any other simpler solution please ?
Edit - clarification
The image has the max. size, which if reached, stops any further increasing of the size of ImageView.
If you are wanting to set the width and height of the ImageView based on the width and height, you can always get the width and height of the TextView programmatically, then implement your own algorithm to scale the ImageView accordingly.
To get the width and height from a textView, let's call it item_textView, it's fairly simple:
TextView item_textView = findViewById(R.id.item_textView);
int text_width = item_textView.getWidth();
int text_height = item_textView.getHeight();
At this point, you can perform whatever math you need to perform to scale the imageView down to the correct size. To set the size of the imageView:
my_imageView.getLayoutParams().width = text_width/2;
my_imageView.getLayoutParams().height = text_height/2;
Since you defined the parent linear layout height as wrap content it will take the size of its content and may vary based on its children element dimensions.
Try to define exact size for the image in your row layout.
If you can define its width and height as 40dp or 48dp you might be able to achieve your goal.
If all elements depend on each other's size you might be able to see variations. Try to define the avatar/image sizes in specific dp.
I tried to tweak your layout and got some results. Check out the following code.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:id="#+id/earthquake_magnitude"
android:layout_width="36dp"
android:layout_height="36dp"
android:background="#android:color/black"
android:fontFamily="sans-serif-medium"
android:src="#mipmap/ic_launcher" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="CHROME" />
</LinearLayout>

Android, ImageView, unwanted padding

I'm using something like that to present my logo or user profile picture:
<ImageView
android:id="#+id/logo"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/circle_bg"
android:src="#drawable/account_circle_grey"
android:layout_gravity="center_horizontal" />
#drawable/circle_bg:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#color/colorWhiteOpacity"/>
<size
android:width="100dp"
android:height="100dp"/>
</shape>
and #drawable/account_circle_grey is just an image I took from MaterialUI(the black 192x192) and used Final-Android-Resizer.
The problem is that I get something like that:
Basically the problem is that when the user clicks and pick a picture, I use glide to load the picture to replace the default #drawable/account_circle_gray but as you can see the padding is gone:
The picture takes the full space, as it should!, what I wanted to add is padding="5dp" and that will give a bit of padding between the background and the Glide loaded user picture, the problem is that there is already a weird padding to #drawable/account_circle_grey, I noticed however that not all drawables get the padding, when I chosen an old picture I used as a full page background I didn't get the padding, maybe I can force android to pick bigger picture, why do I get this padding?
Edit:
To clerify I used this tutorial to try all possible(scaleType+adjustViewBounds) values but nothing worked.
This is likely happening when you're using images that are physically smaller than the size of your ImageView. You can scale the image to fill the space or use a larger image. A mix of both is likely the best solution.
To achieve the former of the two, try this:
<ImageView
android:id="#+id/logo"
android:layout_width="90dp"
android:layout_height="90dp"
android:background="#drawable/circle_bg"
android:src="#drawable/account_circle_grey"
android:layout_gravity="center_horizontal"
android:scaleType="fitXY"
android:padding="5dp" />
Notice that I reduced the width and height by 2x the padding. That is because adding padding to a view increases the entire view's size by the size of the padding. In this particular case we're adding 5dp to the left, to the right, to the top, and to the left. This means we must subtract left and right from the width, and top and bottom from the height.
set the scaleType of your ImageView to centerFit or you can add only high dpi drawable to your drawables
thanks for the answers, the problem was so obvious but I made it complicated, although I used many "account_circle" images, what I didn't think was that they all comes with a transparent padding, so if the image is 192x192 for instance it's actual size is about 182x182 with 5px transparent padding on each side, anyway the simple solution is to open it on photoshop, go to Image>Trim and that's it.

Re-scaling layout to fit screen

I would like to scale my application layout to the screen size.
When I run it on a 4 inch emulator (but I don't display the actual screen size, so it looks larger)
It looks like this,
However when I run it on a larger emulator with the actual screen size, it looks like this,
My layout.xml is
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:animateLayoutChanges="false"
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=".MainActivity" >
Followed by the images and buttons.
The width and height of all images and buttons are,
android:layout_width="wrap_content"
android:layout_height="wrap_content"
I guess what I am asking is how to scale the layout to fit the size of the screen?
Like the way it fits the screen when the screen size is 4inch in emu but is not displaying to actual screen size.
As I want to be able to use the application on larger tablets.
You can use different layouts for different screen sizes.
And by the way...are these images from an emulator??
I hope you are not using "scale to actual size" while running your emulators...
Difference in pixel and resolution may also lead to this
In your relative layout, do this
android:layout_width="match_parent"
android:layout_height="match_parent"
This will make the layout fill the screen.
EDIT:
For the ImageView, use
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerInside"
This would stretch the image to fit the width (hopefully).
The connect ImageView is a tricky one. Not sure what will work for that. You'll need to experiment with the scaleType attribute.
For the buttons, increase the text size and set the layout_width as wrap_content. The buttons will get bigger.

How can I fill an ImageView in an Appwidget while mainiting the aspect ratio?

I have a simple widget containing an ImageView. I'd like to fetch an image from the web and display it in the ImageView while maintaining the aspect ratio.
Here's the layout definition for the widget:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/widget_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/quality_image"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_below="#+id/widget_icon"
android:layout_marginBottom="#dimen/widget_spacing"
android:scaleType="fitXY" />
</LinearLayout>
..and this is the image in question:
I'd like the image to always fit the height of the ImageView. This bit has been easy. If the width of the ImageView is less than that of the image, I don't mind if the image gets cropped horizontally as long as the aspect ratio is maintained. I've set the maximum size of the widget to never be more than the size of the image so we don't have to worry about cases when the height of the ImageView is more than the image.
I'm terribly lost with this and have begin wondering if this is even possible since there doesn't seem to be way to access the widget dimensions. Sometimes the most trivial things bog you down.
Assuming that part of this question is to maximize the height of the widget given the number of cells it occupies (per the fill_parent in the LinearLayout and given you’re open to cropping the width). I’ll ignore the cropping part of the question and provide an example that maintains a specified aspect ratio.
The best way I’ve found to maintain aspect ratio on an AppWidget at maximum height is to create an XML Drawable of a fixed aspect ratio, scale it down to the max height of the widget, and then tie the sides of the ImageView to it using a RelativeLayout. Example:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/widget_layout"
android:layout_width="wrap_content"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/aspectratio"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:adjustViewBounds="true"
android:src="#drawable/frame_aspect"
android:scaleType="fitCenter" >
</ImageView>
<ImageView
android:id="#+id/quality_image"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignLeft=”#id/aspectratio”
android:layout_alignRight=”#id/aspectratio”
android:layout_alignTop=”#id/aspectratio”
android:layout_alignBottom=”#id/aspectratio”
android:scaleType="fitCenter" >
</RelativeLayout>
Here is the layout for the drawable (frame_aspect.xml) that specifies the aspect ratio. Note - it is important that this shape is larger than your widget will ever be. The built in scaleType’s do a good job scaling down, but are not so good at scaling up.
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape = "rectangle">
<size
android:width="1000px"
android:height="500px"/>
</shape>
Now that you have a widget with quality_image scaled to the maximum height for a given aspect ratio, you can play with the scaleType on the ImageView to determine what if any cropping is best.

How to set "absolute" area gradient?

See the image below. The gradient is painted incorrectly, and the vertical black lines are just ugly.
How do I create a gradient that stretches from min to max? E.g. If I have a scale from 0 to 100 I want my area to use N of these 0..100 gradient values.
How do I remove the vertical black lines?
UPDATE: The provided answer works, except that I get this artifact:
UPDATE 2: This only happens when using ONE LinearLayout as shown below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/chart_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="3dip" >
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Then the TChart is added to chart_layout. Bam! Offset error :)
How do I create a gradient that stretches from min to max? E.g. If I have a scale from 0 to 100 I want my area to use N of these 0..100 gradient values.
I want the gradient to fade from minimum to maximum (0 to 100 in this case). So in the image above, points at 80 would have the 80th gradient color (almost green). Points at 50 would have the 50th gradient color (yellow). I believe you need a new gradient type: SYMMETRICRECTGRADIENT
The Area series draws the segments one before the next, and the area below each segment with each of these segments. That's why the Area series can't draw a uniform gradient. However, the other versions of TeeChart have the GradientRelative that does what you request when it's set to false. I've added to the wish list the possibility to implement this property (and the functions associated) to the Java version (TJ71016477).
In the meanwhile, you could use the SeriesBand tool to do it. Here it is an example:
tChart1.getAspect().setView3D(false);
tChart1.getLegend().setVisible(false);
Area area1 = new Area(tChart1.getChart());
area1.fillSampleValues();
area1.setOrigin(0);
area1.setUseOrigin(true);
area1.getAreaLines().setVisible(false);
area1.getGradient().setVisible(false);
area1.setColor(Color.transparent);
SeriesBand band1 = new SeriesBand(tChart1.getChart());
band1.setSeries(area1);
band1.getGradient().setVisible(true);
band1.getGradient().setDirection(GradientDirection.VERTICAL);
band1.getGradient().setStartColor(Color.green);
band1.getGradient().setMiddleColor(Color.yellow);
band1.getGradient().setUseMiddle(true);
band1.getGradient().setEndColor(Color.red);
This is what I get with the code above:
UPDATE: I've reproduced the strange artifact issue. I've added to the wish list to be further investigated (TJ71016541).
In the meanwhile, using a second LinearLayout just for the chart seems to work fine.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="3dip" >
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="#+id/chart_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout>
Another way around this, as said in the comments, is hiding the area line and making visible the SeriesBand pen:
area1.getLinePen().setVisible(false);
band1.getPen().setVisible(true);
How do I create a gradient that stretches from min to max? E.g. If I
have a scale from 0 to 100 I want my area to use N of these 0..100
gradient values.
I am afraid isn't possible do it using 0...100 gradients depending the scale, so the gradient of area is distributed throughout area using start, middle and end colors to draw the gradient.
How do I remove the vertical black lines?
To remove the vertical black lines, you only need set false the Area lines.
I hope will helps.
Thanks,

Categories