Rotate an overlay image concentrically - android

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!

Related

Adjust Image View to Image (Android Studio)

I would like to know how you adjust the "hitbox" of an ImageView to the Image inside, so that there are no empty spaces around the image. I want to make a game and so it feels odd when you click on an empty space next to the Image but it still counts as "a click on the image". I would really appreciate help.
Thank you in advance.
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/soraka"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/image"
android:adjustViewBounds="true"
android:maxWidth="300dp"
android:maxHeight="300dp"
android:scaleType="fitXY"
android:layout_alignParentEnd="false"
android:layout_alignParentStart="false"
android:cropToPadding="false"
android:padding="0dp" />
First of all open your image in some image editor and check if it fills entire canvas. Second - use android:scaleType="fitXY". But be carefull with aspect ratio:
Scale in X and Y independently, so that src matches dst exactly. This
may change the aspect ratio of the src.
Also remove all paddings, margins from ImageView.

how to fill image fullscreen in android

<?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"/>

how to center an image programatically in a layout described by resource

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

Create image layout

I am developing an application. The need is as, i want to create a layout as shown in figure :
In this, I took a relative layout to which I had given an image as background.
The image is not having red dot (buttons).
I placed the red button as image button at fix position. When i run it on my galaxy s2 it looks fine and work fine too.
But when I tested this layout on my LG optimus L3 E400. The red buttons are not on their position as i set.
The code of layout is :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background" >
<TextView
android:id="#+id/textview_navigationbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/navigationbar"
android:text="#string/string_map"
android:gravity="center"
android:textIsSelectable="false" />
<RelativeLayout
android:layout_below="#+id/textview_navigationbar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="50sp"
android:layout_marginBottom="50sp"
android:background="#drawable/map">
<ImageButton
android:id="#+id/imagebutton_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dip"
android:layout_marginLeft="50dip"
android:background="#drawable/button_1" />
<ImageButton
android:id="#+id/imagebutton_2"
android:layout_below="#+id/imagebutton_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dip"
android:layout_marginLeft="6dip"
android:background="#drawable/button_2" />
<ImageButton
android:id="#+id/imagebutton_3"
android:layout_below="#+id/imagebutton_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="1dip"
android:layout_marginLeft="40dip"
android:background="#drawable/button_3" />
</RelativeLayout>
</RelativeLayout>
In my LG Optimus L3 E400 it looks like :
The red buttons are not on position.
I don't want to use map view for this as i don't know and never used it.
Please guide me how to move out of this problem. As how to create layout for maximum resolution and screen support.
The easiest way is to create a custom view that holds the image (bitmap) and the buttons on top of it, and use onDraw method to draw your buttons, and analyse the coordinates on onTouch to create your touch events.
If you maintain your image's aspect ration (width:height) you can easily map the buttons to a suitable location using scaling.
Here is a list of custom views examples:
Android Developer's Custom Views
With Touch handling
Another example
You can also use AndEngine a 2D graphics/gaming engine for android, and it will take care of the scaling for you.
Take a look here : official website , examples
This can be done best with Canvas.
Or the easier way to do this would be edit the image and add those red dots in image itself.
you can use onTouchListener and in onTouch you can get the x and y coordinate to accomplish your task
Something like this:-
public boolean onTouch(View v, MotionEvent event) {
int x = event.getX();
int y = event.getY();
//handle your events on basis of x and y
}
This is'nt the best way to handle it. But should work.

ImageView moves when scaled/rotated

Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#android:color/transparent"
android:id="#+id/globeViewStreamInfoPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView android:id="#+id/streamIndicator"
android:src="#drawable/nv_tidestreamindicator"
android:scaleType="matrix"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_margin="10dp"
android:maxHeight="40dp"
android:maxWidth="40dp"
android:layout_width="40dp"
android:layout_height="40dp"/>
Code (streamIndicator is the ImageView):
streamIndicatorMatrix.reset();
streamIndicatorMatrix.setScale(size,size);
// rotate indicator in the direction of the flow
streamIndicatorMatrix.setRotate((float)(stream.currentStream.direction));
streamIndicator.setImageMatrix(streamIndicatorMatrix);
When I rotate, or scale, or both, the ImageView moves in the layout.
Weird thing is, when I break on the line after setImagematrix and inspect streamIndicator, mTop, mLeft, mWidth and mHeight all look correct. size and my rotation angle are always legal, sensible values.
I just know this is something stupid, what have I missed?
Thanks!
[EDIT]
Here's a pic, the red arrow was added by me to point to the errant ImageView:
Matrix.setRotate uses the (0, 0) pivot point by default. This is the reason your image moves in the layout. There is a overloaded version of the Matrix.setRotate method that allows you to speficy the pivot point.
final float density = getResources().getDisplayMetrics().density;
final int center = Math.round(20 * density);
streamIndicatorMatrix.setScale(size,size, center, center);
streamIndicatorMatrix.setRotate((float)(stream.currentStream.direction), center, center);

Categories

Resources