<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/imageview"
android:scaleType="centerCrop"/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/imagecancel"
android:layout_marginBottom="10dp"
android:background="#80000000">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/imagecaption"
android:hint="Enter a description"
android:textColorHint="#80ffffff"
android:textColor="#ffffff"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"/>
</RelativeLayout>
<ImageButton
android:contentDescription="#string/imagecancel"
android:id="#+id/imagecancel"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp"
android:scaleType="fitStart"
android:background="#android:color/transparent"
android:src="#drawable/cancel"/>
<ImageButton
android:contentDescription="#string/imagesave"
android:id="#+id/imagesave"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:scaleType="fitEnd"
android:background="#android:color/transparent"
android:src="#drawable/ok"/>
</RelativeLayout>
Java
private void previewCapturedImage() {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
ExifInterface exif = null;
int orientation = 0;//Since API Level 5
try {
exif = new ExifInterface(fileUri.getPath());
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
} catch (IOException e) {
e.printStackTrace();
}
String exifOrientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
Log.i("file path",exifOrientation);
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath());
previewimage.setImageBitmap(bitmap);
switch(orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
Log.i("RotateBitmap","270");
RotateBitmap(bitmap, 270);
previewimage.setRotation(270);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
Log.i("RotateBitmap","90");
RotateBitmap(bitmap, 90);
previewimage.setRotation(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
Log.i("RotateBitmap","180");
RotateBitmap(bitmap, 180);
previewimage.setRotation(180);
break;
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
public static Bitmap RotateBitmap(Bitmap source, float angle)
{
Matrix matrix = new Matrix();
matrix.postRotate(angle);
previewimage.setImageBitmap(source);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
here image fill normaly in small screen phones. But in large screen phone image didn't show correctly.It shows a gap 2cm from top and 2cm from bottom. The image comes from taking picture from phone camera. I want to fill image fullscreen. How to solve this problem.
try this
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/imageview"
android:scaleType="fitXY"/>
The source of your problem is a difference between the side ratio of your current preview area compared to side ratio of the picture you're getting. Your preview area will be different on different devices (even on the same device in different orientation - caused by 'soft buttons' position), and the image you get from the camera has rarely the same side ratio as you current preview.
Your question can be answered without any code. Just draw one rectangle (non-square) and one square on a piece of paper and try to fit one into another.
The rectangle (wide or tall) represents you phone and the square represents the picture you've got from the camera (it mostly isn't square, but I use square here to make it clearer to demonstrate).
If you take these 2 shapes and try to 'fit' one into another, you will end up with 3 different scenarios:
you manage to fit square into rectangle by stretching/squeezing it. This is definitely not the result to shoot for (first, it is not square anymore, second, our grandma's face will be too fat or too skinny :-)
you fit the full square into your rectangle and you'll see 2 unfilled areas (if you center it) - this is the situation you're complaining about. Also called 'fit-in' or 'letterbox';
you fill the full rectangle with a portion of your square and two sides of your square will overflow the rectangle. This case looks like you've achieved your goal if you don't mind that you lost some of your image. Situation is sometime called 'pan&scan'.
So, how does this rant help you? If you insist on filling the full screen (and losing overflowing image portion), you adjust your SurfaceView area after you get your image, use it's width / height to calculate the ratios.
If you really insist on seeing some code, it's done here (see the setLayoutParams), but be warned, the example I'm pointing to is more complicated and involves custom camera handling. But the general idea is the same.
Good Luck
if you want, you can set it as RelativeLayout background in xml.
android:background="#drawable/_image"
or set it dynamically.
Change the scaletype
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/imageview"
android:scaleType="fitXY"/>
Related
First let's introduce me, I'm new in Android and mobile device programming, I previously worked on embedded systems running on QNX.
I hope I will respect the rules of this forum which seem to be quite stricts ;-).
I'm wrinting an application where I declare a layout for a welcome screen populated, between other things with a image view.
There is a first image placed in this image view in the xml file, but I will replace it by an other one later in the application's code and this second image will be potentially of a different size.
My problem is to resize and center my second image. According to my tests, it's quite automatic by using resources in Lint but it seems not so obvious by program, even if I read in the docs that it should be similar.
After reading several posts on the subject, I finally have a doubt; Can I center an image in an ImageView, or do I have to center the ImageView in the available space?
I tried the first solution without success.
So my layout is:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragmentInit"
android:layout_width="match_parent"
android:layout_height="match_parent"
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.cabbonline.ndguidelt.MainActivity" >
<TextView
android:id="#+id/textViewAppName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/textViewAppVersion"
android:layout_centerHorizontal="true"
android:text="#string/app_name" />
<TextView
android:id="#+id/textViewAppVersion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/TextViewDevelopCabb"
android:layout_centerHorizontal="true"
android:text="#string/app_version" />
<TextView
android:id="#+id/TextViewDevelopCabb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/imagecaBB"
android:layout_centerHorizontal="true"
android:text="#string/develop_cabb" />
<ImageView
android:id="#+id/imagecaBB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/textViewCabbUrl"
android:layout_centerHorizontal="true"
android:contentDescription="#string/logo_caBB"
android:maxHeight="150dp"
android:src="#drawable/logo_cabb_100x51_or" />
<TextView
android:id="#+id/textViewCabbUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="#string/cabb_url" />
<ImageView
android:id="#+id/imageSite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/textViewAppName"
android:contentDescription="#string/logo_Site"
android:scaleType="centerInside"
android:src="#drawable/image_guide_320x400" />
</RelativeLayout>
Here I can say tht the "imageSite" ImageView is well displayed, centered and occupies the whole area. Right.
Now I have a piece of code to replace this image in this same ImageView:
Bitmap imageSite = site.getSitePictureBitmap();
if (imageSite != null) {
imageGuide.setImageBitmap(imageSite);
}
If I only do that, despite en center_inside flag, the new bitmap, smaller and rectangular horizontally compare to the first one which is almost sqaure, the image is displayed very small on the bottom right corner of the ImageView, or the area taken by the ImageView, Idon't really know.
So I add this piece of code to resize it:
imageSite = site.getSitePictureBitmap(); // here I read the bitmap in a file.
if (imageSite != null) {
float maxWidth = imageGuide.getWidth();
float maxHeight = imageGuide.getHeight();
float width = imageSite.getWidth();
float height= imageSite.getHeight();
float hRatio = width / maxWidth;
float vRatio = height / maxHeight;
if (Math.abs(1 - hRatio) < Math.abs(1 - vRatio)) {
// We match horizontal available size
width = width / hRatio;
height = height / hRatio;
} else {
width = width / vRatio;
height = height / vRatio;
}
Bitmap reSizedBitmap = Bitmap.createScaledBitmap(imageSite, (int)width, (int)height, true);
imageGuide.setImageBitmap(reSizedBitmap);
So the image is now of the good width but as its vertical dimension is lower than the first picture, it's close to the textViewAppName. So as it's a rule for the ImageView in the layout description, I wonder if my image is not in the center of the ImageView in fact and my problem would come from the fact that the ImageView is now of a smaller height and doesn't fill up the whole space available at the top of the layout.
I also wondered if setting a new image doesn't reset the positionning flags. I didn't see that in the doc AFAIR but...
So I add this line after setImagebitmap() without success:
imageGuide.setScaleType(ScaleType.CENTER_INSIDE);
Can you tell me a bit more about ImageView behavior in this case and how to get my image vertically in the center of the available space. Do I have to calculate padding?
Regards,
Al
I am very close to a solution but the last bit is eluding me. I have two images of identical size that I have overlayed in a section of my layout. These images will be scaled to fit the screen depending up on screen size. I have used multiple drawables if that is relevant.
Essentially one image is a circle with an airplane in the middle and the other is a little windsock. I want the windsock to sit in the relative position that the wind is coming from.
I have got the windsock to overlay at the start nicely, I can rotate it BUT it is not rotating concentrically and the scale of the windsock changes slightly when I do the rotation. I can see this because when I return the rotation to zero the windsock graphic is not in the starting position and is slightly larger.
So the question is how do I scale the overlay to be the same as what android does when it creates the initial view?
My XML:
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="0.60"
android:gravity="center"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:textSize="12sp"
android:text="#string/runwayDirection"
android:textColor="#ffffff" />
<EditText
android:id="#+id/rwyDirection"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginLeft="1dp"
android:layout_marginRight="1dp"
android:background="#drawable/border"
android:ems="10"
android:gravity="center"
android:inputType="number"
android:maxLength="3"
android:text="#string/zero"
android:textColor="#ffffff"
android:textCursorDrawable="#null" />
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="#+id/aircraftGraphic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/windRose"
android:src="#drawable/aircraftgraphic" />
<ImageView
android:id="#+id/windpic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/windRose"
android:src="#drawable/windsockring"
/>
</FrameLayout>
</LinearLayout>
The code I am using to rotate:
public void rotate_windsock(){
float relativeWind=90;
float rwydir;
float windDirection;
if (rwyDirection.getText().toString().matches("")) rwydir=0;
else rwydir=Float.parseFloat(rwyDirection.getText().toString());
if (windAngle.getText().toString().matches("")) windDirection=0;
else windDirection=Float.parseFloat(windAngle.getText().toString());
if (rwydir>windDirection) relativeWind=360-(rwydir-windDirection);
else relativeWind=(windDirection-rwydir);
Matrix matrix=new Matrix();
windSock.setScaleType(ScaleType.MATRIX); //required
matrix.postRotate((float) relativeWind, aircraftGraphic.getWidth()/2, aircraftGraphic.getWidth()/2);
//matrix.postScale(aircraftGraphic.getWidth(), aircraftGraphic.getWidth());
windSock.setImageMatrix(matrix);
}
You can see I am currently trying to get the width of the underlying picture and since it is a square use that as the arguments for postRotate. I have tried getting the width of LinearLayout and I have tried doing a rotate on the underlying image hoping that it would scale to the same as the overlying image but nothing has worked. It is close but is obviously not right.
Anyone help me out? The only other thing I have thought of is shrinking the images further so they aren't scaled but this will waste space on larger screens?
EDIT:
I have tried changing the rotation code to this:
Matrix mat = new Matrix();
Bitmap bMap = BitmapFactory.decodeResource(getResources(),R.drawable.windsockring);
mat.postRotate(relativeWind);
Bitmap bMapRotate = Bitmap.createBitmap(bMap, 0, 0,bMap.getWidth(),bMap.getHeight(), mat, true);
windSock.setImageBitmap(bMapRotate);
Now that appears to work perfectly the difference between the runway direction and wind direction is a multiple of 90 but otherwise the scaling of the windsock is affected?!?!?! What is up with that!
EDIT #2:
OK For those in the future I now have it working thanks to these links:
Rotate image without shrinking on Android
http://learnandroideasily.blogspot.com.au/2013/07/imageview-animation-in-android.html
The code to do it:
RotateAnimation rAnimClockWise = new RotateAnimation(0.0f, relativeWind, 1, 0.5f, 1, 0.5f);
rAnimClockWise.setFillAfter(true);
rAnimClockWise.setInterpolator(new LinearInterpolator());
rAnimClockWise.setDuration(0);
windSock.startAnimation(rAnimClockWise);
I know this is incredibly long in the end but I am sure it will help someone in the future!!
See the edits I made in the origina question for the answer!
I'm getting my downloaded drawables correctly and they show up correctly. I just want to show the top 144x284dip of the image on my ImageView. Instead, when the images are downloaded the ImageView resizes itself to the width and height of the drawable. I've tried modifying both layoutparams and minimumwidth / minimumheight, to no avail.
Is there anything I can do to force the ImageView to stay at 144x284?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="284dip"
android:layout_height="144dip" >
<ImageView
android:id="#+id/imageViewLogo"
android:layout_width="284dip"
android:layout_height="144dip" />
</LinearLayout>
If I understand you correctly, you want to do two things:
Fix the size of the ImageView to 284dip X 144dip.
Show only the top left portion of the image, unscaled.
Doing the second part will require you to use "matrix" scale type and set scale to 1.0 and transform factor to 0.0.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView"
android:layout_width="284dip"
android:layout_height="144dip"
android:scaleType="matrix"
android:src="#drawable/ic_launcher" />
</LinearLayout>
By default, scale factor is 1 and translation is 0. So, you don't have to do anything else. If you do wish a different scaling and translation, you could write code like this.
void showImage(Bitmap bm) {
float scaleFactor = ...;
float transform = ...;
imageView.setImageBitmap(bm);
final Matrix matrix = new Matrix();
matrix.setScale(scaleFactor, scaleFactor);
matrix.setTranslate(transform, transform);
imageView.setImageMatrix(matrix);
}
Ok, I solved it.
I just did this:
Bitmap newBitmap = Bitmap.createBitmap(bm, 0, 0, 144, 284);
Then set it to the ImageView.
I'm using a ImageView to dislay an image. There is a "Image--" button, when I click it, the ImageView will use a matrix to scale the image. The problem is, the image will finally too small to see.
You can see my examples.
Original Image:
After clicking button "Image--" 12 times:
You can see the sofa image is so small that hard to see now.
My "main.xml" content is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="#+id/root" xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content"
android:orientation="horizontal">
<!-- buttons -->
</LinearLayout>
<ImageView android:id="#+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:adjustViewBounds="true" android:background="#336699"
android:scaleType="matrix"/>
</LinearLayout>
And my java code is:
this.btnImageZoomOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Matrix matrix = new Matrix(imageView.getImageMatrix());
matrix.postScale(0.8f, 0.8f);
imageView.setImageMatrix(matrix);
imageInfo();
}
});
My question is: how to let the sofa image will smaller a specified size? e.g. 1/5 of original size?
UPDATE
If I can get the size of scaled sofa image, it will be easy to check if the image is too small. But I tried a lot, still not get it, that's why I ask this question. Do I miss something?
I think it might be easier to do it with Layoutparams (which will provide you the size of the image) instead of Matrix since you will need the size anyways. This could be your onClick method for zoom out:
imageView.setScaleType(ScaleType.FIT_XY);
LayoutParams layoutParams=imageView.getLayoutParams();
layoutParams.height*=0.8f;
layoutParams.width*=0.8f;
if(layoutParams.height>scaled_specified_size_in_px && layoutParams.width>scaled_specified_size_in_px){
imageView.setLayoutParams(layoutParams);
}
Notice that you need to have a scaled value there, OR you can simply limit it to a % of the original size (You will need to save the original size).
Can't you check to see how big the 80% will make the photo, and if it is smaller than you want, dont do the scale? Maybe disable the shrink button if the size is too small?
I'm implementing a widget where i'm trying to display a large image inside an image view (8mpx) like this :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" android:id="#+id/widget"
android:background="#000000"
android:padding="15dp"
android:layout_margin="5dp"
android:layout_gravity="top|center_vertical|center_horizontal"
>
<LinearLayout android:background="#ffffff" android:padding="1dp" android:layout_width="wrap_content" android:layout_weight="1"
android:layout_height="wrap_content" >
<ImageView
android:adjustViewBounds="true"
android:id="#+id/image"
android:src="#drawable/sample"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="top|center_horizontal"
android:scaleType="fitXY"
android:maxWidth="200dip"
android:maxHeight="300dip"
/>
</LinearLayout>
In the emulator everything seems ok, but when i deploy to device, i get the "problem loading widget" message.
the emulator is HVGA and my device has a 480x800 resolution.
Any ideea what am i doing wrong ?
Thank you!
==================================================
As advised by you guys i've made a screenshot of the logcat.
Here it is :
imageview.setScaleType(ScaleType.CENTER_INSIDE);
Try below code
<ImageView
android:adjustViewBounds="true"
android:id="#+id/image"
android:src="#drawable/sample"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
android:scaleType="centerInside"
/>
use this
imageview.setImageResource(your_image);
imageview.setScaleType(ScaleType.MATRIX);
Old post, but you never know...
The logcat shows the problem:
"allocation too large for this process"
The image you are trying to render is too large to fit into memory. You need to scale the image down, but don't try to create a scaled version of the bitmap or you'll hit the same problem. The solution is the load the Bitmap into memory but ONLY for it's dimensions, then create a new Bitmap with a sample size that reduces the overall size of the image.
Actually you don't even need to load in the image to get it's original size to do this but it often makes sense so you can choose an appropriate sample size.
e.g.
Assuming your Bitmap is obtained from an InputStream:
InputStream in = ... // Your Bitmap Stream
// Decode JUST the dimensions
Options dimensionOptions = new Options();
dimensionOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, dimensionOptions);
// Get the dimensions of the raw
int rawWidth = dimensionOptions.outWidth;
// Choose a target width for the image (screen width would make sense)
int targetWidth = 480;
// Select the sample size which best matches our target size.
// This must be an int
float sampleSize = (float)rawWidth / (float)targetWidth;
// Assume lower, which will result in a larger image
int sample = (int) FloatMath.floor(sampleSize);
// Use this to decode the original image data
Options scaleOptions = new Options();
scaleOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; // 4 bytes per pixel
scaleOptions.inSampleSize = sample;
// Now create a bitmap using the sample size
Bitmap scaled = BitmapFactory.decodeStream(in, null, scaleOptions);