16

Background

Suppose I want to show an image of the something using an ImageView, and I want to put new views on top of it (animated ImageViews that show pins on a world map image, for example, or a Switch view on top of a smartphone image).

This means that no matter how the ImageView shows the image, the views should be in it, inside correct spot, with the same size as specified, or in a size related to the imageView itself

The problem

As opposed to other views, the ImageView can have a certain size, but its content is something else (to keep aspect ratio).

What I tried

I tried to use ConstraintLayout, but this can't really help, because the ImageView can change its size (for example when changing orientation), and thus ruining the position I've given the views compared to the ImageView.

I've found some libraries that can handle a similar thing (like here) and I even asked a similar question before (here), but all those solutions are for a static image within the ImageView, yet what I search for is adding a view on top of an ImageView.

The question

How do I put the views on top of the ImageView's content correctly?

How do I also scale the views down/up compared to the size of the ImageView's content ?

Can ConstraintLayout be used to change the scale of the views according to the ImageView's size ?

Community
  • 1
  • 1
android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • 1
    setup the layout params of the `Switch`, they should be `android.widget.FrameLayout.LayoutParams`, you will get the values from mapping the matrix returned from `getImageMatrix` method – pskink Jan 10 '17 at 13:24
  • @pskink Please explain how do it it , in code, inside an answer. Or provide a link about a similar question. – android developer Jan 10 '17 at 13:38
  • 1
    i have no idea about similar questions, i just gave you a solution on how to layout your `Switch` view so it always cover some part of your `ImageView` no matter how big it is and what `scaleType` it uses – pskink Jan 10 '17 at 13:43
  • 1
    @pskink Sadly I don't understand how to use your solution, because I can't find it being mentioned on the Internet as your solution lacks code. – android developer Jan 10 '17 at 13:51
  • 1
    see https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/widget/ImageView.java#792 and find where `mDrawMatrix` is used, it should explain what "ImageMatrix" is for – pskink Jan 10 '17 at 13:54
  • @pskink You've given me the source code of ImageView, which is not related to the question. – android developer Jan 10 '17 at 14:26
  • `ImageView` is not related to the question? i thought we are talking about `ImageView` and how it draws its content, am i wrong? – pskink Jan 10 '17 at 14:41
  • 1
    @pskink You are wrong in that putting the source code of ImageView isn't related to the question. As an analogy example, if I would ask you how to set an adapter for a RecyclerView, you would have given me the code of RecyclerView. Or, if I wanted to ask about how to show the list of files of the current path on Linux, you would have given me the code of linux (worst than even showing me "man ls"). This type of answer is bad and people will call it trolling. If you don't know the answer, it's better to avoid writing about it this way. – android developer Jan 10 '17 at 14:48
  • assume you have a png image you want to show using `ImageView`, this image is all white and has small black rectangle, now you want to know top-left and bottom-right corners inside that `ImageView` no matter how big it is and no matter what `scaleType` is used, right? so where it is computed if not inside `ImageView`? – pskink Jan 10 '17 at 14:57
  • 1
    @pskink Just as the answer of how to use Adapter for RecyclerView and how to use "ls" for Linux, can be done by reading the entire code of RecyclerView and Linux - doesn't mean this is a good answer at all. I don't understand why it matters what the image contains. What is important is its aspect ratio, and the rules that are used for the ImageView. What I need is to put the Switch on top of content that's shown by the ImageView, in the correct location and size. I hope now you understand the issue. – android developer Jan 10 '17 at 15:09
  • 1
    so first i gave you solution: use `getImageMatrix`, then you wanted the proof so i gave you the source code, thats all i can do – pskink Jan 10 '17 at 15:13
  • 1
    @pskink I never mentioned that I want a proof. I want a solution. What you gave is not a solution. It doesn't have any code or explain how to use it. It's not even in an answer. Please write a solution in an answer, after you've checked that it works. Besides, giving the source code of ImageView doesn't prove your solution is right, because there is nothing to test. – android developer Jan 10 '17 at 15:16
  • 1
    @pskink In short, a single sentence of "you will get the values from mapping the matrix returned from getImageMatrix method" doesn't provide enough information about what to do. What should I do with the mapping? How do I use it to set the size and position? When should I get the mapping? Is there anything to initialize before? etc... – android developer Jan 10 '17 at 15:19
  • 1
    have you tried anything? if so, what kind of problems do you have with `Matrix` mapping? – pskink Jan 10 '17 at 15:43
  • 1
    @pskink Yes. I've tried ConstraintLayout and also PercentRelativeLayout, but as I wrote, those won't work well in the case that the ImageView size doesn't match its content. ConstraintLayout will work fine only if ImageView has "wrap_content" for both its width and height, I think. I didn't use any matrix class. – android developer Jan 10 '17 at 18:42
  • 1
    its because only ImageView knows how to draw its content – pskink Jan 10 '17 at 18:45
  • @pskink Yes. Indeed. – android developer Jan 11 '17 at 07:30
  • so you have to use `ImageView`s transformation factor: *"void setImageMatrix (Matrix matrix) Adds a transformation Matrix that is applied to the view's drawable when it is drawn. Allows custom scaling, translation, and perspective distortion."*, this java doc clearly describes "image transformation matrix" and what it is used for – pskink Jan 11 '17 at 08:19
  • @pskink Please, if you have an answer, write it. – android developer Jan 11 '17 at 08:41
  • i dont have an answer, the answer would require full working code and dont have it, i used "image matrix" many many times but right now i dont have any source code using it – pskink Jan 11 '17 at 08:45
  • @pskink OK. I hope someone will be able to answe this. Thanks for trying to help. – android developer Jan 11 '17 at 08:52
  • @pskink For now, my workaround is to use wrap_content for the ImageView's width and height. I think that in this case, ConstraintLayout should work fine. Only thing that's not good about it is the resizing of the switch, but I was told it's ok for now. – android developer Jan 11 '17 at 09:39
  • ok [here](http://pastebin.com/8fHfDpWB) you have 20 lines of code describing how "image matrix" works, run it and watch the `logcat` – pskink Jan 11 '17 at 09:56
  • @pskink Please, if you have an answer, write it, by using the "Answer this Question" button. This way, I can also accept it, and it can be here for as long as the website is here. – android developer Jan 11 '17 at 11:48
  • this is not the answer for your question, it just shows how "image matrix" works – pskink Jan 11 '17 at 12:01
  • @pskink Yes. Thank you for that. – android developer Jan 11 '17 at 15:27

7 Answers7

5

Make FrameLayout with wrap_content around ImageView. Then you could set SwitchView on top of ImageView. You could align it to center, side or corners and using margins to get some fine position.

It still won't scale with image, but you can get pretty good results. If that doesn't fit you, you can programatically get width/height of ImageView and alter position (or margins) of SwitchView accordingly.

JoKr
  • 4,976
  • 8
  • 27
  • 39
  • It won't scale and won't move according to the content of the ImageView, just as I wrote, so this is not a good solution. Getting the height and width will have the same result. I need to set the Switch's size and position based on the content of the ImageView, not the ImageView's size itself. – android developer Jan 10 '17 at 13:25
1

With below you can manage width of switch or any other view as per image view width

android:layout_alignLeft="@+id/imageView"
android:layout_alignRight="@+id/imageView"

<Switch
    android:id="@+id/swi"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/imageView"
    android:layout_alignRight="@+id/imageView" />

<ImageView
    android:id="@+id/imageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/swi"
    android:src="@drawable/download" />

Pavya
  • 6,015
  • 4
  • 29
  • 42
  • If this is for RelativeLayout, this is wrong, because what I asked about is aligning (and optionally resizing) the Switch (and other views) compared to the content shown by the ImageView (meaning it depends on ScaleType and on the surrounding restrictions imposed on the ImageView), and not just the bounding box of the ImageView. – android developer Feb 23 '17 at 07:49
0

As far as i get it, you need the image size displayed inside the image view and set that as the max width of your switch view right?

You need both Java and XML for this,

The XML file is basically as RelativeLayout with the view stacked as needed.

   <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ImageView
            android:src="@drawable/nonet_icon"
            android:id="@+id/iconView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <android.support.v7.widget.SwitchCompat
            android:layout_width="wrap_content"
            android:visibility="gone"
            android:layout_centerInParent="true"
            android:layout_height="wrap_content"
            android:id="@+id/switchView"/>
    </RelativeLayout>

And the Java Code gets the imageWidth and sets it to the SwitchView.

        mSwitchCompat.setVisibility(View.VISIBLE);
//        20% x 25% of Content in ImageView
        final float x = mImageView.getDrawable().getIntrinsicWidth()*.2f;
        final float y = mImageView.getDrawable().getIntrinsicHeight()*.25f;
//        waiting for the view to be drawn
        mSwitchCompat.post(new Runnable() {
            @Override
            public void run() {
//        scale current view W.r.t. x and y values 
             mSwitchCompat.setScaleX((float)mSwitchCompat.getWidth()/x);
                mSwitchCompat.setScaleY((float)mSwitchCompat.getHeight()/y);
            }
        });
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT);
//        30% x 35% of content, for location
        int xMargin  = Math.round(mImageView.getDrawable().getIntrinsicWidth()*.3f);
        int yMargin = Math.round(mImageView.getDrawable().getIntrinsicHeight()*.35f);
