How to display the image with aspected ratio? - android

In my application I want to display the image with aspected ratio like the gallery.In my application I have to display the marker image on image.Because the marker image having dragging functionality.So that the following is the xml for that
<RelativeLayout
android:background="#000000"
android:layout_above="#+id/buttonlayout"
android:id="#+id/imagelayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:layout_centerInParent="true"
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</RelativeLayout>
</RelativeLayout>
And in my activity after select the image from gallery, In onactivityresult method the following code I am using.
try {
// bmGallayImage = decodeFile(selectedImagePath);
bmGallayImage = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImageUri);
bmRotated = InventorySubmitImagesActivity.rotateBitmap(bmGallayImage, orientation);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(bmRotated!=null){
Drawable dr = new BitmapDrawable(bmRotated);
old_width=bmRotated.getWidth();
old_height=bmRotated.getHeight();
Log.e("gal bitmap height and width",""+old_height+" "+old_width);
relImage.getLayoutParams().height = old_height;
relImage.getLayoutParams().width = old_width;
relImage.setBackgroundDrawable(dr);
}
relImage.removeAllViews();
imgMarker = new ImageView(this);
final RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
layoutParams.leftMargin = 0;
layoutParams.topMargin = 0;
relImage.addView(imgMarker, layoutParams);
imgMarker.setScaleType(ImageView.ScaleType.MATRIX);
bmdragImage=BitmapFactory.decodeResource(getResources(), R.drawable.image_marker);
imgMarker.setImageBitmap(bmdragImage);
In this code relImage is the referance of relative layout and imgMarker is the referance of image view. And the gallery image is set to the relative layout.And My device resolution is 480 by 800 and image resolution is 1920 by 1080.So this is the out put i am getting.
And gallery image view is like the bellow screen shot.
But my requirement is like the gallery image, i want to display the image with aspected ratio.So please suggest me how to do this. Thanks In Advance to all..

You can do this with FrameLayout put image view in this and put your marker ImageView like this http://chiuki.github.io/images/android-layout-101/frame-layout-center.png

Related

Scrolling images with ScrollView

Using the following XML and java code I add images taken with camera to LinearLayout within a ScrollView.
XML:
<HorizontalScrollView
android:layout_gravity="center_vertical"
android:scrollbars="none"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/detailsback"
android:layout_gravity="center_vertical"
android:id="#+id/imageSlider"
android:orientation="horizontal" >
</LinearLayout>
</HorizontalScrollView>
Java (runs in Fragment):
private void setTakePicButton(){
mTakePicButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mBitmap = mTextureView.getBitmap();
Date currentDateTime = Calendar.getInstance().getTime();
String filename = getFileName();
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream( filename);
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);// bmp is your Bitmap instance
ImageView imageView = new ImageView(getActivity());
imageView.setImageBitmap(mBitmap);
linearLayout.addView(imageView);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
});
}
Problem is whenever I add a pic to linearLayout (id:imageSlider) it is added with large margins like shows in the picture
I want the images to show in a sequence like in the following pic.
Solution 01
You can set the image to bounds using FIT_XY scale type
imgview.setScaleType(ImageView.ScaleType.FIT_XY);
You can find all the ScaleTypes here
Solution 02
If you are trying to view images like a list you can use a RecyclerView:
Create a List with RecyclerView
Solution 03
If you want to display the images side by side, Set layout_weight to imageView
This is how to do that programmatically, (The Last param is the weight )
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT,
1.0f
);
imageView.setLayoutParams(param);
If I understand correctly, the problem is that the image in the bottom is centered instead of outlined to the left? This might be caused by the wrap_content width for the linear layout.
I would also suggest you to use some sort of a list view instead of a LinearLayout and adding items manually. A RecyclerView would be a nice solution and is able to be set to horizontal as well.

Android ImageView resize height without loading image (like instagram, facebook)

