2012-11-16 35 views
8

Tôi đang cố gắng đưa mainImg xuống đáy màn hình.ArcMenu mainImage Tôi cần ở cuối màn hình. OnMeasure không cho phép nó xuất hiện ở cuối màn hình

/* 
* 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. 
*/ 

Trong ArcLayoutOnMeasure nếu tôi thay đổi kích thước để 0 nó đi xuống nhưng các hình ảnh động biến mất. Làm thế nào để thay đổi OnMeasure để làm cho img đi xuống dưới cùng của màn hình và chiều cao nên được đưa lên trên? Hãy giúp tôi!

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(); 
    } 
} 
+0

Bạn đã khắc phục được sự cố chưa? – Naveen

Trả lời

2

Như bạn có thể nhìn thấy trong daCapricorn comment sau về một vấn đề tương tự như báo cáo.

Ông đã cho thông tin chi tiết về các giải pháp khả thi:

Set android: layout_alignParentBottom = "true" và android: layout_alignParentLeft = "true" trong xml và tính marginBottom và marginLeft (họ nên được tiêu cực) lập trình. marginBottom = (chiều cao trung tâm của ArcMenu chiều cao)/2, marginLeft = (chiều rộng của ArcMenu - chiều rộng của centerIcon)/2.

Ý tưởng chính ở đây là đặt lề mong muốn thành giá trị âm (trường hợp của tôi ở dưới cùng bên phải). Tôi đã quản lý để giải quyết điều này bằng cách tính lề mong muốn marginBottom = - ((chiều cao của chiều cao trung tâm của ArcMenu)/2), marginRight = - ((chiều rộng của ArcMenu - chiều rộng của centerIcon)/2).

Tôi không làm điều này bên trong onMeasure tại mã thư viện của ArcLayout.java, tôi đã làm như sau trong hoạt động của mình.

Trong bố trí hoạt động của tôi thiết lập các layout_alignParent như mong muốn:

<?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> 

Trong hoạt động của tôi:

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); 
     } 
    } 
}; 

onCreate của tôi:

@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); 
        } 
       }); 
    } 

Tôi thử nghiệm này trên nhiều thiết bị và nó hoạt động tốt vì tính toán là động.

Hy vọng điều này sẽ giúp tận hưởng tiện ích tuyệt vời từ anh chàng này daCapricorn

+0

crossWidth và crossHeight là gì? – lorraine

+0

Tôi đã nhận nó, controlLayoutWidth và controlLayoutHeight của nó. Và một trong những bạn nên được chỉ định margin tiêu cực không phải là bên phải, nhưng bên trái, như ông đề cập ở đây: https://github.com/daCapricorn/ArcMenu/issues/9 – lorraine

+0

Sử dụng mã này thay đổi không có gì cho tôi. Nếu tôi đặt căn chỉnh về phía dưới và căn chỉnh sang phải, dấu + vẫn không ở trong góc. – Nestor

Các vấn đề liên quan