//      set margin values, can optionally add for top and bottom
        layoutParams.setMargins(xMargin,0,yMargin,0);
        mSwitchCompat.setLayoutParams(layoutParams);

Ref: Getting Displayed image size of an ImageView Trying to get the display size of an image in an ImageView

Ref: Dynamic size values

Do comment if you need a detailed explaination.

Example: Check this image!

Scaled View on Image: Scaled View on Image!

Community
  • 1
  • 1
MadScientist
  • 2,134
  • 14
  • 27
  • Where is the part that you put the view on top of the ImageView in a specific location, in relation to the imageView's content ? For example, make the view 20%x25% of size of the imageView's content, and put it in 30%x35% of the location compared to the imageView's content. – android developer Feb 27 '17 at 10:38
  • The View is added via the XML File, inside a relative layout. Check the XML file for details. As far as the scaling is concerned: Views can be scaled as need: `// scaling the view` `mSwitchCompat.setScaleX(0.2f);` `mSwitchCompat.setScaleY(0.25f);` `int imageWidth = mImageView.getDrawable().getIntrinsicWidth();` `//Setting it on a customlocation` `mSwitchCompat.setSwitchMinWidth(Math.round(imageWidth/30));` – MadScientist Feb 27 '17 at 11:04
  • Check edit, custom margin can also be set to if Position relative to the main image is required. – MadScientist Feb 27 '17 at 11:15
  • The size you wrote isn't in relation to the imageView's content. It's related to the switch size. Also, setting the size of the switch based on the drawable alone isn't correct, because there are boundaries set to the imageView itself, including ScaleType, width, height, parent restrictions, ... And all of those are for the size. The same needs to be done to the location of the view too. – android developer Feb 27 '17 at 11:49
  • Its just an example method for scaling the view. It can be done based on the imageView Content, using thr `getIntrinsicWidth()` and the `getIntrinicHeight()` Methods. so scaleX can be `getIntrinsicWidth()*.2` similar for scaleY. and as for the location, Custom margins can be set using: `RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(30% of content,0,35% of content,0);` – MadScientist Feb 27 '17 at 12:27
  • and adding the params by `mSwitchCompat.setLayoutParams(layoutParams);` – MadScientist Feb 27 '17 at 12:30
  • Please provide a sample code, so I can try it out to tell if it's correct or not. – android developer Feb 27 '17 at 12:32
  • This code doesn't do anything about the way the ImageView presents the image. This means that using a scaleType and a different width/height to the ImageView would make it fail in putting the view in the correct place and size. Even when changing orientation this code doesn't work. See this screenshots for example (world map taken from: http://www.outline-world-map.com/map-images-original/political-world-map-white-thin-b6a.png ) : postimg.org/image/8xi6sudaz postimg.org/image/n57vhhpzv – android developer Feb 27 '17 at 20:13
0

In Java,

        ImageView imgView = (ImageView) findViewById(R.id.imageView);
        imageView.setBackgroundResource(R.drawable.yourDrawable);
        int width = imgView.getDrawable().getIntrinsicWidth();

        Switch switchKey = (Switch) findViewById(R.id.switchKey);
        switchKey.setMinimumWidth(width);

And in XML, align it with alignLeft and alignRight with ImageView.

  • I don't understand. Where is the part that you put the view on top of the ImageView in a specific location, in relation to the imageView's content ? For example, make the view 20%x25% of size of the imageView's content, and put it in 30%x35% of the location compared to the imageView's content. – android developer Feb 27 '17 at 10:40
  • You can add the switch on top of imageview in xml by using RelativeLayout. And by using th JAVA Code above, you can set the width and size of switch according to the image set in imageview. – saDashiv sinha Feb 27 '17 at 10:43
  • Please show how to do it. According to all that I've tried, it doesn't work (try various ScaleTypes, for example). – android developer Feb 27 '17 at 10:51
0

You can use MarginLayoutParams with Relative Layout to set left and top position in ImageView.

    image = (ImageView) findViewById(R.id.imageID);
    MarginLayoutParams marginParams = new MarginLayoutParams(image.getLayoutParams());
    marginParams.setMargins(left_margin, top_margin, right_margin, bottom_margin);
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
    image.setLayoutParams(layoutParams);

find complete information for this in below link :

MarginLayoutParams

Chetan Joshi
  • 5,582
  • 4
  • 30
  • 43
0

Try this, may be it will help you.

<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/img_background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/semi_transparent"
        android:layout_margin="@dimen/spacing_small"
        android:layout_alignTop="@+id/img_background"
        android:layout_alignBottom="@id/img_background">

        //this layout will expand according to your image size

    </RelativeLayout>

</RelativeLayout>
Ashish M
  • 763
  • 6
  • 13
-1

Do you want to show switch that lay on imageview ?

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_download"
    android:layout_width="100dp"
    android:layout_height="60dp"
    android:layout_centerInParent="true"
    android:orientation="vertical">

    <ImageView
        android:src="@android:drawable/btn_star_big_on"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <Switch
        android:id="@+id/mySwitch"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Switch" />
</RelativeLayout>

enter image description here

Sushant Gosavi
  • 3,647
  • 3
  • 35
  • 55
  • Please read the question carefully. The Switch should be on top, but also in relation to the ImageView's content. For example, in your image, try to put the switch at the right tip of the star, no matter how small or large the star is, and make the switch change its size depending on the size of the star. – android developer Jan 10 '17 at 14:25