android coverflow without gallery [closed]

2019-07-31 08:13发布

Hello I have been searching for cover flow android that DOES NOT use gallery . Please don't offer solution that uses gallery such as fancyflow or neil davis because they are using Gallery and its being predicated

Is there something like that at all ?

1条回答
手持菜刀,她持情操
2楼-- · 2019-07-31 08:45

CoverFlowView.java

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class CoverFlowView extends LinearLayout {
public static class Config {
    public int COVER_SPACING = 60;
    public int CENTER_COVER_OFFSET = 130;
    public float SIDE_COVER_ANGLE = 40;
    public int SIDE_COVER_ZPOSITION = 120;
    public float REFLECTION_FRACTION = 0.15f;
    public long FOCUS_ANIMATION_DURATION = 200;
    public int COVER_BUFFER = 6;
    public long BLUR_ANIMATION_DURATION = 120;
    public int DROP_SHADOW_RADIUS = 15;
    public boolean HORIZONTAL_SCROLLBAR_ENABLED = false;
    public boolean FADING_EDGES_ENABLED = true;
    public float IMAGE_SCALE_X = 1;
    public float IMAGE_SCALE_Y = 1;
    public long LONG_CLICK_DURATION = 2000;
}

Config mConfig = new Config();
WeakReference<DataSource> mDataSource;
WeakReference<Listener> mListener;
Set<CoverFlowItem> mOffscreenCovers = new HashSet<CoverFlowItem>();
Map<Integer, CoverFlowItem> mOnscreenCovers = new HashMap<Integer, CoverFlowItem>();
Map<Integer, Bitmap> mCoverImages = new HashMap<Integer, Bitmap>();
Map<Integer, Integer> mCoverImageHeights = new HashMap<Integer, Integer>();
Bitmap mDefaultBitmap;
int mDefaultBitmapHeight;
float mDefaultImageHeight;
ScrollView mScrollView;
ViewGroup mItemContainer;
Thread mLongClickThread;
boolean mCancelNextClick;

int mLowerVisibleCover = -1;
int mUpperVisibleCover = -1;
int mNumberOfImages;
int mBeginningCover;
CoverFlowItem mSelectedCoverView = null;

int mHalfScreenHeight;
int mHalfScreenWidth;

boolean mIsSingleTap;
boolean mIsDraggingCover;
float mStartScrollX;
float mStartX;

SortedSet<Integer> mTouchedCovers = new TreeSet<Integer>();

public CoverFlowView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs);
    setUpInitialState();
}

public CoverFlowView(Context context, AttributeSet attrs) {
    super(context, attrs);
    setUpInitialState();
}

public CoverFlowView(Context context) {
    super(context);
    setUpInitialState();
}

public Config getConfig() {
    return mConfig;
}

void setUpInitialState() {

    // Create the scrollView
    mScrollView = new ScrollView(getContext()) {
        // Catch trackball events
        @Override
        public boolean onTrackballEvent(MotionEvent event) {
            return CoverFlowView.this.onTrackballEvent(event);
        }

    };
    mScrollView.setOnTouchListener(new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            return CoverFlowView.this.onTouchEvent(event);
        }
    });
    ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
            LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
    mScrollView.setLayoutParams(params);
    mScrollView
            .setHorizontalScrollBarEnabled(mConfig.HORIZONTAL_SCROLLBAR_ENABLED);
    mScrollView
            .setHorizontalFadingEdgeEnabled(mConfig.FADING_EDGES_ENABLED);
    addView(mScrollView);

    // Create an intermediate LinearLayout
    LinearLayout linearLayout = new LinearLayout(getContext());
    mScrollView.addView(linearLayout);

    // Create the item container
    mItemContainer = new FrameLayout(getContext());
    linearLayout.addView(mItemContainer);

}

CoverFlowItem coverForIndex(int coverIndex) {
    CoverFlowItem coverItem = dequeueReusableCover();
    if (null == coverItem) {
        coverItem = new CoverFlowItem(getContext());
        coverItem.setScaleType(ImageView.ScaleType.FIT_XY);
        coverItem.setScaleX(mConfig.IMAGE_SCALE_X);
        coverItem.setScaleY(mConfig.IMAGE_SCALE_Y);
        coverItem.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                onTouchItem((CoverFlowItem) v, event);
                return false;
            }
        });
    }
    coverItem.setNumber(coverIndex);
    return coverItem;
}

