如何将图标放在Android中的圆形图像顶部?

时间:2016-06-07 08:48:42

标签: android xml layout

enter image description here

我只是想要实现上面图像的确切内容。红色是我的图标,我需要将它放在圆形图像边框的顶部。每个红色图标都有自己的功能。说它们是评级按钮。在这里,我需要帮助,如何使XML设计实现这一目标。我不知道该怎么做。

2 个答案:

答案 0 :(得分:1)

看看这堂课。它应该按你的意愿工作:

public class CircleLayout extends ViewGroup {

    private static final float DEFAULT_FROM_DEGREES = -90f;

    private static final float DEFAULT_TO_DEGREES = 270f;

    private static final int MIN_RADIUS_DP = 100;

    private static final float DEFAULT_CHILD_PADDING_DP = 5f;

    private final Rect tempChildFrame = new Rect();

    private final float fromDegrees;

    private final float toDegrees;

    private final int childPadding;

    private final int minRadius;

    private int radius;


    private int childSize;

    private boolean expanded;

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

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

    public CircleLayout(Context context, AttributeSet attrs, int def) {
        super(context, attrs);
        final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CircleLayout, 0, 0);
        try {
            childSize = Math.max(a.getDimensionPixelSize(R.styleable.CircleLayout_childSize, 0), 0);
            fromDegrees = a.getFloat(R.styleable.CircleLayout_fromDegrees, DEFAULT_FROM_DEGREES);
            toDegrees = a.getFloat(R.styleable.CircleLayout_toDegrees, DEFAULT_TO_DEGREES);
            final float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_CHILD_PADDING_DP, getResources().getDisplayMetrics());
            childPadding = (int) a.getDimension(R.styleable.CircleLayout_childPadding, px);
            expanded = a.getBoolean(R.styleable.CircleLayout_expandedChild, true);
            minRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, MIN_RADIUS_DP, getResources().getDisplayMetrics());
        } finally {
            a.recycle();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        radius = computeRadius(Math.abs(toDegrees - fromDegrees), getChildCount(), childSize, childPadding, minRadius);
        final int size = radius * 2 + childSize + childPadding;

        setMeasuredDimension(size + getPaddingLeft() + getPaddingRight(), size + getPaddingTop() + getPaddingBottom());

        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            getChildAt(i).measure(MeasureSpec.makeMeasureSpec(childSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(childSize, MeasureSpec.EXACTLY));
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int centerX = getWidth() / 2;
        final int centerY = getHeight() / 2;
        final int radius = expanded ? this.radius : 0;

        final int childCount = getChildCount();
        final float perDegrees = (toDegrees - fromDegrees) / childCount;

        float degrees = fromDegrees;
        for (int i = 0; i < childCount; i++) {
            computeChildFrame(centerX, centerY, radius, degrees, childSize, tempChildFrame);
            degrees += perDegrees;
            getChildAt(i).layout(tempChildFrame.left, tempChildFrame.top, tempChildFrame.right, tempChildFrame.bottom);
        }
    }

    private int computeRadius(float arcDegrees, int childCount, int childSize, int childPadding, int minRadius) {
        if (childCount < 2) {
            return minRadius;
        }

        final float perDegrees = arcDegrees / childCount;
        final float perHalfDegrees = perDegrees / 2;
        final int perSize = childSize + childPadding;

        final int radius = (int) ((perSize / 2) / Math.sin(Math.toRadians(perHalfDegrees)));

        return Math.max(radius, minRadius);
    }

    private void computeChildFrame(int centerX, int centerY, int radius, float degrees, int size, Rect result) {
        final double childCenterX = centerX + radius * Math.cos(Math.toRadians(degrees));
        final double childCenterY = centerY + radius * Math.sin(Math.toRadians(degrees));
        final float halfSize = size * .5f;
        result.left = (int) (childCenterX - halfSize);
        result.top = (int) (childCenterY - halfSize);
        result.right = (int) (childCenterX + halfSize);
        result.bottom = (int) (childCenterY + halfSize);
    }

    public void expand() {
        expanded = true;
        requestLayout();
    }

    public void shrink() {
        expanded = false;
        requestLayout();
    }

    public void setChildSize(int size) {
        if (childSize == size || size < 0) {
            return;
        }
        childSize = size;
        requestLayout();
    }

    public boolean isExpanded() {
        return expanded;
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        final Parcelable superState = super.onSaveInstanceState();
        final SavedState result = new SavedState(superState);
        result.childSize = childSize;
        result.expanded = expanded;
        return result;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (!(state instanceof SavedState)) {
            super.onRestoreInstanceState(state);
            return;
        }

        final SavedState ss = (SavedState) state;
        childSize = ss.childSize;
        expanded = ss.expanded;
        super.onRestoreInstanceState(ss.getSuperState());
    }

    public static class SavedState extends BaseSavedState {

        @SuppressWarnings("hiding")
        public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };

        private int childSize;

        private boolean expanded;

        SavedState(Parcelable superState) {
            super(superState);
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeInt(childSize);
            out.writeInt(expanded ? 1 : 0);
        }

        private SavedState(Parcel in) {
            super(in);
            childSize = in.readInt();
            expanded = in.readInt() != 0;
        }
    }
}

您还必须为此视图添加样式:

<declare-styleable name="CircleLayout">
    <attr name="childSize" format="dimension"/>
    <attr name="childPadding" format="dimension"/>
    <attr name="fromDegrees" format="integer"/>
    <attr name="toDegrees" format="integer"/>
    <attr name="expandedChild" format="boolean"/>
</declare-styleable>

使用示例:

       <your.package.CircleLayout
                android:clipChildren="false"
                android:id="@+id/test_circle_view"
                android:layout_width="match_parent"
                app:childSize="50dp"
                app:childPadding="25dp"
                app:expandedChild="true"
                android:layout_height="match_parent">
            <ImageView
                    android:id="@+id/circle_item_1"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:background="@drawable/some_circle"/>
            <ImageView
                    android:id="@+id/circle_item_2"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:background="@drawable/some_circle"/>
             <ImageView
                    android:id="@+id/circle_item_3"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:background="@drawable/some_circle"/>
             <ImageView
                    android:id="@+id/circle_item_4"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:background="@drawable/some_circle"/>
            <ImageView
                    android:id="@+id/circle_item_5"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:background="@drawable/some_circle"/>
             <ImageView
                    android:id="@+id/circle_item_6"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:background="@drawable/some_circle"/>

        </your.package.CircleLayout>

答案 1 :(得分:1)

问题的确切解决方案是使用 ConstraintLayout中的循环定位 ,有关它的更多信息,您可以点击此链接: https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html#CircularPositioning

希望这可以完全解决您的问题,从而帮助您构建所需的用户界面。