ArcMenu mainImage Мне нужно в нижней части экрана. OnMeasure не позволяет войти в нижнюю часть экрана

Я пытаюсь привести mainImg в нижнюю часть экрана.

/* * Copyright (C) 2012 Capricorn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 

В ArcLayout OnMeasure если я меняю размер на 0, он опускается, но анимация исчезает. Как изменить OnMeasure чтобы img опустился до нижней части экрана, и высота должна быть поднята вверх? Пожалуйста помоги!

 package com.example.splashscreen; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.view.animation.OvershootInterpolator; import android.view.animation.RotateAnimation; import android.view.animation.Animation.AnimationListener; /** * A Layout that arranges its children around its center. The arc can be set by * calling {@link #setArc(float, float) setArc()}. You can override the method * {@link #onMeasure(int, int) onMeasure()}, otherwise it is always * WRAP_CONTENT. * * @author Capricorn * */ public class ArcLayout extends ViewGroup { /** * children will be set the same size. */ private int mChildSize; private int mChildPadding = 5; private int mLayoutPadding = 10; public static final float DEFAULT_FROM_DEGREES = 270.0f; public static final float DEFAULT_TO_DEGREES = 360.0f; private float mFromDegrees = DEFAULT_FROM_DEGREES; private float mToDegrees = DEFAULT_TO_DEGREES; private static final int MIN_RADIUS = 150; /* the distance between the layout's center and any child's center */ private int mRadius; private boolean mExpanded = false; public ArcLayout(Context context) { super(context); } public ArcLayout(Context context, AttributeSet attrs) { super(context, attrs); if (attrs != null) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ArcLayout, 0, 0); mFromDegrees = a.getFloat(R.styleable.ArcLayout_fromDegrees, DEFAULT_FROM_DEGREES); mToDegrees = a.getFloat(R.styleable.ArcLayout_toDegrees, DEFAULT_TO_DEGREES); mChildSize = Math.max(a.getDimensionPixelSize(R.styleable.ArcLayout_childSize, 0), 0); a.recycle(); } } private static int computeRadius(final float arcDegrees, final int childCount, final int childSize, final int childPadding, final int minRadius) { if (childCount < 2) { return minRadius; } final float perDegrees = arcDegrees / (childCount - 1); 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 static Rect computeChildFrame(final int centerX, final int centerY, final int radius, final float degrees, final int size) { final double childCenterX = centerX + radius * Math.cos(Math.toRadians(degrees)); final double childCenterY = centerY + radius * Math.sin(Math.toRadians(degrees)); return new Rect((int) (childCenterX - size / 2), (int) (childCenterY), (int) (childCenterX + size / 2), (int) (childCenterY + size )); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int radius = mRadius = computeRadius(Math.abs(mToDegrees - mFromDegrees), getChildCount(), mChildSize, mChildPadding, MIN_RADIUS); final int size = radius * 2 + mChildSize + mChildPadding + mLayoutPadding * 2; setMeasuredDimension(size, size); final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).measure(MeasureSpec.makeMeasureSpec(mChildSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(mChildSize, 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 = mExpanded ? mRadius : 0; final int childCount = getChildCount(); final float perDegrees = (mToDegrees - mFromDegrees) / (childCount - 1); float degrees = mFromDegrees; for (int i = 0; i < childCount; i++) { Rect frame = computeChildFrame(centerX, centerY, radius, degrees, mChildSize); degrees += perDegrees; getChildAt(i).layout(frame.left, frame.top, frame.right, frame.bottom); } } /** * refers to {@link LayoutAnimationController#getDelayForView(View view)} */ private static long computeStartOffset(final int childCount, final boolean expanded, final int index, final float delayPercent, final long duration, Interpolator interpolator) { final float delay = delayPercent * duration; final long viewDelay = (long) (getTransformedIndex(expanded, childCount, index) * delay); final float totalDelay = delay * childCount; float normalizedDelay = viewDelay / totalDelay; normalizedDelay = interpolator.getInterpolation(normalizedDelay); return (long) (normalizedDelay * totalDelay); } private static int getTransformedIndex(final boolean expanded, final int count, final int index) { if (expanded) { return count - 1 - index; } return index; } private static Animation createExpandAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta, long startOffset, long duration, Interpolator interpolator) { Animation animation = new RotateAndTranslateAnimation(0, toXDelta, 0, toYDelta, 0, 720); animation.setStartOffset(startOffset); animation.setDuration(duration); animation.setInterpolator(interpolator); animation.setFillAfter(true); return animation; } private static Animation createShrinkAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta, long startOffset, long duration, Interpolator interpolator) { AnimationSet animationSet = new AnimationSet(false); animationSet.setFillAfter(true); final long preDuration = duration / 2; Animation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnimation.setStartOffset(startOffset); rotateAnimation.setDuration(preDuration); rotateAnimation.setInterpolator(new LinearInterpolator()); rotateAnimation.setFillAfter(true); animationSet.addAnimation(rotateAnimation); Animation translateAnimation = new RotateAndTranslateAnimation(0, toXDelta, 0, toYDelta, 360, 720); translateAnimation.setStartOffset(startOffset + preDuration); translateAnimation.setDuration(duration - preDuration); translateAnimation.setInterpolator(interpolator); translateAnimation.setFillAfter(true); animationSet.addAnimation(translateAnimation); return animationSet; } private void bindChildAnimation(final View child, final int index, final long duration) { final boolean expanded = mExpanded; final int centerX = getWidth() / 2; final int centerY = getHeight() / 2; final int radius = expanded ? 0 : mRadius; final int childCount = getChildCount(); final float perDegrees = (mToDegrees - mFromDegrees) / (childCount - 1); Rect frame = computeChildFrame(centerX, centerY, radius, mFromDegrees + index * perDegrees, mChildSize); final int toXDelta = frame.left - child.getLeft(); final int toYDelta = frame.top - child.getTop(); Interpolator interpolator = mExpanded ? new AccelerateInterpolator() : new OvershootInterpolator(1.5f); final long startOffset = computeStartOffset(childCount, mExpanded, index, 0.1f, duration, interpolator); Animation animation = mExpanded ? createShrinkAnimation(0, toXDelta, 0, toYDelta, startOffset, duration, interpolator) : createExpandAnimation(0, toXDelta, 0, toYDelta, startOffset, duration, interpolator); final boolean isLast = getTransformedIndex(expanded, childCount, index) == childCount - 1; animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (isLast) { postDelayed(new Runnable() { @Override public void run() { onAllAnimationsEnd(); } }, 0); } } }); child.setAnimation(animation); } public boolean isExpanded() { return mExpanded; } public void setArc(float fromDegrees, float toDegrees) { if (mFromDegrees == fromDegrees && mToDegrees == toDegrees) { return; } mFromDegrees = fromDegrees; mToDegrees = toDegrees; requestLayout(); } public void setChildSize(int size) { if (mChildSize == size || size < 0) { return; } mChildSize = size; requestLayout(); } /** * switch between expansion and shrinkage * * @param showAnimation */ public void switchState(final boolean showAnimation) { if (showAnimation) { final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { bindChildAnimation(getChildAt(i), i, 300); } } mExpanded = !mExpanded; if (!showAnimation) { requestLayout(); } invalidate(); } private void onAllAnimationsEnd() { final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { getChildAt(i).clearAnimation(); } requestLayout(); } } 