void updateCoverBitmap(CoverFlowItem cover) {
    int coverNumber = cover.getNumber();
    Bitmap bitmap = mCoverImages.get(coverNumber);
    if (null != bitmap) {
        Integer coverImageHeight = mCoverImageHeights.get(coverNumber);
        if (null != coverImageHeight)
            cover.setImageBitmap(bitmap, coverImageHeight,
                    mConfig.REFLECTION_FRACTION);
    } else {
        cover.setImageBitmap(mDefaultBitmap, mDefaultBitmapHeight,
                mConfig.REFLECTION_FRACTION);
        mDataSource.get().requestBitmapForIndex(this, coverNumber);
    }
}

void layoutCover(CoverFlowItem cover, int selectedCover, boolean animated) {
    if (null == cover)
        return;

    int coverNumber = cover.getNumber();
    int newX = mHalfScreenWidth + cover.getNumber() * mConfig.COVER_SPACING
            - (int) (cover.getCoverWidth() / 2.0f);
    int newY = mHalfScreenHeight - cover.getCoverHeight() / 2;

    ItemAnimation oldAnimation = (ItemAnimation) cover.getAnimation();
    float oldAngle = oldAnimation != null ? oldAnimation
            .getStopAngleDegrees() : 0;
    int oldZOffset = oldAnimation != null ? oldAnimation.getStopZOffset()
            : 0;
    int oldXOffset = oldAnimation != null ? oldAnimation.getStopXOffset()
            : 0;

    ItemAnimation anim = null;

    if (coverNumber < selectedCover) {
        if (oldAngle != mConfig.SIDE_COVER_ANGLE
                || oldXOffset != -mConfig.CENTER_COVER_OFFSET
                || oldZOffset != mConfig.SIDE_COVER_ZPOSITION) {
            anim = new ItemAnimation();
            anim.setRotation(oldAngle, mConfig.SIDE_COVER_ANGLE);
            anim.setViewDimensions(cover.getCoverWidth(),
                    cover.getOriginalCoverHeight());
            anim.setXTranslation(oldXOffset, -mConfig.CENTER_COVER_OFFSET);
            anim.setZTranslation(oldZOffset, mConfig.SIDE_COVER_ZPOSITION);
            if (animated)
                anim.setDuration(mConfig.BLUR_ANIMATION_DURATION);
            else
                anim.setStatic();
        }
    } else if (coverNumber > selectedCover) {
        if (oldAngle != -mConfig.SIDE_COVER_ANGLE
                || oldXOffset != mConfig.CENTER_COVER_OFFSET
                || oldZOffset != mConfig.SIDE_COVER_ZPOSITION) {
            anim = new ItemAnimation();
            anim.setRotation(oldAngle, -mConfig.SIDE_COVER_ANGLE);
            anim.setViewDimensions(cover.getCoverWidth(),
                    cover.getOriginalCoverHeight());
            anim.setXTranslation(oldXOffset, mConfig.CENTER_COVER_OFFSET);
            anim.setZTranslation(oldZOffset, mConfig.SIDE_COVER_ZPOSITION);
            if (animated)
                anim.setDuration(mConfig.BLUR_ANIMATION_DURATION);

            else
                anim.setStatic();
        }
    } else {
        if (oldAngle != 0 || oldXOffset != 0 || oldZOffset != 0) {
            anim = new ItemAnimation();
            anim.setRotation(oldAngle, 0);
            anim.setViewDimensions(cover.getCoverWidth(),
                    cover.getOriginalCoverHeight());
            anim.setXTranslation(oldXOffset, 0);
            anim.setZTranslation(oldZOffset, 0);
            if (animated)
                anim.setDuration(mConfig.FOCUS_ANIMATION_DURATION);
            else
                anim.setStatic();
            anim.setAnimationListener(new Animation.AnimationListener() {
                public void onAnimationStart(Animation animation) {
                }

                public void onAnimationRepeat(Animation animation) {
                }

                public void onAnimationEnd(Animation animation) {
                    mSelectedCoverView.bringToFront();
                    layoutZ(mSelectedCoverView.getNumber(),
                            mLowerVisibleCover, mUpperVisibleCover);
                }
            });
        }
    }

    FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
            cover.getLayoutParams());
    params.setMargins(newX, newY, 0, 0);
    params.gravity = Gravity.LEFT | Gravity.TOP;
    cover.setLayoutParams(params);

    if (null != anim)
        cover.startAnimation(anim);
}

