22

I want to develop following screen in Android.enter image description here

I used CircleLayout but I am still not able to achieve desired output. See following code and screenshot.

<com.example.hl.CircleLayout
        android:id="@+id/pie"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        custom:dividerWidth="5dp"
        custom:innerCircle="@drawable/profile_pic_icon"
        custom:innerRadius="50dp"
        custom:layoutMode="pie"
        custom:sliceDivider="@android:color/transparent" >

        <RelativeLayout
            android:id="@+id/appt_center_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/appt_center_bg" >

            <TextView
                android:id="@+id/one"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:onClick="onClick"
                android:text="APP CENTER"
                android:textStyle="bold" />
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/meds_cabinet_bg" >

            <TextView
                android:id="@+id/two"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:onClick="onClick"
                android:text="MEDS CABINET"
                android:textStyle="bold" />
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/check_in_bg" >

            <TextView
                android:id="@+id/three"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:onClick="onClick"
                android:text="CHECK-IN"
                android:textStyle="bold" />
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/my_tracker_bg" >

            <TextView
                android:id="@+id/four"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:onClick="onClick"
                android:text="MY TRACKERS"
                android:textStyle="bold" />
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/myaccount_bg" >

            <TextView
                android:id="@+id/five"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:onClick="onClick"
                android:text="MY ACCOUNTS"
                android:textStyle="bold" />
        </RelativeLayout>
    </com.example.hl.CircleLayout>

screenshot enter image description here

Question:-

Is there any other library that can help developing the desired screen?

How to develop such screen using custom view? I mean what are steps to develop such custom view easily?

ligi
  • 39,001
  • 44
  • 144
  • 244
dira
  • 30,304
  • 14
  • 54
  • 69
  • I would probably use the deprecated AbsoluteLayout and perform all x,y calculations of the different buttons myself relatively to the total available size. Remember to re-calc all positions on resize. – talkol Oct 01 '13 at 12:50
  • 2
    Have you checked the example project? The first difference I see is that all the `CircleLayout`'s direct children have `match_parent` for the height/width, while yours don't. Go through it and mimic the example as best you can, then see if it gets you closer. By the way, "Is there other library..." is off-topic here, and your other question is too broad. I'd stick with "How can I fix this CircleLayout...". – Geobits Oct 01 '13 at 13:00
  • @becomputer06 Did you solve the problem? – SeniorJD Jan 12 '14 at 16:53
  • This library does something similar to what you are asking for with even more features https://github.com/xresco/CircularLayout – xresco Nov 12 '14 at 14:31

1 Answers1

31

I have implemented a library for circular layout. Currently under development, basically meets need I think. Feel free to fork and develop.

https://github.com/ycagri/CircularLayout

End of Edit

You can use a custom layout given below. Number of items, inner radius and outer radius are defined in class. You can use those variables as custom layout attribute. The layout given below draws android launcher icon in the middle and around the circles. Titles are drawn below selection items.

Screenshot belongs to Nexus 7 device. Extra margin and padding can be defined to get better results on different screen resolutions.

public class CircleLayout extends View {

private final static int TOTAL_DEGREE = 360;
private final static int START_DEGREE = -90;

private Paint mPaint;
private RectF mOvalRect = null;

private int mItemCount = 5;
private int mSweepAngle;

private int mInnerRadius;
private int mOuterRadius;
private Bitmap mCenterIcon;
private int[] mColors = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.CYAN};
private String[] mTitles = {"APPT CENTER", "MEDS CABINET", "CHECK-IN", "MY TRACKERS", "MY ACCOUNTS"};

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

public CircleLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public CircleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setStrokeWidth(2);

    mSweepAngle = TOTAL_DEGREE / mItemCount;

    mInnerRadius = 125;
    mOuterRadius = 400;

    mCenterIcon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
}

@Override
protected void onDraw(Canvas canvas) {

    int width = getWidth();
    int height = getHeight();

    if (mOvalRect == null) {
        mOvalRect = new RectF(width / 2 - mOuterRadius, height / 2 - mOuterRadius, width / 2 + mOuterRadius, height / 2 + mOuterRadius);
    }

    for (int i = 0; i < mItemCount; i++) {
        int startAngle = START_DEGREE + i * mSweepAngle;
        mPaint.setColor(mColors[i]);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawArc(mOvalRect, startAngle, mSweepAngle, true, mPaint);

        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawArc(mOvalRect, startAngle, mSweepAngle, true, mPaint);

        int centerX = (int) ((mOuterRadius + mInnerRadius) / 2 * Math.cos(Math.toRadians(startAngle + mSweepAngle / 2)));
        int centerY = (int) ((mOuterRadius + mInnerRadius) / 2 * Math.sin(Math.toRadians(startAngle + mSweepAngle / 2)));
        canvas.drawBitmap(mCenterIcon, width / 2 + centerX - mCenterIcon.getWidth() / 2, height / 2 + centerY - mCenterIcon.getHeight() / 2, null);

        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawText(mTitles[i], width / 2 + centerX - mCenterIcon.getWidth() / 2, height / 2 + centerY + mCenterIcon.getHeight(), mPaint);
    }

    mPaint.setColor(Color.WHITE);
    mPaint.setStyle(Paint.Style.FILL);
    canvas.drawCircle(width / 2, height / 2, mInnerRadius, mPaint);
    canvas.drawBitmap(mCenterIcon, width / 2 - mCenterIcon.getWidth() / 2, height / 2 - mCenterIcon.getHeight() / 2, null);

    super.onDraw(canvas);
}
}

enter image description here

Arash Hatami
  • 5,297
  • 5
  • 39
  • 59
ycagri
  • 434
  • 7
  • 19
  • 1
    But how to make items clickable?? – Mohamed Dec 06 '14 at 23:20
  • You should override the onTouch method. You can get touch position and have to calculate which item is touched. When related item is touched, you can just simply add some opacity to color. – ycagri Dec 08 '14 at 07:42
  • hey @ycagri if i overirde on touched event ..and after calculating of view how can i transfer to next page ...i want whenever any view got clicked ..it should transfer to that page – Tufan Mar 03 '16 at 08:22
  • @ycagri Instead of `Paint` i tried to use `ImageView` but i'm not getting fitxy scaled image. please help – Aks4125 Apr 18 '16 at 07:47
  • @Aks4125 If you want to use ImageView, you should extend the class from ViewGroup. Then add image views to this view group manually. This should work in your case. – ycagri Apr 18 '16 at 11:33
  • how to draw the labels outside the circle and make it in the right location? – whd.nsr Oct 03 '17 at 14:45
  • @whd.nsr While calculating centerX and centerY, I used (int) ((mOuterRadius + mInnerRadius) / 2 to find middle of area between inner circle and outer circle. If you use that part as (int) ((mOuterRadius + mInnerRadius), it will draw outside. – ycagri Oct 03 '17 at 15:11
  • @ycagri how can I remove the black border? – Ast Feb 26 '20 at 11:59
  • 1
    @Ast check out these lines: mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); canvas.drawArc(mOvalRect, startAngle, mSweepAngle, true, mPaint); These lines draws all the black borders. However, if you only want to remove outer black border, you need to draw simple lines between sections. – ycagri Mar 10 '20 at 08:38