32

I have a cell with a fixed width and height, let it be 100x100px. Inside that cell I want to display an ImageView with a border around.
My first idea was to put a background resource to the ImageView, and add a padding of 1dp to create the border effect:

<LinearLayout
        android:layout_width="100dp"
        android:layout_height="100dp" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/image_border"
        android:padding="1dp"
        android:src="@drawable/test_image" />

</LinearLayout>

Apparently this should work, but it doesn't, or at least not as expected.
The problem is that the ImageView background fills the entire 100x100px cell's space, thus, if the image's width is less than 100px, then the top and bottom border will appear larger.

Notice the yellow border, I need it to be exactly 1px around the ImageView:

enter image description here

Any help, idea, suggestion of any kind is much, much appreciated.

Andy Res
  • 15,963
  • 5
  • 60
  • 96

10 Answers10

51

If you put the padding=1 and the background color in the LinearLayout, you'll have a 1px yellow border.

Christine
  • 5,617
  • 4
  • 38
  • 61
  • 1
    To put padding=1 on the LinearLayout? If so this won't work. Pay attention that the LinearLayout has a fixed width of 100x100px. So, setting the background to it, will make a 100x100 yellow background, and it won't stick to ImageView dimentions. Or, maybe I didn't understand correctly, if you can show a line of code, I'll appreciate very much. – Andy Res Sep 24 '12 at 20:33
  • I was assuming that your image would fill the linearlayout. You can also set the LinearLayout to "wrap_content", give it a 1dp padding, then put in the image. Or you give the image a layout_margin of 1dp, inside the yellow LinearLayout that wraps it. – Christine Sep 25 '12 at 18:40
  • What if you want to keep padding in place with its default color and still add a border around the image. For instance in a GridView you want to highlight a selection without distoring padding between cells. – Aaron Dancygier Oct 28 '16 at 20:15
  • Simple and elegant answer – Hasan Shouman Feb 20 '21 at 21:40
32

Here is what worked for me...

<!-- @drawable/image_border -->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
  <solid android:color="@color/colorPrimary"/>
  <stroke android:width="1dp" android:color="#000000"/>
  <padding android:left="1dp" android:top="1dp" android:right="1dp" android:bottom="1dp"/>
</shape>

<ImageView
  android:layout_width="300dp"
  android:layout_height="300dp"
  android:layout_gravity="center"
  android:padding="1dp"
  android:cropToPadding="true"
  android:scaleType="centerCrop"
  android:background="@drawable/image_border"/>

Here it the result that I get with an viewpager and imageview with a border.

Example imageview with border 1dp black.

Ray Hunter
  • 15,137
  • 5
  • 53
  • 51
9

If the images are variable in size then you'll always get that effect. I guess you need to set a fixed size for the ImageView and give it a set background colour - from the look of your example black would make sense. Wrap the imageview in a FrameLayout or just a view with a yellow background and 1px padding.

EDIT


I had a think about this and my answer didn't feel right so...

If you set each ImageView with a fixed size, padding and margin. and then set the background colour as required you can get the effect you want.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent" >


        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:background="#52D017"
            android:padding="1dp"
            android:layout_margin="5dp"
            android:src="@drawable/test1"
            tools:ignore="ContentDescription" />

        <ImageView
            android:id="@+id/imageView2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="5dp"
            android:background="#52D017"
            android:padding="1dp"
            android:src="@drawable/test2"
            tools:ignore="ContentDescription" />

</LinearLayout>

In the screenshot both displayed images are less than 100px in width and different heights.

example

This doesn't handle images with transparent backgrounds as then the (in this case) yellow green colour shows through. You could solve this by wrapping each ImageView in a FrameLayout. Making the ImageView background black and setting the FrameLayout to WrapContent with the required padding (I think)

Paul D'Ambra
  • 7,629
  • 3
  • 51
  • 96
4

you can use the custom imageview, from where you can get the border, here is the code. you can also change the width of padding and stroke width according to your need. It is specify just below the first line of code, thank you