void layoutCovers(int selected, int lowerBound, int upperBound) {
    CoverFlowItem cover;

    for (int i = lowerBound; i <= upperBound; i++) {
        cover = mOnscreenCovers.get(i);
        layoutCover(cover, selected, true);
    }
}

void layoutZ(int selected, int lowerBound, int upperBound) {
    CoverFlowItem cover;
    for (int i = upperBound; i > selected; i--) {
        cover = mOnscreenCovers.get(i);
        if (null != cover)
            mItemContainer.bringChildToFront(cover);
    }
    for (int i = lowerBound; i <= selected; i++) {
        cover = mOnscreenCovers.get(i);
        if (null != cover)
            mItemContainer.bringChildToFront(cover);
    }

}

CoverFlowItem dequeueReusableCover() {
    CoverFlowItem item = null;
    if (!mOffscreenCovers.isEmpty()) {
        item = mOffscreenCovers.iterator().next();
        mOffscreenCovers.remove(item);
    }
    return item;
}

public void setBitmapForIndex(Bitmap bitmap, int index) {
    Bitmap bitmapWithReflection = CoverFlowItem
            .createReflectedBitmap(bitmap, mConfig.REFLECTION_FRACTION,
                    mConfig.DROP_SHADOW_RADIUS);
    setReflectedBitmapForIndex(bitmapWithReflection, index);
}

public void setReflectedBitmapForIndex(Bitmap bitmapWithReflection,
        int index) {
    mCoverImages.put(index, bitmapWithReflection);
    int originalHeight = (int) ((int) (bitmapWithReflection.getHeight() - 2 * mConfig.DROP_SHADOW_RADIUS) / (1 + mConfig.REFLECTION_FRACTION));
    mCoverImageHeights.put(index, originalHeight);

    // If this cover is onscreen, set its image and call layoutCover.
    CoverFlowItem cover = mOnscreenCovers.get(index);
    if (null != cover) {
        cover.setImageBitmap(bitmapWithReflection, originalHeight,
                mConfig.REFLECTION_FRACTION);
        layoutCover(cover, mSelectedCoverView.getNumber(), false);
    }
}

public Bitmap[] getReflectedBitmaps() {
    Bitmap[] result = new Bitmap[mCoverImages.size()];
    for (int i = 0; i < result.length; i++)
        result[i] = mCoverImages.get(i);
    return result;
}

