2

I am trying to create a complete circular Layout so that if i put any content inside that layout. That content should be inside the circle. How is that possible ? I tried the following way. But the shape is not circular all the time. Sometime it becomes oval depending on the space. How to keep the layout circular all the time and content should come inside it ?

<LinearLayout
            android:id="@+id/zodiac_Layout"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:orientation="vertical"
            android:background="@drawable/circular_background">

            <ImageView
                android:id="@+id/zodiac_img"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginRight="2dp"
                android:adjustViewBounds="true"
                android:src="@drawable/sunrise" />

            <TextView
                android:id="@+id/zodiac_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginLeft="5dp"
                android:text="@string/na"
                android:textColor="#fff"
                android:textSize="@dimen/nakshatra_text_size" />
        </LinearLayout>

This is the circular_background.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#50514F"/>
    <size android:width="5dp"
        android:height="5dp"/>
</shape>

What if I make the ImageView match_parent. It comes out of the circle shape of the Layout. I want the content to be cropped along the circular shape of the layout.

sagar suri
  • 4,351
  • 12
  • 59
  • 122
  • I hope android devices come in different sizes and they are not square for height and width dont match always. So what are yu planning to do withe extra space? – Xenolion Oct 27 '17 at 10:17

1 Answers1

8

Due to what we have chatted in the comments. Now I know what you real want is the Circular crop to your ImageView and also a TextView. So after a dedicated work I have decided to form the solution that will result to an output that is shown in the image below:

in this image.
Dont worry about the textView you can position it anywhere. Even on top of the image! And change its size!

First you will have to know there is no default implementation on this meaning there is no default View class that provides Circular cropped Views in android. So here are the two alternatives for solving this trick using XML ONLY!

FIRST ALTERNATIVE ( BEST OPTION )
We are going to use a FrameLayout which is a layout that add Views on top of each other. That means if you put the first then the second will be on top of the first etc.

Requirements

  • To fit an image well in a circular view then it should be SQUARE(this is just logical) so you we will need to set width and height equal values.

  • We will need a circular shape with stroke (The idea is to put it on top of a well calculated view sizes!)

Inside your drawable folder make a file called circular_image_crop.xml. And paste the code (dont worry will describe it later!) do not forget to read the comments in it:

<?xml version="1.0" encoding="utf-8"?>
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="oval">
  <solid android:color="#00ffffff"/>
   <!--The above colour is completely transparent!-->
  <stroke android:width="20dp" android:color="#ec407a" />
  <size android:width="140dp" android:height="140dp"/>
</shape>

After making that drawable file we will have to make our FrameLayout (This frame layout is not a root view of any view just copy it inside any view you want to show this layout) Go on and paste the code below (we will explain it later!) again read the comments in it:

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ec407a">

        <!-- This is our framelayout! Notice our background color is the same as the one in the stroke of our drawable. Also this is your image view notice the it has width and height similar (square) do use match parent or wrap content just define a square and views will be position by adjust view bounds true-->

        <ImageView
            android:id="@+id/image_view_user_profile_image"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="20dp"
            android:adjustViewBounds="true"
            android:contentDescription="@string/your_image_description"
            android:src="@drawable/your_image" />

        <!-- Ooh here we have another image! This is an image just for displaying our drawable and crop our image (how?? dont worry!) -->

        <ImageView
            android:layout_width="140dp"
            android:layout_height="140dp"
            android:layout_gravity="center_horizontal"
            android:contentDescription="@string/also_your_image_description_if_any"
            android:src="@drawable/circular_image_crop" />
        <!--This text view we almost forget here it is!-->
        <TextView
            android:id="@+id/your_text_view_id"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="125dp"
            android:gravity="center"
            android:text="John Nanai Noni"
            android:textColor="#ffffff"
            android:textSize="16sp"
            android:textStyle="bold" />
    </FrameLayout>

