Я пытаюсь создать пользовательское представление Android, которое состоит из нескольких экземпляров FloatingActionButton
(пространство имен android.support.design.widget
), которые расположены по кругу.
Для этого я создаю новое представление, которое наследуется от ViewGroup
. Код выглядит следующим образом:
package myapp;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.support.design.widget.FloatingActionButton;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.ImageView;
import myapp.R;
public class ButtonOverlayView extends ViewGroup
{
private final float _radius = 200.0f;
private int _desiredSize;
public ButtonOverlayView(Context context)
{
super(context);
initializeViewGroup(context);
}
public ButtonOverlayView(Context context, AttributeSet attrs)
{
super(context, attrs);
initializeViewGroup(context);
}
public ButtonOverlayView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
initializeViewGroup(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
_desiredSize = 600;
measureChildren(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(_desiredSize, _desiredSize);
}
@Override
protected void onLayout(boolean b, int i, int i1, int i2, int i3)
{
layoutChildren();
}
private void initializeViewGroup(Context context)
{
createChildren(context, getIconIdentifiers(), getColorIdentifiers());
}
private void createChildren(Context context, int[] iconIdentifiers, int[] colorIdentifiers)
{
for(int i = 0; i < iconIdentifiers.length; i++)
{
final FloatingActionButton button = new FloatingActionButton(context);
button.setImageResource(iconIdentifiers[i]);
button.setSize(FloatingActionButton.SIZE_NORMAL);
button.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
button.setBackgroundTintList(ColorStateList.valueOf(colorIdentifiers[i]));
button.setClickable(true);
addView(button);
}
}
private void layoutChildren()
{
int buttonCount = getChildCount();
int center = _desiredSize / 2;
float angle = 0.0f;
float angleIncrement = 360.0f / (buttonCount - 1);
FloatingActionButton button = (FloatingActionButton)getChildAt(0);
int halfWidth = button.getMeasuredWidth() / 2;
int halfHeight = button.getMeasuredHeight() / 2;
button.layout(center - halfWidth, center - halfHeight, center + halfWidth, center + halfHeight);
for(int i = 1; i < buttonCount; i++)
{
button = (FloatingActionButton)getChildAt(i);
halfWidth = button.getMeasuredWidth() / 2;
halfHeight = button.getMeasuredHeight() / 2;
double radians = Math.toRadians(angle);
int x = (int)(Math.cos(radians) * _radius) + center;
int y = (int)(Math.sin(radians) * _radius) + center;
button.layout(x - halfWidth, y - halfHeight, x + halfWidth, y + halfHeight);
angle += angleIncrement;
}
}
private int[] getIconIdentifiers()
{
final TypedArray icons = getResources().obtainTypedArray(R.array.icons);
int[] iconIdentifiers = new int[icons.length()];
try
{
for(int i = 0; i < icons.length(); i++)
{
iconIdentifiers[i] = icons.getResourceId(i, -1);
}
}
finally
{
icons.recycle();
}
return iconIdentifiers;
}
private int[] getColorIdentifiers()
{
final TypedArray colors = getResources().obtainTypedArray(R.array.colors);
int[] colorIdentifiers = new int[colors.length()];
try
{
for(int i = 0; i < colors.length(); i++)
{
colorIdentifiers[i] = colors.getResourceId(i, -1);
}
}
finally
{
colors.recycle();
}
return colorIdentifiers;
}
}
Значки и цвета для FloatingActionButton
предоставляются в отдельном XML-файле со следующим содержанием:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="icons">
<item>@android:drawable/ic_delete</item>
<item>@android:drawable/ic_input_add</item>
<item>@android:drawable/ic_menu_call</item>
<item>@android:drawable/ic_delete</item>
<item>@android:drawable/ic_input_add</item>
<item>@android:drawable/ic_menu_call</item>
<item>@android:drawable/ic_delete</item>
</array>
<array name="colors">
<item>@color/colorPrimary</item>
<item>@color/colorPrimary</item>
<item>@color/colorPrimary</item>
<item>@color/colorPrimary</item>
<item>@color/colorPrimary</item>
<item>@color/colorPrimary</item>
<item>@color/colorAccent2</item>
</array>
</resources>
Технически все это работает, то есть компилируется и отображается при интеграции в приложение Android. Однако при визуализации экземпляры FloatingActionButton
выглядят "странно".
Следующие скриншоты иллюстрируют, что я имею в виду под «странным»:
Телефон 1 (Android 8.1):
На левом скриншоте показаны все кнопки в незажатом состоянии, в то время как на правом скриншоте нажата нижняя правая кнопка.
Телефон 2 (Android 9):
То же, что и выше, слева - состояние без щелчка, справа - нажатие правой нижней кнопки.
У кого-нибудь есть объяснение, почему эти кнопки выглядят "странно"? И как бы я исправить эту проблему?
Редактировать
Вдохновленный этим ТАКИМ вопросом, я более подробно рассмотрел следующие зависимости, которые я использую:
com.android.support:appcompat-v7:25.3.1
com.android.support:support-v4:25.3.1
com.android.support:support-annotations:+
com.android.support:design:25.3.1
com.android.support:support-vector-drawable:25.3.1
Поскольку это потенциально может быть ошибка в этих библиотеках, я обновил их до 28.0.0
, но оптический результат остается таким же, как на скриншотах выше.