//
// @Override
// protected void onLayout(boolean changed, int l, int t, int r, int b) {
// mScrollView.layout(l, t, r, b);
// }
//
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    ViewGroup.LayoutParams params = new LinearLayout.LayoutParams(
            mNumberOfImages * mConfig.COVER_SPACING
                    + MeasureSpec.getSize(widthMeasureSpec),
            LayoutParams.FILL_PARENT);
    mItemContainer.setLayoutParams(params);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mHalfScreenWidth = w / 2;
    mHalfScreenHeight = h / 2;

    int lowerBound = Math.max(-1,
            (mSelectedCoverView != null ? mSelectedCoverView.getNumber()
                    : 0) - mConfig.COVER_BUFFER);
    int upperBound = Math.min(mNumberOfImages - 1,
            (mSelectedCoverView != null ? mSelectedCoverView.getNumber()
                    : 0) + mConfig.COVER_BUFFER);
    layoutCovers(
            mSelectedCoverView != null ? mSelectedCoverView.getNumber() : 0,
            lowerBound, upperBound);

    centerOnSelectedCover(false);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    try {
        switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:
            mIsSingleTap = event.getPointerCount() == 1;
            final int index = mSelectedCoverView.getNumber();
            if (mIsSingleTap) {
                mStartX = event.getX(0);

                int lowest = mTouchedCovers.first();
                int highest = mTouchedCovers.last();

                if (lowest <= mSelectedCoverView.getNumber()
                        && highest >= mSelectedCoverView.getNumber()
                        && null != mListener && null != mListener.get()
                        && null == mLongClickThread) {
                    mLongClickThread = new Thread(new Runnable() {
                        public void run() {
                            try {
                                Thread.sleep(getConfig().LONG_CLICK_DURATION);
                                post(new Runnable() {

                                    public void run() {
                                        mListener.get()
                                                .onSelectionLongClicked(
                                                        CoverFlowView.this,
                                                        index);
                                        mCancelNextClick = true;
                                    }
                                });
                            } catch (InterruptedException e) {
                            }

                        }
                    });
                    mLongClickThread.start();
                    mCancelNextClick = false;

                }

            }

            mBeginningCover = mSelectedCoverView.getNumber();
            mStartScrollX = event.getX(0) + mScrollView.getScrollX();
            break;
        case MotionEvent.ACTION_MOVE:
            int scrollOffset = (int) (mStartScrollX - event.getX(0));
            int xOffset = (int) Math.abs(event.getX(0) - mStartX);

            // If finger moves too much, not a single tap anymore:
            mIsSingleTap = mIsSingleTap && (xOffset < 20);

            if (!mIsSingleTap) {
                // Cancel long click
                if (null != mLongClickThread
                        && Thread.State.TERMINATED != mLongClickThread
                                .getState()) {
                    mLongClickThread.interrupt();
                    mLongClickThread = null;
                }

                // Update the scroll position
                mScrollView
                        .scrollTo(scrollOffset, mScrollView.getScrollY());

                // Select new cover
                int newCover = scrollOffset / mConfig.COVER_SPACING;

                // make sure we're not out of bounds:
                if (newCover < 0)
                    newCover = 0;
                else if (newCover >= mNumberOfImages)
                    newCover = mNumberOfImages - 1;

                // Select newCover if appropriate
                if (newCover != mSelectedCoverView.getNumber()) {
                    setSelectedCover(newCover);
                    // Notify listener
                    if (null != mListener && null != mListener.get())
                        mListener.get().onSelectionChanging(this,
                                mSelectedCoverView.getNumber());
                }
            }

            break;
        case MotionEvent.ACTION_UP:

            // Cancel long click
            if (null != mLongClickThread) {
                if (Thread.State.TERMINATED != mLongClickThread.getState())
                    mLongClickThread.interrupt();
                mLongClickThread = null;
            }

            if (mIsSingleTap && 0 < mTouchedCovers.size()) {
                int lowest = mTouchedCovers.first();
                int highest = mTouchedCovers.last();
                if (mSelectedCoverView.getNumber() < lowest)
                    setSelectedCover(lowest);
                else if (mSelectedCoverView.getNumber() > highest)
                    setSelectedCover(highest);
                else if (lowest <= mSelectedCoverView.getNumber()
                        && highest >= mSelectedCoverView.getNumber()
                        && null != mListener && null != mListener.get()) {
                    if (!mCancelNextClick) {
                        mListener.get().onSelectionClicked(this,
                                mSelectedCoverView.getNumber());
                    }
                }

            }

            mCancelNextClick = false;

            // Smooth scroll to the center of the cover
            mScrollView.smoothScrollTo(mSelectedCoverView.getNumber()
                    * mConfig.COVER_SPACING, mScrollView.getScrollY());

            if (mBeginningCover != mSelectedCoverView.getNumber()) {
                // Notify listener
                if (null != mListener && null != mListener.get())
                    mListener.get().onSelectionChanged(this,
                            mSelectedCoverView.getNumber());
            }

            // Clear touched covers
            mTouchedCovers.clear();

            break;
        }
    } catch (Exception e) {

    }

    return true;
}

