Bitmap get croped when setting to Image inside scrollview - android

Scrollable Imageview, Image will be inside the scrollview in framelayout, and that layout will have fix size and image will be scrolled.
So When runtime changing size of framelayout, affecting bitmap and get crop from the bottom and the size of framelayout changed and also imageview size.
Only the problem with the bitmap croped
Layout.xml
<FrameLayout
android:id="#+id/frameLayout_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/grid">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:scrollbars="none">
<ImageView
android:id="#+id/image_picture"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ScrollView>
</FrameLayout>
Programatically changing the framelayout like
private void changeSizeOfImage(int width,int height){
mImageViewImage.destroyDrawingCache();
mImageViewImage.buildDrawingCache();
mFrameLayoutImageMain.setLayoutParams(new LinearLayout.LayoutParams(width, height));
if (bitmap != null) {
mImageViewImage.setImageBitmap(null);
mImageViewImage.setImageBitmap(bitmap);
}
}
}

Related

android scale ImageView parent clip scaled imageView

i have imageView inside LinearLayout the imageView scaled by
setScaleX(e);
setScaleY(e);
e is float value
and the xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="wrap_content"
android:clipChildren="false"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal">
<test.blabla.com.app.scledImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:id="#+id/scaled"
android:src="#drawable/emoji_1f3b0_64"
android:layout_gravity="center_vertical|center_horizontal" />
</LinearLayout>
now this image before i scale ImageView
after scale imageView
the parent LinearLayout not effected by scale and its height and width still same
i try use this for linearLayout while scale
parent.invalidate();
also i tried
parent. postInvalidate();
still same problem
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
>
<ImageView
android:id="#+id/iv_logo"
android:layout_width="180dp"
android:layout_height="180dp"
android:src="#drawable/app_logo"
android:contentDescription="#string/app_name"
/>
</LinearLayout>
Inside your activity set scale of ImageView like this:
btnScaleImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
iv_logo.setScaleX(0.5f);
iv_logo.setScaleY(0.5f);
}
});
i solve it by scale width and height now parent width and height changed when its child size changed
parent.invalidate();

setImageBitmap() modifies the predifined layout