The image I want to do is get the shape of the imageview before it comes to the screen.
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"/>
I did it this way but the imageview does not appear because the height is wrap_content before the image is loaded. The image expands after being uploaded, but I want to get the image size without loading the image.
I assume that you are getting the image URL / path from the server. Like, http://......
Then, you will definitely get the height and the width of the image from its path / URL by converting it into the Bitmap.
Try this:
try {
URL url = new URL("http://....");// here put your string URL comes from server
Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
int width = b.getWidth(); // here is the your image width
int height = b.getHeight(); // here is the your image height
} catch(IOException e) {
System.out.println(e);
}

Why does layout, set to match_parent, displays a 0 width

I have the following code:
llColors = (LinearLayout) findViewById(R.id.llColorSpect);
llColors.setOnTouchListener(llTouch);
width = llColors.getWidth();
height = llColors.getHeight();
Log.i("LAYOUT WIDTH", "width" +width); //shows 0
Log.i("LAYOUT HEIGHT", "height" +h); //shows the correct height
What makes me confused is why is the LAYOUT WIDTH is 0. In the XML, I set the layout width to match_parent and height to wrap_content.
How do I take the Bitmap that I am decoding below and fill in the layout above width fill_parent? Do I use LayoutParams?
bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.palette2);
The XML code is this:
<LinearLayout
android:id="#+id/llColorSpect"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/palette2"
android:layout_alignParentBottom="true" >
</LinearLayout>
What I am trying to accomplish is lehman term is, take the layout and fill it with a background image and use the pixel to get X and Y coordinate.
You are calling getWidth() too early. The UI has not been sized and laid out on the screen yet.
Try getting size after overriding the onWindowFocusChanged() function:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
//Here you can get the size!
}
Have a look at this discussion
If you want your bitmap to match parent height and width you can use this:
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
imageView.setImageBitmap(bitmap);
imageView.setLayoutParams(params);
Hope this helps :)
As far as the width being 0, the layout may not be finished being drawn yet. I used OnGlobalLayoutListener to know when it had been drawn. Here is a bit of code how I have done it to make my layout a Bitmap so I could print it. A little different but same concept.
#Override
public void onGlobalLayout()
{
String path = null;
try {
path = Environment.getExternalStorageDirectory().getPath().toString();
FileOutputStream out = new FileOutputStream(path + "/testPrint" + "0" + ".png");
Bitmap bm = Bitmap.createBitmap(root.getDrawingCache(), 0, 0,
root.getWidth(), root.getHeight());
bm.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
where root is the inflated layout that I needed to get the width of.
and you can set the listener with something like
ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener((OnGlobalLayoutListener) root.getContext());
OnGlobalLayoutListener Docs

imageView.getWidth(); returns screen instead of bitmap width

I have an imageview that looks like this
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignTop="#+id/textView3"
android:layout_centerHorizontal="true"
android:layout_marginBottom="80dp"
android:layout_marginTop="40dp"
android:onClick="Time"
android:adjustViewBounds="false"
android:src="#drawable/ic_launcher" />
I'm trying to get the width of the image displayed in the imageview by using
ImageView artCover = (ImageView)findViewById(R.id.imageView1);
int coverWidth = artCover.getWidth();
But the width returned is the same as the screen width and not of the image (when the image width is less then the screen width). If I do
int coverHeight = artCover.getHeight();
I get the correct height of the image. How can I get the width of the displayed image?
Your imageview's bitmap is probably scaled and aligned accordingly. You need to take this into account.
// Get rectangle of the bitmap (drawable) drawn in the imageView.
RectF bitmapRect = new RectF();
bitmapRect.right = imageView.getDrawable().getIntrinsicWidth();
bitmapRect.bottom = imageView.getDrawable().getIntrinsicHeight();
// Translate and scale the bitmapRect according to the imageview's scale-type, etc.
Matrix m = imageView.getImageMatrix();
m.mapRect(bitmapRect);
// Get the width of the image as shown on the screen:
int width = bitmapRect.width();
(note that I haven't tried to compile above code, but you'll get the gist of it :-)).
The above code only works when the ImageView has completed its layout.
You have to wait till the View tree has been measured completely which might be even later than onPostResume(). One way to deal with that is:
final ImageView artCover = (ImageView)findViewById(R.id.imageView1);
artCover.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int coverWidth = artCover.getWidth();
}
}
);
You can get image from imageview and will get width the image.
Bitmap bitmap = ((BitmapDrawable)artCover.getDrawable()).getBitmap();<p>
bitmap.getWidth();