@Override
public boolean onTrackballEvent(MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_MOVE:
        int newCover = -1;
        if (event.getX(0) > 0)
            newCover = mSelectedCoverView.getNumber() + 1;
        else if (event.getX(0) < 0)
            newCover = mSelectedCoverView.getNumber() - 1;

        if (0 <= newCover && mNumberOfImages > newCover
                && mSelectedCoverView.getNumber() != newCover) {
            setSelectedCover(newCover);
            mScrollView.smoothScrollTo(newCover * mConfig.COVER_SPACING,
                    mScrollView.getScrollY());
            // Notify listener
            if (null != mListener && null != mListener.get())
                mListener.get().onSelectionChanged(this,
                        mSelectedCoverView.getNumber());

        }
        break;
    }
    return true;
}

void onTouchItem(CoverFlowItem cover, MotionEvent event) {
    mTouchedCovers.add(cover.getNumber());
}

public void clear() {
    mNumberOfImages = 0;
    mSelectedCoverView = null;
    mOffscreenCovers.clear();
    mOnscreenCovers.clear();
    mCoverImages.clear();
    mCoverImageHeights.clear();
    mDefaultBitmap = null;
    mLowerVisibleCover = -1;
    mUpperVisibleCover = -1;

    // Recreate the item container to force free memory
    LinearLayout parent = (LinearLayout) mItemContainer.getParent();
    parent.removeView(mItemContainer);
    mItemContainer = new FrameLayout(getContext());
    parent.addView(mItemContainer);

}

public void setNumberOfImages(int numberOfImages) {
    mNumberOfImages = numberOfImages;

    int lowerBound = Math.max(-1,
            (mSelectedCoverView != null ? mSelectedCoverView.getNumber()
                    : 0) - mConfig.COVER_BUFFER);
    int upperBound = Math.min(mNumberOfImages - 1,
            (mSelectedCoverView != null ? mSelectedCoverView.getNumber()
                    : 0) + mConfig.COVER_BUFFER);
    if (null != mSelectedCoverView)
        layoutCovers(mSelectedCoverView.getNumber(), lowerBound, upperBound);
    else
        setSelectedCover(0);

    centerOnSelectedCover(false);
}

public void setDefaultBitmap(Bitmap bitmap) {
    mDefaultBitmapHeight = null != bitmap ? bitmap.getHeight() : 0;
    mDefaultBitmap = bitmap;
}

public void setDataSource(DataSource dataSource) {
    mDataSource = new WeakReference<DataSource>(dataSource);
    setDefaultBitmap(dataSource.defaultBitmap());
}

public void setListener(Listener listener) {
    mListener = new WeakReference<Listener>(listener);
}

public void centerOnSelectedCover(final boolean animated) {
    if (null == mSelectedCoverView)
        return;

    final int offset = mConfig.COVER_SPACING
            * mSelectedCoverView.getNumber();
    mScrollView.post(new Runnable() {
        public void run() {
            if (animated)
                mScrollView.smoothScrollTo(offset, 0);
            else
                mScrollView.scrollTo(offset, 0);
        }
    });
}