public class FreeCollage extends ImageView {

    private static final int PADDING = 8;
    private static final float STROKE_WIDTH = 5.0f;

    private Paint mBorderPaint;

    public FreeCollage(Context context) {
        this(context, null);
    }

    public FreeCollage(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        setPadding(PADDING, PADDING, PADDING, PADDING);
    }

    public FreeCollage(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initBorderPaint();
    }

    private void initBorderPaint() {
        mBorderPaint = new Paint();
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setColor(Color.WHITE);
        mBorderPaint.setStrokeWidth(STROKE_WIDTH);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawRect(PADDING, PADDING, getWidth() - PADDING, getHeight() - PADDING, mBorderPaint);
    }
}
Shubham
  • 535
  • 5
  • 11
4

This is what worked for me:

    <ImageView
        android:id="@+id/dialpad_phone_country_flag"
        android:layout_width="22dp"
        android:layout_height="15dp"
        android:scaleType="fitXY"
        android:background="@color/gen_black"
        android:padding="1px"/>
Goran Horia Mihail
  • 3,536
  • 2
  • 29
  • 40
3

Just add the property adjustViewBounds to the ImageView.

<ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/image_border"
        android:padding="1dp"
        android:adjustViewBounds="true"
        android:src="@drawable/test_image" />

Kindly note that android:adjustViewBounds="true" works only with android:layout_width and android:layout_height set to "wrap_content".

string.Empty
  • 10,393
  • 4
  • 39
  • 67
rricarrdo
  • 91
  • 4
1

just add bellow line in your ImageView layout

if layout_width and layout_height of imageview is not match_parent than use,

android:adjustViewBounds = "true"

or

android:adjustViewBounds = "true"
android:scaleType="fitXY"

or

android:adjustViewBounds = "true"
android:scaleType="centerCrop"
varotariya vajsi
  • 3,965
  • 37
  • 39
1

Starting with version 1.2.0-alpha03 of the Material Components Library there is ShapeableImageView that makes this easy to do. You can use something like the following to add a border with round corners.

  <com.google.android.material.imageview.ShapeableImageView
      ...
      android:scaleType="centerCrop"
      android:padding="2dp" 
      app:shapeAppearanceOverlay="@style/roundedImageView"
      app:srcCompat="@drawable/image"
      app:strokeColor="@color/yourColor"
      app:strokeWidth="2dp"
   />

The padding above should be the same or slightly larger than your border so that it shows up properly.

with:

  <style name="roundedImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">12dp</item>
  </style>

The strokeColor and strokeWidth could alternatively be included as part of the style instead of in the xml.

Ben
  • 3,346
  • 6
  • 32
  • 51
0

Following is the code snippet which I used in my simplest solution.

<FrameLayout
    android:layout_width="112dp"
    android:layout_height="112dp"
    android:layout_marginLeft="16dp" <!-- May vary according to your needs -->
    android:layout_marginRight="16dp" <!-- May vary according to your needs -->
    android:layout_centerVertical="true">
    <!-- following imageView acts as the boarder which sitting in the background of our main container ImageView -->
    <ImageView
        android:layout_width="112dp"
        android:layout_height="112dp"
        android:background="#000"/>
    <!-- following imageView holds the image as the container to our image -->
    <!-- layout_margin defines the width of our boarder, here it's 1dp -->
    <ImageView
        android:layout_width="110dp"
        android:layout_height="110dp"
        android:layout_margin="1dp"
        android:id="@+id/itemImageThumbnailImgVw"
        android:src="@drawable/banana"
        android:background="#FFF"/>
</FrameLayout>

If you want further explanation please look at the following link where I'd explained it well enough.

Hope this may be helpful to you anyone out there!

Cheers!

Community
  • 1
  • 1
Randika Vishman
  • 7,983
  • 3
  • 57
  • 80
0

You have to add scaletyle in your imageview. After that your image would be fit.

android:scaleType="fitXY"

Shubham
  • 1
  • 1