How to handle ImageView setImageResource difference from setImageDrawable - android

So after tons of frustrations with trying to stretch my image properly to width I realise my real problem is that setImageResource acts different from setImageDrawable (which I'm trying to use). XML below gives me perfect width, aspect ratio stretched image with setImageResource but with setImageDrawable the image is not stretched to the width, any suggestions to how I should handle the problem? I use setImageDrawable because I get the image from the internet alternatives are welcome :)
<ImageView
android:id="#+id/item_image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"/>
Oh and I've tryed scaletype, the one giving best results was centercrop but it crops which isn't desired.

This issue is really stale but in case anyone comes across it, the problem has to do with not quite a bug, but a bad implementation decision in versions of Android prior to 18. If you target 18+ you probably won't see this issue. However I'm currently targeting enterprise owned tablets at 16.
The solution is to create a superclass of ImageView that overrides onMeasure to enforce the aspect ratio:
class MyImageView extends ImageView {
public MyImageView(Context context) {
super(context);
}
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
float iwidth = (float) View.MeasureSpec.getSize(widthMeasureSpec);
float swidth = (float) getDrawable().getIntrinsicWidth();
float sheight = (float) getDrawable().getIntrinsicHeight();
float iheight = sheight / swidth * iwidth;
setMeasuredDimension((int)iwidth, (int)iheight);
}
}
In your layout:
<com.mypackage.MyImageView layout_width="match_parent" etc... />
If you target Android 18+ adjustViewBounds should work as expected.

you just make change in xml ImageView
android:layout_width="fill_parent"
android:layout_hight="fill_parent"

One fix I've found is to use a bitmap as setImageBitmap apparently works similar to setImageResource. I'm still open to other suggestions.

Your image view's width is fill_parent so if your image's width is not enough then it will be stretched.If you dont want to use fill_parent just replace the width "wrap_content".
<ImageView
android:id="#+id/item_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"/>

Related

Android studio how can i image size all screen

I have an image and ImageView of width 45dp & height 45dp. If I use my phone this image looks good but on another phone image seems very small. If you use picture converter and put xhdpi xxhdpi... the picture is still small.
(I want to get the same experience in all screen size. Example, in pixel 2 width 45dp height 45dp looks very good, Nexus width 65dp height 65dp very good, Samsung tab3 100dp looks very good. How can I do this?
Sorry for my poor English.
In the Dimens package of your application under res folder, use separate dimen values like dimens-ldpi, dimens-hdpi, dimens-mdpi, dimens-xhdpi, dimens-xxhdpi, dimens-xxxhdpi.
Create a value in each file and use different values for them.
Or, you can visit this question. There's multiple solution mentioned with example.
You need to maintain the aspect ratio of image view by calculating the ratio of screen width and height .
Create a Java File , say ProportionalImageView :
public class ProportionalImageView extends ImageView {
public ProportionalImageView(Context context) {
super(context);
}
public ProportionalImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ProportionalImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable d = getDrawable();
if (d != null) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = w * d.getIntrinsicHeight() / d.getIntrinsicWidth();
setMeasuredDimension(w, h);
}
else super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
then use this image View in your xml file :
<com.example.ProportionalImageView
android:layout_width="matchParent"
android:layout_height="wrapContent"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="#mipmap/img" />
Here , replace com.example. with your package name Hope it helps

Setting layout_height equal to layout_width="match_parent" in a layout file

The title says it all. I need to create a square sized View which height depends entirely from size of the mobile devices width (layout_width="match_parent").
Is it possible to specify layout_height="...equals to width..." from Android's .xml file or I have to do this at runtime?
You could resize the view programmatically by extending it and using your custom class in the xml instead. For example, I will extend the ImageView class and will return a square image(by changing the height to the size of the width):
public class SquareImageView extends ImageView {
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Allows the view to resize
* {#inheritDoc}
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width, width); //setting height same as width here
}
}
As mentioned, using this class would always result in a square image, where the height is equal to the width.
To use it in layout file:
<com.packagename.SquareImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
However, you have to take care of cases such as the device is in landscape, this way you'll have the width much greater than the height, so the view won't fit.

Android custom view's padding when scroll