How it works and customizations!???
The good thing is that we used our Frame Layout and position our real View at the centre horizontal(square image). The we made our drawable which is a circular and also have a circular hole(space) at the centre which matches the height and with our picture. Lastly we add our textview and put on top of all those but at the bottom (it should not obscure out image right?).

So the way that we can understand this is viewing the following image as an outline to whats needed.(dont think its complicated):

sample1

So from there we can see how it went on the image at the middle the Circular crop and etc

sample2

The next stage:

sample3

From there we can apply the same background colour to our whole layout (FrameLayout) to hide the Circular things and leave our own visible space.

sample4

And yes we have finished our layout! What about customization.

Customization

For colours you can put your own colour anywhere in the FrameLayout background well as well as the stroke of the drawable. But never change the <solid> colour it should always be completely transparent always.
For customization of the radius of the circular crop lets dig into its mathematics formula to figure out the coverage of the image!

Mathematics

Let your width or height(the image is square remember) of your image be x dps. Then the values in your drawable are

stroke= 0.2071 * x

size(height and width)=stroke + x

You can 2 or 3 dps for elimination of truncation errors!

Actually the mathematics behind is based on the formula below. The formula works if your interested how comment below:
simple method!

SECOND ALTERNATIVE

Another alternative which I think is good for someone who DOES NOT care about the space between the circular view is by making the ImageView inside the CardView and making the corner radius half the size of the CardView for example this code:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView 
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="280dp"
    android:layout_height="280dp"
    android:layout_gravity="center_horizontal"
    android:layout_margin="30dp"
    app:cardCornerRadius="140dp"
    app:cardElevation="12dp">

    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:adjustViewBounds="true"
        android:src="@drawable/login_back_ground" />

 </android.support.v7.widget.CardView>

This is an output I get In android Studio. Also I cant guarantee how is this is going to look like in various devices especially old ones!

cardview image

CONCLUSION

Both methods are good and useful. Understanding both can even lead to more customizations like making using the first alternative with the second to bring about customizations like adding elevations of circular image. But the first method fits number of daily uses and it also bring equal experiences to all android devices.

I hope this will even help future users who might have the same problem.

Community
  • 1
  • 1
Xenolion
  • 12,035
  • 7
  • 33
  • 48
  • Both your solutions doesn't fit my requirement. What if I make the ImageView match_parent. Your solution doesn't work. It comes out of the circle shape. I want the content to be cropped along the circular shape of the layout – sagar suri Oct 27 '17 at 10:48
  • Thanks @Hiren so you want the ImageView to be cropped circularly! Like how profile pictures of some social networks or google account??? is it? – Xenolion Oct 27 '17 at 11:14
  • Please comment to confirm so I can edit my answer. And do you want that for an image View only or the whole layout?? And do you want some parts of the imageview to be cropped off the corners to appear full circularly – Xenolion Oct 27 '17 at 11:18
  • I want to use the ImageView to cover the whole layout and I want a `View` a `Textview` within the circular layout @Xenolion – sagar suri Oct 27 '17 at 11:29
  • I dont get it well @Hiren can you give me a link to the image of how you want it to be! – Xenolion Oct 27 '17 at 11:45
  • Do you want a textView on top of the image? – Xenolion Oct 27 '17 at 11:53
  • Is this what you want?? https://i.pinimg.com/736x/08/a9/0a/08a90a48a9386c314f97a07ba1f0db56--avatar-bb.jpg – Xenolion Oct 27 '17 at 12:00
  • Exactly. Sorry was in a meeting @Xenolion – sagar suri Oct 27 '17 at 13:07
  • 1
    I am back and written a detailed explanation of how to achieve it! Dont get tired reading! hahah and accept it if it solves your problem or helps you to do so. @Hiren . If still it does not work to your needs comment here! – Xenolion Oct 27 '17 at 18:20
  • Great!! such a great solution. You are a champ man. :) Thanks a ton. – sagar suri Oct 28 '17 at 01:44
  • 1
    You are welcome, Ooooh I am glad you solved the problem @Hiren **Happy Coding!** – Xenolion Oct 28 '17 at 03:47