Scaling ImageView to device width

In my Android App I have a Activity which show images which have following size 244 x 330.
I want to show those images in full device width.
My layout file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ImageView android:id="#+id/news_image"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_marginLeft="18dip"
android:layout_marginRight="18dip"
android:background="#aaaaaa" />
</LinearLayout>
</ScrollView>
I tried to set the ScaleType of the ImageView but there is no ScalingType which scales the ImageView proportional.
How can I scale the image proportionally to fit the whole screen in landscape mode AND portrait mode?
Basically what I want is something like ScaleType.CENTER_CORP but which also sets the proportional height for the image so I can see all of it and not just a part of the image.
Edit cause I know I'm confusing you with my "weird" questing.
I want to show it to you with a image.
This is what I get at the moment with my layout. I want to fill the whole grey area by scaling the image as big as needed. How can I accomplish that?
When I set the ScaleType to CENTER_CROP I get this
but this is not what I want cause you are not seeing the whole image just a part from the center.
And this is what I want it to be:
I hope this helps you to understand what I'm trying to accomplish.
Anyone knows how to do that?
Edit 2:
It might look weird and little confusing that I'm trying to display a image which is bigger in the height than the screen size but since I'm using a ScrollView in my example layout this should be ok and the user could scroll if he want to see the not displayed area.
Hope this helps to understand what I'm trying to do.
I tried really every ScaleType in my ImageView with fill_parent and wrap_content but no of them worked. I also tried everything what I found on Google but nothing worked for me either so came up with something on my own.
It was clear that the ImageView is not scaling my image like I wanted to be scaled so I had to scale it on my own. After scaling the bitmap I would set the new Bitmap as the image source to the ImageView. This works pretty good and looks very good on the G1 and on the Motorola Milestone 2.
And here is all pieces of my code
Layout:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/news_wrapper">
<ImageView android:id="#+id/news_image"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_marginLeft="18dip"
android:layout_marginRight="18dip"
android:background="#aaaaaa" />
</LinearLayout>
</ScrollView>
Activity
public class ScalingImages extends Activity {
private ImageView imageView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_margin);
this.imageView = (ImageView)findViewById(R.id.news_image);
// The image is coming from resource folder but it could also
// load from the internet or whatever
Drawable drawable = getResources().getDrawable(R.drawable.img);
Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
// Get scaling factor to fit the max possible width of the ImageView
float scalingFactor = this.getBitmapScalingFactor(bitmap);
// Create a new bitmap with the scaling factor
Bitmap newBitmap = Util.ScaleBitmap(bitmap, scalingFactor);
// Set the bitmap as the ImageView source
this.imageView.setImageBitmap(newBitmap);
}
private float getBitmapScalingFactor(Bitmap bm) {
// Get display width from device
int displayWidth = getWindowManager().getDefaultDisplay().getWidth();
// Get margin to use it for calculating to max width of the ImageView
LinearLayout.LayoutParams layoutParams =
(LinearLayout.LayoutParams)this.imageView.getLayoutParams();
int leftMargin = layoutParams.leftMargin;
int rightMargin = layoutParams.rightMargin;
// Calculate the max width of the imageView
int imageViewWidth = displayWidth - (leftMargin + rightMargin);
// Calculate scaling factor and return it
return ( (float) imageViewWidth / (float) bm.getWidth() );
}
}
Util class
public class Util {
public static Bitmap ScaleBitmap(Bitmap bm, float scalingFactor) {
int scaleHeight = (int) (bm.getHeight() * scalingFactor);
int scaleWidth = (int) (bm.getWidth() * scalingFactor);
return Bitmap.createScaledBitmap(bm, scaleWidth, scaleHeight, true);
}
}
If there is an better or more accurate way to accomplish the same scaling please let me know because I can't believe that such a trivial thing is so hard to accomplish.
I'm really hoping to see a better way to do this.
Thank you for reading.
the easiest way is to add android:adjustViewBounds="true" to the ImageView and set the scale type to "fitCenter"
Slightly confused on what you're looking for, exactly. If you're scaling to fit the screen, you have three options, two of which are viable if you're keeping proportions. You can use ScaleType fitCenter, which will make the image fit within the bounds proportionally, or you can use centerCrop (which you said you tried), which will stretch the shortest side of the image to fit the container (meaning some will get cropped off on the longer dimension). You can't have it stretch to fit the width AND height without either cropping, or stretching disproportionately.
EDIT: Okay, I think I get your point now. First, I'd set your LinearLayout to wrap_content for the height. Second, in code, here's one way you can do it that I can think of. There's probably also another way you could do it by first getting the screen dimensions, and then doing createScaledBitmap with the new dimensions, and then setting the background resource.
final ImageView newsImage = (ImageView)findViewById(R.id.news_image);
//get details on resolution from the display
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
//going to set what happens as the layout happens
newsImage.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
int oldHeight, oldWidth, newHeight, newWidth;
//we want the new width to be as wide as the screen
newWidth = metrics.widthPixels;
oldHeight = newsImage.getDrawable().getIntrinsicHeight();
oldWidth = newsImage.getDrawable().getIntrinsicWidth();
//keeping the aspect ratio, the new height should be w1/h1 = w2/h2
newHeight = Math.floor((oldHeight * newWidth) / oldWidth);
LinearLayout.LayoutParams params =
(LinearLayout.LayoutParams)newsImage.getLayoutParams();
params.height = newHeight;
params.width = newWidth;
newsImage.setLayoutParams(params);
newsImage.setScaleType(ScaleType.CENTER);
newsImage.invalidate();
newsImage.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
}
I googled everywhere and could not find a solution.
Here is what I did, that worked for me and with a scroll view.
XML file:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<ImageView
android:id="#+id/manga_page_image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
</ScrollView>
Have you tried setting it programmatically via ImageView.setScaleType()?
setAdjustViewBounds( false ) might help as well.
Edit: sorry, I mis-read the question. Regardless, setAdjustViewBounds() still might help. Never used it though.
I want to show those images in full
device width.
This is simple. You just have the wrong margin settings. Remove these lines and your image will show in full device width:
android:layout_marginLeft="18dip"
android:layout_marginRight="18dip"
I don't see the images anymore and the question is old but just in case someone else finds this and has the same problem. Wouldn't it be better to just get float screenWidth = getResources().getDisplayMetrics().widthPixels and set the ImageView LayoutParamters programmatically to scale the image to screenWidth. Just an idea !!
manage to achieve what I wanted, which hopefully is the same as your aim:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pgviewer);
ImageView PgContainer = (ImageView)findViewById(R.id.imageView1);
String Page = String.valueOf(getIntent().getExtras().getInt("Page"));
try {
PgContainer.setImageBitmap(getBitmapFromAsset(Page));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
PgContainer.setScaleType(ScaleType.FIT_CENTER);
PgContainer.scrollTo(0, 0);
PgContainer.setScrollBarStyle(0);
}
then to scale the bitmap:
private Bitmap getBitmapFromAsset(String strName) throws IOException
{
AssetManager assetManager = getAssets();
InputStream istr = assetManager.open(strName+".png");
Bitmap bitmap = BitmapFactory.decodeStream(istr);
float screenWidth = getResources().getDisplayMetrics().widthPixels;
int ih=bitmap.getHeight();
int iw=bitmap.getWidth();
float scalefactor = screenWidth/iw;
//w = 480, h=~
//int newh = bitmap.getHeight()/bitmap.getWidth();
return android.graphics.Bitmap.createScaledBitmap(bitmap, (int)(iw*scalefactor), (int)(ih*scalefactor), true);
//return bitmap;
}
One of the ways to do it is by setting android:adjustViewBounds="true" to the ImageView and set the scale type to "fitCenter" in the xml file.
This should work as expected.
You can also do this programatically by setting ImageView.adjustViewBounds(true) and ImageView.setScaleType(ScaleType.FIT_CENTER).

Categories

Resources