Scaling and overlapping ImageViews - android

I am a bit of an android noob, and have been struggling with this problem for far too long.
What I'm aiming for:
Two ImageViews. The first will be the width of the screen, and drawn to match the proportions of its src image (so far so easy). The second ImageView needs to be scaled, so that its width is a fixed multiple (between 0 and 1) of the first image.
I will ultimately then need to be able to touch-drag the second smaller image around on top of the first, fixed image, although this part is not the point of this question.
This will all generally be done programmatically, as the src images and the scale multiple are not known until runtime.
What I've tried: I can overlay two ImageViews in a RelativeLayout, using alignParentTop and so on. This works fine, but I can't see how to scale the images in this case.
I can alternatively scale the two ImageViews using a LinearLayout, by setting their layout_weights to 1 and the scale multiple respectively. In this case I can't get the images overlapping however (not strictly true - I have managed this with negative margins, but it is a very hacky solution and will make it almost impossible to implement the movement of the top image later).
So my question is: is there a way to fix either of the two solutions I have tried to implement? Or is there perhaps a better way to approach the problem?
(I'm not necessarily looking for an answer in code, just the approach I should take)

Well with what I understand,
You can use a Constraint Layout
Place 1st ImageView on your desired place
with constraints to your parent
Place Second ImageView on your desired place
with constraints to the parent (NOT WITH ANY OTHER CHILD VIEW)
The Approach is if you put a SubView In ConstraintLayout with Constraints to Parent, you can manipulate (Scale / translate) without any effect on other views.
to change the position of the View in runtime you can use
view.setTranslationX() and view.setTranslationY();
you can also create a view programmatically with Constraints to the parent
(my personal preference)
you can use this to overlay different Views in ConstraintLayout
<ImageView
android:id="imageID1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="yourImageStable"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
// put your own constraints-
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</ImageView>
<ImageView
android:id="imageID2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="yourImageUnStable"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
Note: This two constraint value will draw an ImageView from the Top-Left
corner of the Parent View (on Position x=0, y=0)
Remember: the View which you want to overlay should be written next to the other,
like here ImageID2 can overlay ImageID1.
</ImageView>

Related

how can I constraint a view to the center of another views bottom?

I would like to have an image always perfectly centered on top of the bottom of another image.
My first thought was setting the background image's bottom constraint to, for example 100dp from another view, and then the foreground image's bottom constraint to 50dp from the same view, and set it's height to 100dp.
This way it will always be on the center of the background image's bottom center, but I am making the foreground view not responsive by giving it a fixed size, which is something I would like to avoid.
Another thought I had was to constraint both the top and bottom of the foreground image to the bottom of the background image, but then the view just collapses.
I can't find any settings that would allow that to work.
*I need to keep a ratio for the foreground image.
I found an answer here:
https://gist.github.com/writtmeyer/f5971266394b2316eb01b566cdeff2a0
It suggests a clever way if using a dummy view.
You can do it by constraining your view to the start and end of the target, so that it will keep centered to it. Here's a sample:
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#+id/targetView"
app:layout_constraintStart_toStartOf="#+id/targetView"
app:layout_constraintEnd_toEndOf="#+id/targetView" />
I think this is what you are looking for.
<ImageView
android:id="#+id/backgroundImage"
android:layout_width="150dp"
android:layout_height="150dp"
app:srcCompat="#mipmap/ic_launcher" />
<ImageView
android:id="#+id/foregroundImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="#id/backgroundImage"
app:layout_constraintEnd_toEndOf="#id/backgroundImage"
app:layout_constraintStart_toStartOf="#id/backgroundImage"
app:layout_constraintTop_toTopOf="#id/backgroundImage"
app:srcCompat="#mipmap/ic_launcher"/>

Crop image and retain positioning android

I have two images that are positioned in the same space, effectively overlapping one another.
They are slightly different but identically sized.
I want to be able to crop the top laying image but retain the initial positioning.
So almost like cutting it in half, and keeping the left half in place, which would perfectly overlap the underlaying image.
The following is the code I have, just two ImageView's within a FrameLayout.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_gravity="center_horizontal"
android:layout_width="380dp"
android:layout_height="wrap_content"
android:src="#drawable/level_off">
</ImageView>
<ImageView
android:layout_gravity="center_horizontal"
android:layout_width="190dp"
android:layout_height="wrap_content"
android:src="#drawable/level_on">
</ImageView>
</FrameLayout>
Any ideas? I've done my best to explain what I mean! Thanks!
You could try an programmatic approach by inheriting ImageView and override onDraw(), doing so will also save you an extra layout group.
In onDraw()you have to:
obtain the imageMatrix from your original image
alter the canvas to left/right half of your original size
draw the second image in that altered canvas with the same matrix as the original image
I've done a similar thing and theoretically it should work for your case as well.

RelativeLayout align parent *side* + margin *side*

I've noticed a strange behavior in RelativeLayout when you align a view to the layout's side
(any side) and having a large margin in the same direction.
I have 2 RelativeLayouts that each contains a simple view. In one layout that view is align to the top and left, in the other to the bottom and right:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginTop="110dp"
android:layout_gravity="center"
android:background="#ff555555" >
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:background="#aa8711" />
</RelativeLayout>
<RelativeLayout
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginBottom="110dp"
android:layout_gravity="center"
android:background="#ff555555" >
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="#998877" />
</RelativeLayout>
</FrameLayout>
It looks like this:
I added 130dp of margin in each direction of parent alignment. That means that the view should be only partially visible in the layout. This is what happens:
As you can see, the views are now smaller than the original size, as the get pushed on the "walls" of the layout. Next I tried to give a margin that is bigger than the layout, so I gave them 151dp of margin in the aligned directions. It looked like this:
The bottom-right aligned view now "breaks out" of the layout and is again the same size as it was originally. On the other hand, the top-left aligned view is too in its original size, but completely inside the layout instead of outside of it.
I've tried this individually and in every permutation of alignment and got the same results.
Question one: Can anyone explain this inconsistent behavior?
I tried the same thing, this time comparing the behavior to that of a FrameLayout.
Initial setup:
and after margins:
The FrameLayout keeps the view in its original size at all time and simply lets the view "exit" it. I tried to give a negative margin in the opposite direction of at least the size of the view that should be outside of the RelativeLayout and saw the same behavior as happens in the FrameLayout by default.
Question 2: Can anyone explain the difference in behavior and the opposite negative margin effect?
Why should it be only partially visible?
I added 130dp of margin in each direction of parent alignment. That
means that the view should be only partially visible in the layout
The box is getting smaller because preference is given to keeping it inside the parent layout at all costs, while still applying the margin. Since the smaller child view is 50dp, you have added a margin of 130dp, the total width it needs is 180dp but the parent view itself is only 150dp wide. That is 130dp + 50dp > 150dp - the child plus the margin cannot fit inside the parent.
This is "silly input" and the XML interpreter is doing its best to render something. The decision that it makes in the end is that it can alter the width of the child box and still respect the margin constraint. Or mathematically
130dp + 20dp == 150dp
Basically it shrinks the width of the inner box down from the assigned 50dp to 20dp so that it can fit inside the parent with its added margin. And if you look at the size of the square 20dp looks about right. It is 60% smaller.
This is clever behaviour by the interpreter because as screen sizes change and it runs into issues like this it should always preserve the margin constraint opposed to the width constraint.
In summary the interpreter is doing its best to fit the box, and its margin inside its parent, to do so it is making the box smaller. It is choosing to preserve the given margin, over the given width - probably because of the top-most parent layout.
When you say "this should be partially visible" I assume you think the child will render half inside the parent bounds, and half outside the parent bounds, similar to windows form development. This is not the case though because it will always try to keep children inside the bounds of parents in most layouts.
The choices that are made depend on the top-most parent layout too, some layouts may prefer to preserve the width of the child box rather than the margin, or even render the box outside of the parent's bounds.
In the second case:
so I gave them 151dp of margin in the aligned directions.
You are going beyond the point in which the interpreter can shrink the image. It cannot shrink the image to negative 1. That is
50dp + 151dp > 150dp
It can't meet this margin constraint you have given it so the behaviour is fairly unpredictable. At a guess I would say it knows it cannot keep both the images, along with their margins inside the parent. So it simply renders one inside and one outside.
Once again, this is silly input and the interpreter is doing its best to render what you want.
Can anyone explain the difference in behavior and the opposite negative margin effect?
A negative margin will do different things depending on the type of layout in its parent, and that it is aligned too. In a frame layout it will behave differently to a relative layout. Usually if you are looking at negative layouts you have chosen the wrong parent containers and you are trying to hack it to get it to look right.
I don't know what you are trying to do exactly but maybe you just need tweak your thought process a little and think of the poor interpreting trying to understand the XML you give it.
You wouldn't be the first person to be utterly confused by android's XML layouts. Nesting layouts inside layouts is always confusing and the behaviour changes depending on a number of things like margins, alignments, widths, etc. Most people I know simply muck around with it until it is right and try different container layout types to get the right design.
In short, avoid playing with margins (like flash or winforms) and play without layout types instead to get things where you want them.
hope that helps, sorry for tl;dr.

Two circular images on top of one another

I am having two different circular images with different sizes.I have to place both in same place where the center point will be same.These two imageviews are in a relative layout.
please help..
When using a relative layout the only option to do that is to center both images in the layout, but if you start adding more elements, such as some text above/below any of the images, the result will not be as expected.
So my recommendation is to do it programatically. You can define a View and override the onDraw() method. Then you would load the bitmaps by means of two ImageView (or BitmapFactory). Then you paint it to the canvas at the desired location. To find out the center of each image you can use the Rect class that you obtain from the View method getDrawingRect after you apply the layout properties (so the size is calculated),, or by hand (create a Rect with de dimensions of the loaded Bitmap if you use BitmapFactory)
Other alterative is using LayerDrawable and define the image positions so they are centered (you need to know the image dimensions before hand).
Difficult to help without your layout XML code. Having said that, the moment you see "one on top of the other", you need to consider FrameLayout.
Use Framelayout, and set the background for the same with an image and then add images on top with setting layout gravity to left or right or middle.
In stead of creating a new sublayout, you can potentially have the ImageViews align on all sides and set the scaleType attribute to something like center:
<ImageView
android:id="#+id/circle_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/..."
android:scaleType="center"/>
<ImageView
android:id="#+id/circle_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/..."
android:layout_alignTop="#+id/circle_a"
android:layout_alignBottom="#+id/circle_a"
android:layout_alignLeft="#+id/circle_a"
android:layout_alignRight="#+id/circle_a"
android:scaleType="center" />
This will give the circle_b ImageView actually the same dimensions as circle_a, but setting the appropriate scaleType will prevent the image from being stretched or misaligned.
//Edit: ups, I meant to say center... corrected.

Trimming ImageView in Android

I have an image which is 450px square below some text in a linear layout and wanted it to fill the width of the device, which I done by using;
ImageView android:id="#+id/my_image_container"
android:src="#drawable/my_image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/orange"
android:scaleType="fitStart"
This has worked in a fashion, but the ImageView element fills the rest of the screen and any elements placed under do not show.
Does anyone know of a way to trim the bottom of the space that the ImageView uses.
Hopefully this image can explain it better - I want to crop the empty area under the image (orange background).
I recommend you to use a RelativeLayout instead of a LinearLayout. You can then use android:layout_above="" and android:layout_below="" to ensure that you get the layout you want.

Categories

Resources