LoginSignup
6
6

More than 5 years have passed since last update.

ConstraintLayoutのCircular positioningを使って円状にViewを配置してみる

Last updated at Posted at 2017-12-05

Circular positioning

ConstraintLayout 1.1.0-beta3から、Circular positioningという制約が追加されました。
https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html

circle1.png
circle2.png
(画像は上記URLより引用)

これはView Aの位置から極座標でView Bを配置できるようにするものです。
layout_constraintCircle
layout_constraintCircleRadius
layout_constraintCircleAngle(12時方向が0、値を増やすと時計回りに角度が変わる。負の値や360を超えた値も使える)
の3つのパラメータを指定することで利用できます。

面白そうだったのでこれを使って簡単なサンプルを作ってみました。
EditTextに数値を入力して画面遷移すると、その数だけ等間隔にTextViewを円状に表示するアプリです。
TextViewはコードから動的にaddView()するようにしています。

input_num.png

circule.png

実装

環境

Android Studio:3.0.1
ConstraintLayout:1.1.0-beta3

導入

build.gradleにConstraintLayout 1.1.0-beta3を追加します。
ruby
implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta3'

コード

1つ目の画面はEditTextに入力してボタンで画面遷移するだけなので省略。
2つ目の画面に使うコードを以下に示します。

CircularPositionActivity.java

public class CircularPositionActivity extends AppCompatActivity {

    private static final String NUMBER_OF_VIEW = "numberOfView";

    public static Intent createIntent(Context context, int num) {
        Intent intent = new Intent(context, CircularPositionActivity.class);
        intent.putExtra(NUMBER_OF_VIEW, num);
        return intent;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        int num = intent.getIntExtra(NUMBER_OF_VIEW, 0);

        ActivityCircularPositionBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_circular_position);

        ConstraintLayout root = binding.root;
        View centralView = binding.centralView;

        int radius = getResources().getDimensionPixelSize(R.dimen.circle_radius);

        // 入力された数だけ等間隔に配置する
        for (int i = 0; i < num; i++) {
            TextView textView = new TextView(this);

            ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(
                    ConstraintLayout.LayoutParams.WRAP_CONTENT,
                    ConstraintLayout.LayoutParams.WRAP_CONTENT);

            layoutParams.circleConstraint = centralView.getId(); // 基点になるViewを指定
            layoutParams.circleAngle = computeAngle(num, i); // 角度を指定
            layoutParams.circleRadius = radius; // 半径を指定(dp)
            textView.setLayoutParams(layoutParams);

            textView.setText(String.valueOf(i));

            root.addView(textView);
        }
    }

    private static final int CIRCLE_RADIUS = 360;

    private float computeAngle(int num, int index) {
        float angleUnit = (float) CIRCLE_RADIUS / num;
        return angleUnit * index;
    }
}

activity_circular_position.xml

<?xml version="1.0" encoding="utf-8"?>

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" >

    <android.support.constraint.ConstraintLayout
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <View
            android:id="@+id/centralView"
            android:layout_width="3dp"
            android:layout_height="3dp"
            android:background="@color/colorAccent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>

    </android.support.constraint.ConstraintLayout>
</layout>

dimens.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="circle_radius">120dp</dimen>
</resources>

感想

正直なところCircular positioningをどう活かすべきなのかまだよくわかりませんが、今回のようなレイアウトを組むのには非常に簡単に実装できます。
今までだと同じことを実装するのに、一つ一つのViewの座標を出すためにマージンの計算などめんどくさい処理をたくさん書かないといけませんでした。その手間が大幅に解消できるところはメリットだと思います。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6