I prepared a layout with 2 images of same size in a vertical LinearLayout so both appear with exact same size in AS.
The layout is as follow:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/partner_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="#drawable/fake_background" />
<LinearLayout
android:id="#+id/partner_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="0dp">
<ImageView
android:id="#+id/imageGuide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="#string/logo_Site"
android:scaleType="centerInside"
android:src="#drawable/my_logo"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/partner_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="0dp"
>
<ImageView
android:id="#+id/partner_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
android:contentDescription="#string/logo_Site"
android:scaleType="centerInside"
android:src="#drawable/my_logo" />
</RelativeLayout>
</LinearLayout>
</FrameLayout>
<ListView android:id="#+id/left_drawer"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/white"
android:dividerHeight="1dp"
android:background="#F2F2F2"/>
<ListView android:id="#+id/right_drawer"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:choiceMode="singleChoice"
android:divider="#android:color/white"
android:dividerHeight="1dp"
android:background="#F2F2F2"/>
</android.support.v4.widget.DrawerLayout>
The RelativeLayouts are here because I will have some other objects in.
If I execute it on my device, everything is ok, I get the exact same rendering.
But now, I want to change the bottom logo with one downloaded from my server.
I download the exact same image and then, I set it like that:
ImageView partnerLogo = (ImageView) findViewById(R.id.partner_logo);
file = new File(getApplicationContext().getFilesDir(), "/partner/partnerLogo.png");
uri = Uri.fromFile(file);
bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
if (bitmap != null) {
partnerLogo.setImageBitmap(bitmap);
}
When I look at bitmap in the debugger, the image is 512x512 as expected.
But the result is that one:
Could you tell me why the layout is modified?
Edit
I made some tests to try to set both images programmatically and I discovered that using:
try {
bitmap = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
if (bitmap != null) {
partnerLogo.setImageBitmap(bitmap);
}
set an image smaller than using:
partnerLogo.setImageDrawable(getResources().getDrawable(R.drawable.my_logo));
But both images are exactly the same PNG images!?!
So I think the problem comes from setImageBimap() and not from the layout.
EDIT 2
According to many post about similar problems, it seems that Android needs a drawable to be able to scale it as needed.
That would confirm my experiment given in first EDIT.
So I tried that:
ImageView partnerLogo = (ImageView) findViewById(R.id.partner_logo);
file = new File(getApplicationContext().getFilesDir(), "/partner/partnerLogo.png");
uri = Uri.fromFile(file);
BitmapDrawable drawable = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), uri);
if (bitmap != null) {
drawable = new BitmapDrawable(getResources(), bitmap);
}
} catch (IOException e) {
e.printStackTrace();
}
if (bitmap != null) {
partnerLogo.setImageDrawable(drawable);
}
But that doesn't work better !?!
On your layout on the LinearLayout add android:weightSum="2"
On your both RelativeLayout containing a ImageView change android:layout_height="wrap_content" to android:layout_height="0dp"
But those RelativeLayout are superfluous you can remove it and put on the ImageView's
android:layout_height="0dp"
android:layout_weight="1"
This ensures that the vertical space will be divided between the two images
Just modified relevant code. Add it and check.
Modification Like:
Adding weightSum to LinearLayout
Giving equal weight to the LinearLayout's immediate children
Modified your LinearLayout (partner_layout ).
This is just modified piece of your XML file.
<LinearLayout
android:id="#+id/partner_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1"
android:orientation="vertical">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
android:padding="0dp">
<ImageView
android:id="#+id/imageGuide"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="#string/logo_Site"
android:scaleType="centerInside"
android:src="#drawable/my_logo"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/partner_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
android:padding="0dp">
<ImageView
android:id="#+id/partner_logo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
android:contentDescription="#string/logo_Site"
android:scaleType="centerInside"
android:src="#drawable/my_logo" />
</RelativeLayout>
</LinearLayout
Our first aim should be how to resolve the issue.It seems that it could be handled by your xml layout.
So in my suggestion if you are using relative layout try to fix width and height of your imageView.
Other wise try some other layout like tableLayout, frameLayout or gridLyout and try to change width and height of your imageview with various available option(match_parents/wrap_content etc or also try with fix size).and also add
android:scaleType="fitXY"
Hope this will resolve your issue.
When You set Images from Drawable then Android system Automatically resize that image accrding available width and height but when you set Any image using setImageBitmap() method it dose not resize and actual image shown.
Although the system performs scaling and resizing to make your
application work on different screens, you should make the effort to
optimize your application for different screen sizes and densities. In
doing so, you maximize the user experience for all devices and your
users believe that your application was actually designed for their
devices—rather than simply stretched to fit the screen on their
devices.
Find your solution and more details regarding Images,Bitmap scaling and resizing ,drawables in below links :
How to stop Android form automatically scaling drawables?
Supporting Multiple Screens
So the only solution I found is to scale the image by hand, based on the layout built with fake images.
And the code is based on the one found quiet a long time ago somewhere in SO:
final ImageView myLogo = (ImageView) findViewById(R.id.image_logo);
bitmap = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.my_logo_512x512);
final ImageView partnerLogo = (ImageView) findViewById(R.id.partner_logo);
file = new File(getApplicationContext().getFilesDir(), "/partner/partnerLogo.png");
uri = Uri.fromFile(file);
try {
bitmap2 = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
if (bitmap != null) {
ViewTreeObserver vto = myLogo.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
myLogo.getViewTreeObserver().removeOnPreDrawListener(this);
finalHeight = myLogo.getMeasuredHeight();
finalWidth = myLogo.getMeasuredWidth();
pictureWidth = bitmap.getWidth();
pictureHeight = bitmap.getHeight();
float ratioImage = (float)pictureWidth / (float)pictureHeight;
float ratioView = (float)finalWidth / (float)finalHeight;
if (ratioView > ratioImage) { // finalHeight is the limit
finalWidth = (int)((float)pictureWidth * ((float) finalHeight / (float) pictureHeight));
} else { // finalWidth is the limit
finalHeight = (int)((float)pictureHeight * ((float) finalWidth / (float) pictureWidth));
}
bitmap = Bitmap.createScaledBitmap(bitmap, finalWidth, finalHeight, false);
myLogo.setImageBitmap(bitmap);
if (bitmap2 != null) {
bitmap2 = Bitmap.createScaledBitmap(bitmap2, finalWidth, finalHeight, false);
partnerLogo.setImageBitmap(bitmap2);
}
return true;
}
});
}
I saw that a comic downvoted my question, I hope that next time he will motivate it.