I wrote a custom text view(it doesn't matter what kind of view actually) that extends from View. I added padding to this view in my XML document and read these padding and pass it to super to apply these padding. And in my onDraw and onMeasure I also took these padding into consideration and everything works just fine.
EXCEPT, if I scroll this view via the method View.scrollTo(), the padding no longer works. By saying no longer works, I mean the content that drawn on canvas doesn't respect the view's padding, like the images shown below:
I want to know if there's any workaround on this?(PS: don't tell me to use TextView instead of making my own. I'm doing this for some reason, the only problem I want to solve here is just the padding stuff, not some brilliant alternatives, thanks!)
EDIT:
my xml
<com.example.custom.MyTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text_area"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/text_bg"
android:padding="10dp"/>
and in my constructor:
public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// by calling super, the super class will take care of the paddings
// internal, and after this, I just have to get the paddings by
// getPaddingTop(),getPaddingLeft(),getPeddingRight(),getPaddingBottom() etc.
}
and in my onMeasure:
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
......
setMeasuredDimension(getPaddingLeft()+contentWidth+getPaddingRight()
,getPaddingTop()+contentHeight+getPaddingBottom());
//whereas the contentWidth and contentHeight is determined by the widthMeasureSpec
// and heightMeasureSpec and some certain logic inside the view.
// I don't think this will cause the view's content to exceed the conten area
}
and in my onDraw:
public void onDraw(Canvas canvas){
Path path = new Path();
for(String eachLine: text){
path.moveTo(startX,startY);
path.lineTo(endX,endY);
canvas.drawTextOnPath(eachLine,path,0,0,painter);
...
}
....
//the startX,startY,endX, endY has already took the padding into consideration.
//*NOTE: The only solution that I can think of is that I control this
//drawing logic according to the padding. But this approach still won't fix the
//problem, for example: what if I scroll half line height? How do I draw the
//half of the line? So there must be some other approach that I don't know.
}

Rotating an image around a specified point doesn't work! (Android)

I'm rotating an ImageView with postRotate(float degrees, float px, float py), setting px and py to a few differnt values including (0,0) and (imgView.getHeight(),imgView.getWidth()) but it refuses to rotate around any other point than the center. I'm wondering whether it's got anything to do with the fact that my gravity is center in the LinearLayout?
My layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<ImageView
android:id="#+id/imageTraj"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:src="#drawable/impactangle" />
How I'm rotating the image:
matrix.postRotate(degrees,imageView.getHeight(),imageView.getWidth());
imageView.setImageBitmap(Bitmap.createBitmap(imageScaled, 0, 0,
imageScaled.getWidth(), imageScaled.getHeight(), matrix, true));
PS I've noticed there are a few similar questions, but none of them have suitable answers.
I am using a custom ImageView where I set the angle rotation.
public class CompassImage extends ImageView {
private float angleRotation;
public CompassImage(Context context) {
super(context);
}
public CompassImage(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CompassImage(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setAngleRotation(float angleRotation) {
this.angleRotation = angleRotation;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Rect clipBounds = canvas.getClipBounds();
canvas.save();
canvas.rotate(angleRotation, clipBounds.exactCenterX(), clipBounds.exactCenterY());
super.onDraw(canvas);
canvas.restore();
}
}
If you play around with clipBounds you may find that helpful.
A slight "hack", you could probably adjust the image size using something like Paint.net or Gimp, depending on your OS. That would make the image appear to spin on another point. This solution would be pointless if you are planning on using a lot of images though. This is a spinning cube tutorial using opengl.

Android: GridView width not wrapping to content?

I am trying to display a GridView in a Dialog. Despite all my efforts, the GridView width grows to the entire screen, instead of wrapping to the columns. The layout and an image depicting the issue are below (I set a background color for the GridView to illustrate the issue).
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/colorgridview"
android:background="#FF00CCBB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="4"
android:verticalSpacing="5dp"
android:horizontalSpacing="5dp"
android:columnWidth="70dp"
android:stretchMode="none"
/>
I know that this post is a bit outdated. But if someone needs a solution to this, this answer may come in handy.
It is possible to set the view's width after screen measurement.
To do this:
Let your class implement the OnGlobalLayoutListener.
The screen is measured when the onGlobalLayout method is called. We can do our magic here.
GridView.getLayoutParams().width = ....
edit:
I wasn't very clear on how to add the onGlobalLayoutListener. See plugmind's post, he shows how to add it.
Can't figure out how to get view/layout width/height
Kind regards,
Bram
I think you should use android:layout_width="fill_parent" instead of android:layout_width="wrap_content" because wrap content use the minimum place it needs. On the other hand, fill_parent use all space needed. More over you should get rid of "android:columnWidth="70dp".
It's certainly possible to set a fixed layout_width (in dp). Since the number of your columns is also fixed, could this be a workaround for you?
Had the same problem...
I solved it with overridden onMeasure()
public class GridViewEx extends GridView {
private int mRequestedNumColumns = 0;
public GridViewEx(Context context) {
super(context);
}
public GridViewEx(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridViewEx(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void setNumColumns(int numColumns) {
super.setNumColumns(numColumns);
if (numColumns != mRequestedNumColumns) {
mRequestedNumColumns = numColumns;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mRequestedNumColumns > 0) {
int width = (mRequestedNumColumns * getColumnWidth())
+ ((mRequestedNumColumns-1) * getHorizontalSpacing())
+ getListPaddingLeft() + getListPaddingRight();
setMeasuredDimension(width, getMeasuredHeight());
}
}
}

Categories

Resources