Circular positioning
ConstraintLayout 1.1.0-beta3から、Circular positioningという制約が追加されました。
https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html
これはView Aの位置から極座標でView Bを配置できるようにするものです。
layout_constraintCircle
layout_constraintCircleRadius
layout_constraintCircleAngle
(12時方向が0、値を増やすと時計回りに角度が変わる。負の値や360を超えた値も使える)
の3つのパラメータを指定することで利用できます。
面白そうだったのでこれを使って簡単なサンプルを作ってみました。
EditTextに数値を入力して画面遷移すると、その数だけ等間隔にTextViewを円状に表示するアプリです。
TextViewはコードから動的にaddView()するようにしています。
実装
環境
Android Studio:3.0.1
ConstraintLayout:1.1.0-beta3
導入
build.gradleにConstraintLayout 1.1.0-beta3を追加します。
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の座標を出すためにマージンの計算などめんどくさい処理をたくさん書かないといけませんでした。その手間が大幅に解消できるところはメリットだと思います。