Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Layout views rotated and spaced around a circle?

I'm trying to figure out a way to layout a series of views around a circle, in such a way that each view is rotated to be facing outward from the circle. The picture below is a rough sketch of what I'm looking for. The outside block is the layout/viewgroup, the red squares represent the views I want to rotate.

Rough Sketch of what I want to do

I'm familiar with the PivotX, PivotY, and Rotation view properties and suspect I will be making use of these in some way, but I'm not sure how to use these in concert with an appropriate layout to get the desired effect.

like image 229
CodeFusionMobile Avatar asked Jan 05 '13 15:01

CodeFusionMobile


2 Answers

Here's an example that does this. I created a new Android project and replaced the RelativeLayout that's already there, with a FrameLayout. It's >= API 11 only because of translate and rotate calls in View:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/hello_world" />
</FrameLayout>

I'll create some quick views in code, just replace them with whatever views you have. I'm placing them all in the center of the layout, by setting the gravity of their LayoutParams to Gravity.CENTER. Then, I'm translating and rotating them to their correct positions:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final FrameLayout main = (FrameLayout)findViewById(R.id.main);

    int numViews = 8;
    for(int i = 0; i < numViews; i++)
    {
        // Create some quick TextViews that can be placed.
        TextView v = new TextView(this);
        // Set a text and center it in each view.
        v.setText("View " + i);
        v.setGravity(Gravity.CENTER);
        v.setBackgroundColor(0xffff0000);
        // Force the views to a nice size (150x100 px) that fits my display.
        // This should of course be done in a display size independent way.
        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(150, 100);
        // Place all views in the center of the layout. We'll transform them
        // away from there in the code below.
        lp.gravity = Gravity.CENTER;
        // Set layout params on view.
        v.setLayoutParams(lp);

        // Calculate the angle of the current view. Adjust by 90 degrees to
        // get View 0 at the top. We need the angle in degrees and radians.
        float angleDeg = i * 360.0f / numViews - 90.0f;
        float angleRad = (float)(angleDeg * Math.PI / 180.0f);
        // Calculate the position of the view, offset from center (300 px from
        // center). Again, this should be done in a display size independent way.
        v.setTranslationX(300 * (float)Math.cos(angleRad));
        v.setTranslationY(300 * (float)Math.sin(angleRad));
        // Set the rotation of the view.
        v.setRotation(angleDeg + 90.0f);
        main.addView(v);
    }
}

And this is the result:

Image of 8 views in a circle

like image 196
Daniel Johansson Avatar answered Oct 19 '22 23:10

Daniel Johansson


The answer by @Daniel is great.

If you need more functionality you can use this nice library on GitHub called Android-CircleMenu

enter image description here

like image 22
dmSherazi Avatar answered Oct 19 '22 23:10

dmSherazi