Как вы можете видеть в следующем комментарии daCapricorn по аналогичной проблеме.

Он подробно рассказал о возможном решении:

Установите android: layout_alignParentBottom = "true" и android: layout_alignParentLeft = "true" в xml и программным образом вычислите marginBottom и marginLeft (они должны быть отрицательными). MarginBottom = (высота по высоте центра ArcMenuIcon) / 2, marginLeft = (ширина ArcMenu – ширина центра Icon) / 2.

Основная идея здесь – установить желаемые поля на отрицательные значения (мой случай внизу справа). Мне удалось решить эту задачу, вычислив нужный маржи marginBottom = – ((высота высоты центра по высоте ArcMenu) / 2), marginRight = – ((ширина ширины ArcMenu – ширина центра Icon) / 2).

Я не делал этого внутри onMeasure в библиотечном коде ArcLayout.java, я сделал следующее внутри своей деятельности.

В макете моей работы установите layout_alignParent по желанию:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:arc="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" > <com.capricorn.ArcMenu android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:id="@+id/arc_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" arc:childSize="@dimen/menuChildSize" arc:fromDegrees="180" arc:toDegrees="270" /> </RelativeLayout> 

В моей деятельности:

 ArcMenu arcMenu; // the arc menu FrameLayout controlLayout; // the frame layout of the control from library int arcWidth, arcHeight; // arc menu measurments to be calculated , required for margins int controlLayoutWidth, controlLayoutHeight; // controlLayout measurments to be calculated , required for margins boolean isArcMeasureReady, isControlLayoutMeasureReady; // determine if measurements are ready if so apply the margins with the following runnable Runnable runnable = new Runnable() { @Override public void run() { if (isArcMeasureReady && isControlLayoutMeasureReady) { RelativeLayout.LayoutParams params = (LayoutParams) arcMenu // your container LayoutParmas , mine is RelativeLayout .getLayoutParams(); int rightMargin = -((arcWidth - crossWidth) / 2); int bottomMargin = -((arcHeight - crossHeight) / 2); params.setMargins(0, 0, rightMargin, bottomMargin); arcMenu.setLayoutParams(params); } } }; 

My onCreate:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); isArcMeasureReady = isControlLayoutMeasureReady = false; controlLayout = (FrameLayout) findViewById(com.capricorn.R.id.control_layout); ... ViewTreeObserver viewTreeObserverControlLayout = controlLayout.getViewTreeObserver(); if (viewTreeObserverControlLayout.isAlive()) { viewTreeObserverControlLayout .addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { controlLayout.getViewTreeObserver() .removeGlobalOnLayoutListener(this); controlLayoutWidth = controlLayout.getWidth(); controlLayoutHeight = controlLayout.getHeight(); isControlLayoutMeasureReady = true; runOnUiThread(runnable); } }); } ViewTreeObserver viewTreeObserver = arcMenu.getViewTreeObserver(); if (viewTreeObserver.isAlive()) { viewTreeObserver .addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { arcMenu.getViewTreeObserver() .removeGlobalOnLayoutListener(this); arcWidth = arcMenu.getWidth(); arcHeight = arcMenu.getHeight(); isArcMeasureReady = true; runOnUiThread(runnable); } }); } 

Я тестировал это на нескольких устройствах, и он отлично работает, потому что вычисление является динамическим.

Надеюсь, это поможет наслаждаться великолепным виджетами этого парня daCacricorn