安卓系统:动画可以在KitKat和LolliPop上使用,但不能在其他API版本上使用



我必须构建这样的动画。对不起,我没有太多的声誉上传图片。你可以从上面的链接找到gif文件。我已经做了所有这些,它只适用于KitKat和LollyPop,但不适用于其他API版本。我正在使用这个图书馆。谁能算出实际的问题吗这是我的密码。提前感谢

public abstract class AbstractSlideExpandableListAdapter extends WrapperListAdapterImpl

private View lastOpnUpperView = null;
ArrayList<View> upperViewsList = new ArrayList<View>();
ArrayList<View> lowerViewsList = new ArrayList<View>();
ArrayList<View> circleViewsList = new ArrayList<View>();

private View lastOpen = null;
private int lastOpenPosition = -1;
private int lastOpenItemIndex = 0;
private int animationDuration = 800;

private BitSet openItems = new BitSet();

private final SparseIntArray viewHeights = new SparseIntArray(10);

private ViewGroup parent;
public AbstractSlideExpandableListAdapter(ListAdapter wrapped)
{
    super(wrapped);
    lastOpenPosition = 0;
    openItems.set(lastOpenPosition, true);
}
private OnItemExpandCollapseListener expandCollapseListener;

public void setItemExpandCollapseListener(OnItemExpandCollapseListener listener)
{
    expandCollapseListener = listener;
}
public void removeItemExpandCollapseListener()
{
    expandCollapseListener = null;
}

public interface OnItemExpandCollapseListener
{
    public void onExpand(View itemView, int position);

    public void onCollapse(View itemView, int position);
}
private void notifiyExpandCollapseListener(int type, View view, int position)
{
    if (expandCollapseListener != null)
    {
        if (type == ExpandCollapseAnimation.EXPAND)
        {
            expandCollapseListener.onExpand(view, position);
        }
        else if (type == ExpandCollapseAnimation.COLLAPSE)
        {
            expandCollapseListener.onCollapse(view, position);
        }
    }
}
@Override
public View getView(int position, View view, ViewGroup viewGroup)
{
    this.parent = viewGroup;
    view = wrapped.getView(position, view, viewGroup);
    enableFor(view, position);
    return view;
}

public abstract View getExpandToggleButton(View parent);
public abstract View getExpandableView(View parent);
// upperView to expand animation for sequeeze
public abstract View getUpperView(View upperView);
// Lower view to expand and collapse
public abstract View getLowerView(View upperView);
// Get the circle view to hide and show
public abstract View getCircleView(View circleView);
/**
 * Gets the duration of the collapse animation in ms. Default is 330ms. Override this method to change the default.
 * 
 * @return the duration of the anim in ms
 */
public int getAnimationDuration()
{
    return animationDuration;
}
/**
 * Set's the Animation duration for the Expandable animation
 * 
 * @param duration
 *            The duration as an integer in MS (duration > 0)
 * @exception IllegalArgumentException
 *                if parameter is less than zero
 */
public void setAnimationDuration(int duration)
{
    if (duration < 0)
    {
        throw new IllegalArgumentException("Duration is less than zero");
    }
    animationDuration = duration;
}
/**
 * Check's if any position is currently Expanded To collapse the open item @see collapseLastOpen
 * 
 * @return boolean True if there is currently an item expanded, otherwise false
 */