public void setSelectedCover(int newSelectedCover) {
    if (null != mSelectedCoverView
            && newSelectedCover == mSelectedCoverView.getNumber())
        return;

    if (newSelectedCover >= mNumberOfImages)
        return;

    CoverFlowItem cover;
    int newLowerBound = Math
            .max(0, newSelectedCover - mConfig.COVER_BUFFER);
    int newUpperBound = Math.min(mNumberOfImages - 1, newSelectedCover
            + mConfig.COVER_BUFFER);
    if (null == mSelectedCoverView) {
        // Allocate and display covers from newLower to newUpper bounds.
        for (int i = newLowerBound; i <= newUpperBound; i++) {
            cover = coverForIndex(i);
            mOnscreenCovers.put(i, cover);
            updateCoverBitmap(cover);
            if (i == newSelectedCover) {
                // We'll add it later
                continue;
            } else if (i < newSelectedCover) {
                mItemContainer.addView(cover);
            } else {
                mItemContainer.addView(cover, 0);
            }
            layoutCover(cover, newSelectedCover, false);
        }
        // Add the selected cover
        cover = mOnscreenCovers.get(newSelectedCover);
        mItemContainer.addView(cover);
        layoutCover(cover, newSelectedCover, false);

        mLowerVisibleCover = newLowerBound;
        mUpperVisibleCover = newUpperBound;
        mSelectedCoverView = cover;
        return;
    } else {
        layoutZ(mSelectedCoverView.getNumber(), mLowerVisibleCover,
                mUpperVisibleCover);

    }

    if ((newLowerBound > mUpperVisibleCover)
            || (newUpperBound < mLowerVisibleCover)) {
        // They do not overlap at all.
        // This does not animate--assuming it's programmatically set from
        // view controller.
        // Recycle all onscreen covers.
        for (int i = mLowerVisibleCover; i <= mUpperVisibleCover; i++) {
            cover = mOnscreenCovers.get(i);
            mOffscreenCovers.add(cover);
            mItemContainer.removeView(cover);
            mOnscreenCovers.remove(i);
        }

        // Move all available covers to new location.
        for (int i = newLowerBound; i <= newUpperBound; i++) {
            cover = coverForIndex(i);
            mOnscreenCovers.put(i, cover);
            updateCoverBitmap(cover);
            if (i == newSelectedCover) {
                // We'll add it later
                continue;
            } else if (i < newSelectedCover) {
                mItemContainer.addView(cover);
            } else {
                mItemContainer.addView(cover, 0);
            }
        }
        cover = mOnscreenCovers.get(newSelectedCover);
        mItemContainer.addView(cover);

        mLowerVisibleCover = newLowerBound;
        mUpperVisibleCover = newUpperBound;
        mSelectedCoverView = cover;
        layoutCovers(newSelectedCover, newLowerBound, newUpperBound);

        return;

    } else if (newSelectedCover > mSelectedCoverView.getNumber()) {
        // Move covers that are now out of range on the left to the right
        // side,
        // but only if appropriate (within the range set by newUpperBound).
        for (int i = mLowerVisibleCover; i < newLowerBound; i++) {
            cover = mOnscreenCovers.get(i);
            if (mUpperVisibleCover < newUpperBound) {
                // Tack it on the right side.
                mUpperVisibleCover++;
                cover.setNumber(mUpperVisibleCover);
                updateCoverBitmap(cover);
                mOnscreenCovers.put(cover.getNumber(), cover);
                layoutCover(cover, newSelectedCover, false);
            } else {
                // Recycle this cover.
                mOffscreenCovers.add(cover);
                mItemContainer.removeView(cover);
            }
            mOnscreenCovers.remove(i);
        }

        mLowerVisibleCover = newLowerBound;

        // Add in any missing covers on the right up to the newUpperBound.
        for (int i = mUpperVisibleCover + 1; i <= newUpperBound; i++) {
            cover = coverForIndex(i);
            mOnscreenCovers.put(i, cover);
            updateCoverBitmap(cover);
            mItemContainer.addView(cover, 0);
            layoutCover(cover, newSelectedCover, false);
        }
        mUpperVisibleCover = newUpperBound;
    } else {
        // Move covers that are now out of range on the right to the left
        // side,
        // but only if appropriate (within the range set by newLowerBound).
        for (int i = mUpperVisibleCover; i > newUpperBound; i--) {
            cover = mOnscreenCovers.get(i);
            if (mLowerVisibleCover > newLowerBound) {
                // Tack it on the left side.
                mLowerVisibleCover--;
                cover.setNumber(mLowerVisibleCover);
                updateCoverBitmap(cover);
                mOnscreenCovers.put(cover.getNumber(), cover);
                layoutCover(cover, newSelectedCover, false);

            } else {
                // Recycle this cover.
                mOffscreenCovers.add(cover);
                mItemContainer.removeView(cover);
            }
            mOnscreenCovers.remove(i);
        }

        mUpperVisibleCover = newUpperBound;

        // Add in any missing covers on the left down to the newLowerBound.
        for (int i = mLowerVisibleCover - 1; i >= newLowerBound; i--) {
            cover = coverForIndex(i);
            mOnscreenCovers.put(i, cover);
            updateCoverBitmap(cover);
            mItemContainer.addView(cover, 0);
            layoutCover(cover, newSelectedCover, false);
        }

        mLowerVisibleCover = newLowerBound;
    }

    if (mSelectedCoverView.getNumber() > newSelectedCover) {
        layoutCovers(newSelectedCover, newSelectedCover,
                mSelectedCoverView.getNumber());
    } else if (newSelectedCover > mSelectedCoverView.getNumber()) {
        layoutCovers(newSelectedCover, mSelectedCoverView.getNumber(),
                newSelectedCover);
    }

    mSelectedCoverView = mOnscreenCovers.get(newSelectedCover);

}