Resize ImageView even if ScaleType

I have a problem, I'm trying to resize a ImageView and its parent container but the problem is that the ImageView has ScaleType:"matrix", and I cant`t resize the image or its container
this is my code:
public void resize() {
LayoutParams contet = relativeLayout.getLayoutParams();
LayoutParams photo = image.getLayoutParams();
int widPhoto = image.getWidth();
int hePhoto = image.getHeight();
photo.width = ((widPhoto * 6) / 2);
photo.height = ((hePhoto * 6) / 2);
contenedor.width = widPhoto * 2;
contenedor.height = hePhoto * 2;
relativeLayout.setLayoutParams(contenedor);
image.setLayoutParams(photo );
}
and my xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/containerImg"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="matrix" />
</RelativeLayout>
setLayoutParams() does nothing but remove the property ScaleType if I resize everything correctly, but I cant´t remove that property. Any way to resize? they could put the property ScaleType: NONE? thank you very much and sorry for my bad English
To resize your ImageView, I suggest to use FrameLayout:
<FrameLayout
android:id="#+id/fm_id"
android:layout_width="img_width"
android:layout_height="img_height"
... ...
>
<ImageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:layout_gravity="center"
android:gravity="center"
/>
</FrameLayout>
then you just need to resize 'img_width' and 'img_height' in your codes
I got the solution, if you are using the Layout ScaleType: matrix
you need to use matrix.setScale (); for Resizing

Adapt ImageView for show picture correctly

I have some pictures stored on internal storage, that have different sizes and i would like to show it inside a scrollview contains imageview. I would that in each dimension case (image wider than higher, image higher than wider, squared image) image occupy entire screen width.
But code i've write for do that doesn't work well. If an image is squared or higher than wider everithing works well, but not if image is wider than higher.
this is xml of scrollview
<RelativeLayout
....
>
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/linearInsideScroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</ScrollView>
</RelativeLayout>
and this is xml of single imageView that i will inflate inside layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!--
othed widget
-->
<ImageView
android:id="#+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
and this is how i fill my view (pics is a list object contains image informations):
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linearInsideScroll);
for (int i = 0; i < pics.size(); i++) {
View new_element = inflater.inflate(R.layout.single_element, null,
false);
if (pics.get(i).getWidth() > pics.get(i).getHeight()) {
imageView.getLayoutParams().width = width_px;
imageView.getLayoutParams().height = LayoutParams.WRAP_CONTENT;
} else if (pics.get(i).getWidth() < pics.get(i).getHeight()) {
imageView.getLayoutParams().height = height_px;
imageView.getLayoutParams().width = LayoutParams.MATCH_PARENT;
}
else {
imageView.getLayoutParams().height = width_px;
imageView.getLayoutParams().width = width_px;
}
linearLayout.addView(new_element);
}
For the imageView, set scaleType.
http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

ImageView with no source does not honor layout, adding source does not repair layout