public boolean isAnyItemExpanded()
{
    return (lastOpenPosition != -1) ? true : false;
}
public void enableFor(View parent, int position)
{
    View more = getExpandToggleButton(parent);
    View itemToolbar = getExpandableView(parent);
    View upperView = getUpperView(parent);
    View circleView = getCircleView(parent);
    View lowerView = getLowerView(parent);
    itemToolbar.measure(parent.getWidth(), parent.getHeight());
    upperViewsList.add(upperView);
    circleViewsList.add(circleView);
    lowerViewsList.add(lowerView);
    if (position == 0)
    {
        // lastopenUpperViewTemporary = upperView;
        lastOpnUpperView = upperView;
        upperView.setVisibility(View.GONE);
        lowerView.setVisibility(View.GONE);
    }
    enableFor(more, upperView, itemToolbar, position);
    itemToolbar.requestLayout();
}
private void animateListExpand(final View button, final View target, final int position)
{
    target.setAnimation(null);
    int type;
    if (target.getVisibility() == View.VISIBLE)
    {
        type = ExpandCollapseAnimation.COLLAPSE;
    }
    else
    {
        type = ExpandCollapseAnimation.EXPAND;
    }
    // remember the state
    if (type == ExpandCollapseAnimation.EXPAND)
    {
        openItems.set(position, true);
    }
    else
    {
        openItems.set(position, false);
    }
    // check if we need to collapse a different view
    if (type == ExpandCollapseAnimation.EXPAND)
    {
        if (lastOpenPosition != -1 && lastOpenPosition != position)
        {
            if (lastOpen != null)
            {
                animateWithUpperView(lastOpen, ExpandCollapseAnimation.COLLAPSE, position);
                // animateView(lastOpen, ExpandCollapseAnimation.COLLAPSE);
                notifiyExpandCollapseListener(ExpandCollapseAnimation.COLLAPSE, lastOpen, lastOpenPosition);
            }
            openItems.set(lastOpenPosition, false);
        }
        lastOpen = target;
        lastOpenPosition = position;
    }
    else if (lastOpenPosition == position)
    {
        lastOpenPosition = -1;
    }
    // animateView(target, type);
    // Expand the view which was collapse
    Animation anim = new ExpandCollapseAnimation(target, type);
    anim.setDuration(getAnimationDuration());
    target.startAnimation(anim);
    this.notifiyExpandCollapseListener(type, target, position);
    // }
}
private void enableFor(final View button, final View upperView, final View target, final int position)
{
    // lastopenUpperViewTemporary = upperView;
    if (target == lastOpen && position != lastOpenPosition)
    {
        // lastOpen is recycled, so its reference is false
        lastOpen = null;
    }
    if (position == lastOpenPosition)
    {
        // re reference to the last view
        // so when can animate it when collapsed
        // lastOpen = target;
        lastOpen = target;
        lastOpnUpperView = upperView;
    }
    int height = viewHeights.get(position, -1);
    if (height == -1)
    {
        viewHeights.put(position, target.getMeasuredHeight());
        updateExpandable(target, position);
    }
    else
    {
        updateExpandable(target, position);
    }
    button.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(final View view)
        {
            System.out.println("Position: " + position);
            if (lastOpenPosition == position)
            {
                return;
            }
            System.out.println("Upper View: " + upperView);
            Animation anim = new ExpandCollapseUpperViewAnimation(upperViewsList.get(position), ExpandCollapseUpperViewAnimation.COLLAPSE);
            anim.setDuration(800);
            anim.setAnimationListener(new AnimationListener()
            {
                @Override
                public void onAnimationStart(Animation animation)
                {
                    circleViewsList.get(position).setVisibility(View.GONE);
                }
                @Override
                public void onAnimationRepeat(Animation animation)
                {
                    // TODO Auto-generated method stub
                }
                @Override
                public void onAnimationEnd(Animation animation)
                {
                    // TODO Auto-generated method stub
                    // upperViewsList.get(position).setVisibility(View.VISIBLE);
                    animateListExpand(button, target, position);
                }
            });
            upperViewsList.get(position).startAnimation(anim);
            // Lower animation
            Animation lowerAnim = new ExpandCollapseUpperViewAnimation(lowerViewsList.get(position), ExpandCollapseUpperViewAnimation.COLLAPSE);
            lowerAnim.setDuration(800);
            lowerViewsList.get(position).startAnimation(lowerAnim);
        }
    });
}
private void updateExpandable(View target, int position)
{
    final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) target.getLayoutParams();
    if (openItems.get(position))
    {
        target.setVisibility(View.VISIBLE);
        params.bottomMargin = 0;
    }
    else
    {
        target.setVisibility(View.GONE);
        params.bottomMargin = 0 - viewHeights.get(position);
    }
}
/**
 * Performs either COLLAPSE or EXPAND animation on the target view
 * 
 * @param target
 *            the view to animate
 * @param type
 *            the animation type, either ExpandCollapseAnimation.COLLAPSE or ExpandCollapseAnimation.EXPAND
 */
private void animateView(final View target, final int type)
{
    Animation anim = new ExpandCollapseAnimation(target, type);
    anim.setDuration(getAnimationDuration());
    anim.setAnimationListener(new AnimationListener()
    {
        @Override
        public void onAnimationStart(Animation animation)
        {
        }
        @Override
        public void onAnimationRepeat(Animation animation)
        {
        }
        @Override
        public void onAnimationEnd(Animation animation)
        {
            System.out.println("Animation End");
            if (type == ExpandCollapseAnimation.EXPAND)
            {
                if (parent instanceof ListView)
                {
                    ListView listView = (ListView) parent;
                    int movement = target.getBottom();
                    Rect r = new Rect();
                    boolean visible = target.getGlobalVisibleRect(r);
                    Rect r2 = new Rect();
                    listView.getGlobalVisibleRect(r2);
                    if (!visible)
                    {
                        listView.smoothScrollBy(movement, getAnimationDuration());
                    }
                    else
                    {
                        if (r2.bottom == r.bottom)
                        {
                            listView.smoothScrollBy(movement, getAnimationDuration());
                        }
                    }
                }
            }
        }
    });
    target.startAnimation(anim);
}
private void animateWithUpperView(final View target, final int type, final int position)
{
    Animation anim = new ExpandCollapseAnimation(target, type);
    anim.setDuration(getAnimationDuration());
    anim.setAnimationListener(new AnimationListener()
    {
        @Override
        public void onAnimationStart(Animation animation)
        {
        }
        @Override
        public void onAnimationRepeat(Animation animation)
        {
        }
        @Override
        public void onAnimationEnd(Animation animation)
        {
            // upperViewsList.get(lastOpenItemForUpperView).setVisibility(View.VISIBLE);
            // lastOpenItemForUpperView = position;
            Animation expandItemAniamtion = new ExpandCollapseLowerViewAnimation(upperViewsList.get(lastOpenItemIndex), ExpandCollapseUpperViewAnimation.EXPAND);
            expandItemAniamtion.setDuration(800);
            expandItemAniamtion.setAnimationListener(new AnimationListener()
            {
                @Override
                public void onAnimationStart(Animation animation)
                {
                }
                @Override
                public void onAnimationRepeat(Animation animation)
                {
                    // TODO Auto-generated method stub
                }
                @Override
                public void onAnimationEnd(Animation animation)
                {
                    circleViewsList.get(lastOpenItemIndex).setVisibility(View.VISIBLE);
                    lastOpenItemIndex = position;
                }
            });
            // Lower view animation
            Animation lowerAnim = new ExpandCollapseLowerViewAnimation(lowerViewsList.get(lastOpenItemIndex), ExpandCollapseUpperViewAnimation.EXPAND);
            lowerAnim.setDuration(800);
            upperViewsList.get(lastOpenItemIndex).startAnimation(expandItemAniamtion);
            lowerViewsList.get(lastOpenItemIndex).startAnimation(lowerAnim);
        }
    });
    target.startAnimation(anim);
}
/**
 * Closes the current open item. If it is current visible it will be closed with an animation.
 * 
 * @return true if an item was closed, false otherwise
 */