private static class ScrollView extends HorizontalScrollView {

    public ScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public ScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollView(Context context) {
        super(context);
    }

}

public interface DataSource {
    public void requestBitmapForIndex(CoverFlowView coverFlow, int index);

    public Bitmap defaultBitmap();
}

public interface Listener {
    public void onSelectionChanging(CoverFlowView coverFlow, int index);

    public void onSelectionChanged(CoverFlowView coverFlow, int index);

    public void onSelectionClicked(CoverFlowView coverFlow, int index);

    public void onSelectionLongClicked(CoverFlowView coverFlow, int index);
}

public static class ItemAnimation extends Animation {
    private int mViewWidth;
    private int mViewHeight;
    private int mStartZOffset;
    private int mStopZOffset;
    private int mStartXOffset;
    private int mStopXOffset;
    private float mStopAngleDegrees = 0;
    // private double mStopAngleRadians = 0;
    private float mStartAngleDegrees = 0;
    private boolean mStatic = false;

    // private double mStartAngleRadians = 0;

    public ItemAnimation() {
        super();
        setFillAfter(true);
        setFillBefore(true);
    }

    public void setStatic() {
        mStatic = true;
        setDuration(0);
    }

    public void setRotation(float start, float stop) {
        mStartAngleDegrees = start;
        mStopAngleDegrees = stop;
    }

    public void setXTranslation(int start, int stop) {
        mStartXOffset = start;
        mStopXOffset = stop;
    }

    public void setZTranslation(int start, int stop) {
        mStartZOffset = start;
        mStopZOffset = stop;
    }

    public void setViewDimensions(int width, int height) {
        mViewWidth = width;
        mViewHeight = height;
    }

    public float getStopAngleDegrees() {
        return mStopAngleDegrees;
    }

    public float getStartAngleDegrees() {
        return mStartAngleDegrees;
    }

    public int getStartXOffset() {
        return mStartXOffset;
    }

    public int getStopXOffset() {
        return mStopXOffset;
    }

    public int getStopZOffset() {
        return mStopZOffset;
    }

    @Override
    protected void applyTransformation(float interpolatedTime,
            Transformation t) {
        t.setTransformationType(mStatic ? Transformation.TYPE_BOTH
                : Transformation.TYPE_MATRIX);

        if (mStatic)
            t.setAlpha(interpolatedTime < 1.0f ? 0 : 1);

        float angleDegrees = mStartAngleDegrees + interpolatedTime
                * (mStopAngleDegrees - mStartAngleDegrees);
        float zOffset = mStartZOffset + interpolatedTime
                * (mStopZOffset - mStartZOffset);
        int xOffset = mStartXOffset
                + (int) (interpolatedTime * (mStopXOffset - mStartXOffset));
        Matrix m = new Matrix();
        Camera camera = new Camera();
        camera.translate(0, 0, zOffset);

        camera.rotateY(angleDegrees);

        camera.getMatrix(m);
        m.preTranslate(-(mViewWidth / 2), -(mViewHeight / 2));
        m.postTranslate((mViewWidth / 2) + xOffset, (mViewHeight / 2));

        t.getMatrix().set(m);
        super.applyTransformation(interpolatedTime, t);
    }

}
 }

you can use this class

in your activity`s layout file ( main_layout.xml)

  <your.packageName.CoverFlowView
    android:id="@+id/coverflow"
    android:layout_width="fill_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white" />

in MainActivity,java

    private CoverFlowView mCoverflow;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);

    // Find the coverflow
    mCoverflow = (CoverFlowView) findViewById(R.id.coverflow);


}
查看更多
登录 后发表回答