My base layout is a ListView of LinearLayouts, and each item in the grid is the FrameLayout below. I am downloading an image to the ImageView. Prior to the image being loaded, there is no content and the layout is shrunk to the height of the small ProgressBar (first problem), when I expect it to be 240dp or 120dp. After the image is placed in the view, the layout does not adjust (second problem) and the height remains the shrunken dimension of a small ProgressBar.
loading image code:
#Override
public View getView(View convertView) {
// ...
// set up holder
// ...
new GetPhotoTask().execute(holder.my_tile_image, holder.my_loading, my_media_url);
holder.my_tile_image.setVisibility(View.INVISIBLE);
holder.my_loading.setVisibility(View.VISIBLE);
holder.my_tile_label.setText(activityObject1.track.name);
// ...
}
private final class GetPhotoTask extends AsyncTask<Object, Void, Drawable> {
ImageView iv;
ProgressBar pb;
#Override
protected Drawable doInBackground(Object... params) {
iv = (ImageView) params[0];
pb = (ProgressBar) params[1];
return new BitmapDrawable(getResources(), loadAsset(params[2]).media_url, true));
}
#Override
protected void onPostExecute(Drawable result) {
super.onPostExecute(result);
pb.setVisibility(View.GONE);
iv.setImageDrawable(result);
iv.setVisibility(View.VISIBLE);
}
}
the main xml:
<ListView
android:id="#+id/my_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="2dp" />
the xml for each row:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_row_type_3"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="240dp"
android:weightSum="3" >
<include layout="#layout/my_tile_layout"
android:id="#+id/my_tile_1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
<LinearLayout
android:id="#+id/my_row_type_2"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:weightSum="2" >
<include layout="#layout/my_tile_layout"
android:id="#+id/my_tile_2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<include layout="#layout/my_tile_layout"
android:id="#+id/my_tile_3"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
the xml for row content:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_tile_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="2dp" >
<ImageView
android:id="#+id/my_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:contentDescription="#string/foo" />
<ProgressBar
android:id="#+id/my_loading"
style="?android:attr/progressBarStyleSmall"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
<TextView
android:id="#+id/my_tile_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/my_title"
android:layout_gravity="left|bottom" />
</FrameLayout>
Why does the initial layout shrink to the height of progress bar even though I've hard coded 240dp for each row? Why does setting a bitmap in the ImageView content not cause it to resize at that point either? The first question most important, as I believe it will nullify the second. Thanks in advance.
SOLUTION
To get the structure I want, I use RelativeLayout for the tiles (for layering ability), and for each row I am overriding the LinearLayout to enforce the sizing I want set for each row. As there is a potential for each tile's content to be larger or smaller than the view, this is screwing up my ability to rely on either centerCrop or fitCenter. So in my custom layout, I set the height to be proportional to the width of each row, and the mode of the MeasureSpec to be EXACTLY.
public final class MyRow3 extends LinearLayout {
// ...
#Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, makeMeasureSpec(getSize(widthMeasureSpec) * 2 / 3, MeasureSpec.EXACTLY));
}
I'm not sure why it isn't honouring it but why not do something like this instead:
Set an absolute height in your ImageView to guarantee some space.
<ImageView
android:layout_height="###dp"
/>
Then change the layout back to an auto adjusted state just before the image is loaded:
iv.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT ) );
To get the structure I want, I use RelativeLayout for the tiles (for layering ability), and for each row I am overriding the LinearLayout to enforce the sizing I want set for each row. As there is a potential for each tile's content to be larger or smaller than the view, this is screwing up my ability to rely on either centerCrop or fitCenter. So in my custom layout, I set the height to be proportional to the width of each row, and the mode of the MeasureSpec to be EXACTLY.
public final class MyRow3 extends LinearLayout {
// ...
#Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, makeMeasureSpec(getSize(widthMeasureSpec) * 2 / 3, MeasureSpec.EXACTLY));
}

Categories

Resources