public boolean collapseLastOpen()
{
    if (isAnyItemExpanded())
    {
        // if visible animate it out
        if (lastOpen != null)
        {
            animateView(lastOpen, ExpandCollapseAnimation.COLLAPSE);
        }
        openItems.set(lastOpenPosition, false);
        lastOpenPosition = -1;
        return true;
    }
    return false;
}
public Parcelable onSaveInstanceState(Parcelable parcelable)
{
    SavedState ss = new SavedState(parcelable);
    ss.lastOpenPosition = this.lastOpenPosition;
    ss.openItems = this.openItems;
    return ss;
}
public void onRestoreInstanceState(SavedState state)
{
    if (state != null)
    {
        this.lastOpenPosition = state.lastOpenPosition;
        this.openItems = state.openItems;
    }
}
/**
 * Utility methods to read and write a bitset from and to a Parcel
 */
private static BitSet readBitSet(Parcel src)
{
    BitSet set = new BitSet();
    if (src == null)
    {
        return set;
    }
    int cardinality = src.readInt();
    for (int i = 0; i < cardinality; i++)
    {
        set.set(src.readInt());
    }
    return set;
}
private static void writeBitSet(Parcel dest, BitSet set)
{
    int nextSetBit = -1;
    if (dest == null || set == null)
    {
        return; // at least dont crash
    }
    dest.writeInt(set.cardinality());
    while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1)
    {
        dest.writeInt(nextSetBit);
    }
}
/**
 * The actual state class
 */
static class SavedState extends View.BaseSavedState
{
    public BitSet openItems = null;
    public int lastOpenPosition = -1;
    SavedState(Parcelable superState)
    {
        super(superState);
    }
    private SavedState(Parcel in)
    {
        super(in);
        lastOpenPosition = in.readInt();
        openItems = readBitSet(in);
    }
    @Override
    public void writeToParcel(Parcel out, int flags)
    {
        super.writeToParcel(out, flags);
        out.writeInt(lastOpenPosition);
        writeBitSet(out, openItems);
    }
    // required field that makes Parcelables from a Parcel
    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];
        }
    };
}
public static Animation ExpandOrCollapseView(final View v, final boolean expand)
{
    try
    {
        Method m = v.getClass().getDeclaredMethod("onMeasure", int.class, int.class);
        m.setAccessible(true);
        m.invoke(v, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(((View) v.getParent()).getMeasuredWidth(), MeasureSpec.AT_MOST));
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
    final int initialHeight = v.getMeasuredHeight();
    if (expand)
    {
        v.getLayoutParams().height = 0;
    }
    else
    {
        v.getLayoutParams().height = initialHeight;
    }
    v.setVisibility(View.VISIBLE);
    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t)
        {
            int newHeight = 0;
            if (expand)
            {
                newHeight = (int) (initialHeight * interpolatedTime);
            }
            else
            {
                newHeight = (int) (initialHeight * (1 - interpolatedTime));
            }
            v.getLayoutParams().height = newHeight;
            v.requestLayout();
            if (interpolatedTime == 1 && !expand)
                v.setVisibility(View.GONE);
        }
        @Override
        public boolean willChangeBounds()
        {
            return true;
        }
    };
    a.setDuration(1000);
    return a;
}}

幸运的是,我找到了解决方案。在预kitkat上,列表项上已消失的upperView不会强制设置动画,但在kitkat等上,它会强制设置从消失到可见的动画。因此,作为解决方案,我们必须在列表项和上部视图之间提供一层视图(我们必须设置动画)。这样一来,它就会像魅力一样发挥作用。

相关内容

最新更新